RE: Re: Functional Expression Meaning (was:A Functional Expression Trick)
- To: mathgroup at smc.vnet.net
- Subject: [mg24016] RE: [mg23926] Re: Functional Expression Meaning (was:[mg23859] A Functional Expression Trick)
- From: hwolf at debis.com
- Date: Tue, 20 Jun 2000 03:07:32 -0400 (EDT)
- Sender: owner-wri-mathgroup at wolfram.com
-----Original Message----- From: Allan Hayes [SMTP:hay at haystack.demon.co.uk] To: mathgroup at smc.vnet.net Sent: Friday, June 16, 2000 6:57 AM To: mathgroup at smc.vnet.net Subject: [mg23926] Re: Functional Expression Meaning (was:[mg23859] A Functional Expression Trick) Dear David and Hartmut, I have come across some problems with Hartmut's solution, toFunc, as written up by David. I offer new version, toFunc2 Hartmut's solution is toFunc::usage = "toFunc[expr] will convert an expression of pure functions into a pure function."; toFunc[expr_] := Module[{e}, Off[Pattern::patv]; Off[Function::flpar]; e = ReleaseHold[ Evaluate[ expr /. {Function[({var__} | var_), body_] :> Block[{var}, Hold[body] /. Thread[Rule[{var}, Array[Slot, {Length[{var}]}]]]], Function -> Hold}] &]; On[Pattern::patv]; On[Function::flpar]; e] I am always wary when replacement reaches inside scoping constructs like Function, With ...., because it does not respect the scoping. With toFunc we get toFunc[Function[x, With[{x = 5}, a + x^2]]] With[{#1 = 5}, a + #1\^2] &\) Also, constant functiions give trouble: toFunc[Function[{}, a + x]] Block::"lvsym": "Local variable specification \!\({\({}\)}\) contains \ \!\({}\) which is not a symbol or an assignment to a symbol." Block[{{}}, a + x /.\[InvisibleSpace]Thread[{{}} -> Array[Slot, {Length[{{}}]}]]] & Func2, below, uses the functions themselves to introduce the slots, rather than replacement. It also avoids generating messages. toFunc2[expr_] := ReleaseHold[Function @@ ({expr} /. (F_ /; F === Function)[vars_, body_] :> Apply[F[vars, Hold[body]], Slot /@ Range[Last[Dimensions[Unevaluated[{vars}]]]]] )] With this we get toFunc2[Function[x, With[{x = 5}, a + x^2]]] With[{x = 5}, a + x^2] & toFunc2[Function[{}, a + x]] a + x & ------- cut here ------- >>>>>>> Dear Allan, dear David, this is one of the threads so enjoyable when discussing, yet not so pleasing (for me) at the archive. So, Allan, thank you very much for pointing out the errors. After that, I now come up with a surprisingly simple solution toFunc[expr_] := expr /. f : Function[__] :> f[##] & That's it! And I'm convinced, that it is correct. Why? It is simply based on \[eta]-conversion, namely that Function[{vars}, f[vars]] has to be semantically the same as f. The problem with David's creditable idea to introduce this functional calculus was that the bodies of the component function had to be hold while building the resulting function, and that functions, given as lambda-expressions should be included into the calculus. My idea, to achieve that through \[alpha]-conversion (= the name of the variable must not count) however was seriously flawed: The problem is not the substitition of the variables within scoped constructs per se, but not with Slot, which shall not appear at the lhs! The solution above has a small procedural drawback: the substitution is executed at application time, i.e. possibly over and over again. But this easily can be repaired by toFunc[expr_] := ReleaseHold[Evaluate[Hold[expr] /. f : Function[__] :> f[##]] &] What has to be noted is: the execution order of the component functions is not the same as when traversing the held expression depth first, but if I'm not wrong, _Mathematica_ does not give any garanties for that anyhow (when reshuffling into canonical order occurs at intermediate steps), and certainly you should never program relying on that order (in any language). Kind regards, Hartmut