MathGroup Archive 2000

[Date Index] [Thread Index] [Author Index]

Search the Archive

RE: Re: Functional Expression Meaning (was:A Functional Expression Trick)

-----Original Message-----
From:	Allan Hayes [SMTP:hay at]
To: mathgroup at
Sent:	Friday, June 16, 2000 6:57 AM
To:	mathgroup at
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


toFunc[expr_] := Module[{e}, Off[Pattern::patv];
    e = ReleaseHold[
            expr /. {Function[({var__} | var_), body_] :>
                    Hold[body] /.
                      Thread[Rule[{var}, Array[Slot, {Length[{var}]}]]]],
                Function -> Hold}] &];

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."

        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,

  • Prev by Date: Re: I wish Descending Order Result
  • Next by Date: Re: RE:Working Precision
  • Previous by thread: Re: Functional Expression Meaning (was:A Functional Expression Trick)
  • Next by thread: Questions about RoxReduce