Re: execution model: Function vs. delayed execution
- To: mathgroup at smc.vnet.net
- Subject: [mg121342] Re: execution model: Function vs. delayed execution
- From: "Oleksandr Rasputinov" <oleksandr_rasputinov at hmamail.com>
- Date: Sun, 11 Sep 2011 07:30:00 -0400 (EDT)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- References: <j4fhvn$2gr$1@smc.vnet.net>
On Sat, 10 Sep 2011 12:34:15 +0100, Alan <alan.isaac at gmail.com> wrote:
> Warning: I am a Mathematica newbie and not a CS type, so my vocabulary
> may prove clumsy.
>
> I am used to a deferred execution model of function definition.
> Roughly, if I can write code that would be successfully executed outside
> a function definition, then I can make it a function body by
> appropriately "wrapping" it.
>
> In Mathematica, I can evaluate the following):
> x = {1,1,2}
> x=DeleteDuplicates[x]; x
> (Note: the redundancy is intentional.)
>
> Next, I attempt to "wrap" this as follows
> Clear[x]
> Function[x, (x=DeleteDuplicates[x];x)][{1,1,2}]
>
> This produces an error:
> Set::shape: "Lists {1,1,2} and {1,2} are not the same shape."
>
> Can you help me understand the execution model that leads to this?
>
> Thanks,
> Alan Isaac
>
Function employs strict lexical scoping that overrides the HoldFirst
attribute of Set:
In[1] :=
Function[x, x = DeleteDuplicates[x]; x][{1, 1, 2}] // Trace
Out[1] =
{
Function[x, x = DeleteDuplicates[x]; x][{1, 1, 2}],
{1, 1, 2} = DeleteDuplicates[{1, 1, 2}]; {1, 1, 2},
{
{
DeleteDuplicates[{1, 1, 2}],
{1, 2}
},
{1, 1, 2} = {1, 2}, (* <- this gives rise to the message *)
{
Message[Set::shape,{1, 1, 2},{1, 2}],
{Set::shape,Lists `1` and `2` are not the same shape.}
<< extra tracing omitted >>
}
}
}
this is documented via the statement,
"Function has attribute HoldAll. The function body is evaluated only after
the formal parameters have been replaced by arguments."
Using With for comparison:
In[2] :=
With[{x = {1, 1, 2}},
x = DeleteDuplicates[x]; x
]
During evaluation of In[2] :=
Set::shape: Lists {1, 1, 2} and {1, 2} are not the same shape.
Out[2] = {1, 1, 2}
This is in contrast to Block which implements dynamic scoping (or indeed
Module, whose scoping is effectively lexical, but not as directly so as
that of With or Function):
In[3] :=
Block[{x = {1, 1, 2}},
x = DeleteDuplicates[x]; x
]
Out[3] = {1, 2}