Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.

Dismiss

131 views

Skip to first unread message

Mar 8, 2010, 6:15:59 AM3/8/10

to

Hi everyone,

I have encountered a behavior which seems to me like a bug in the

implementation of the lexical scoping of either Function or RuleDelayed or

both.

Here is a toy problem: given a list where I may have some number (possibly

zero) of consecutive integers at the beginning end at the end, and some

(nonzero) number of consecutive reals in the middle, I want to

1. Deconstruct the list into these 3 groups and be able to apply some

function of my choice, taking 3 arguments, to the result.

2. Use the above to apply some arbitrary function to the reals in the

middle.

Here is my implementation:

ClearAll[deconstruct, applyToReals, applyToRealsAlt];

With[{valuePattern = {(_Integer | _Real) ..}},

deconstruct[decF_, values : valuePattern] :=

values /. {leftInts : _Integer ..., reals : _Real ..,

rightInts : _Integer ...} :>

decF[{leftInts}, {reals}, {rightInts}];

applyToReals[f_, values : {_Integer ..}] := values;

applyToReals[f_, values : valuePattern] :=

deconstruct[

Function[{leftInts, reals, rightInts},

{leftInts, f[{reals}], rightInts}], values];

applyToRealsAlt[f_, values : {_Integer ..}] := values;

applyToRealsAlt[f_, values : valuePattern] :=

deconstruct[

Function[{leftIntsLoc, realsLoc, rightIntsLoc},

{leftIntsLoc, f[{realsLoc}], rightIntsLoc}], values];

]; (* End external With *)

Note that the functions <applyToReals> and <applyToRealsAlt> only differ in

the names of variables of internal Function, so I'd expect identical

behavior for them, regardless of where they are used, if the lexical scoping

is working properly. Now please observe:

In[136]:=

test = {1, 2, 3, 3.5, 4.0, 4.5, 5, 6, 7}

Out[136]= {1, 2, 3, 3.5, 4., 4.5, 5, 6, 7}

In[139]:= applyToReals[f, test]

During evaluation of In[139]:= Function::flpar: Parameter specification

{1,2,3,3.5,4.,4.5,5,6,7} in

Function[{1,2,3,3.5,4.,4.5,5,6,7},{1,2,3,f[{3.5,4.,4.5}],5,6,7}] should be a

symbol or a list of symbols. >>

During evaluation of In[139]:= Function::flpar: Parameter specification

{1,2,3,3.5,4.,4.5,5,6,7} in

Function[{1,2,3,3.5,4.,4.5,5,6,7},{1,2,3,f[{3.5,4.,4.5}],5,6,7}] should be a

symbol or a list of symbols. >>

Out[139]=

Function[{1, 2, 3, 3.5, 4., 4.5, 5, 6, 7}, {1, 2, 3,

f[{3.5, 4., 4.5}], 5, 6, 7}][{1, 2, 3}, {3.5, 4., 4.5}, {5, 6, 7}]

In[142]:= applyToRealsAlt[f, test]

Out[142]= {{1, 2, 3}, f[{{3.5, 4., 4.5}}], {5, 6, 7}}

To me this looks like a clear case of inappropriate variable capture: the

names of variables in internal Function in <applyToReals> happen to be the

same as those used in <deconstruct> to deconstruct the list, and are

captured by Function before it binds those symbols.

In the alternative version, the names are different and everything is as

expected. But I'd expect things to work also in the first case - the fact

that they don't is an indication to me that a lexical scope is broken for

this particular use case. Tracing shows that both RuleDelayed and Function

do rename their variables, but in the same way, so the name collision still

happens - perhaps this (plus the fact that RuleDelayed does not respect the

inner scoping constructs in terms of name collisions) is the origin of the

problem?

Just to make myself clear, I am not looking for a solution to this toy

problem that would work, I just want to understand the reason for this

behavior, particularly to know whether I am missing something (perhaps using

things inappropriately) or this is indeed a bug.

Thanks in advance.

Regards,

Leonid

Mar 9, 2010, 6:21:54 AM3/9/10

to

Test sequence:

test = Flatten@{RandomInteger[{0, 1}, RandomInteger[{0, 2}]],

RandomReal[{0, 1}, RandomInteger[{1, 3}]],

RandomInteger[{0, 1}, RandomInteger[{0, 2}]]}

{1, 0.260818, 0.767116, 0}

Split into sublists:

SplitBy[test, IntegerQ]

{{1}, {0.260818, 0.767116}, {0}}

Apply a function:

f @@ SplitBy[test, IntegerQ]

f[{1}, {0.260818, 0.767116}, {0}]

Apply another function to the reals:

SplitBy[test, IntegerQ] /. x_Real :> g@x

{{1}, {g[0.260818], g[0.767116]}, {0}}

Do both, in either order:

f @@ (SplitBy[test, IntegerQ] /. x_Real :> g@x)

f[{1}, {g[0.260818], g[0.767116]}, {0}]

(f @@ SplitBy[test, IntegerQ]) /. x_Real :> g@x

f[{1}, {g[0.260818], g[0.767116]}, {0}]

Bobby

On Mon, 08 Mar 2010 05:15:39 -0600, Leonid Shifrin <lsh...@gmail.com>

wrote:

0 new messages

Search

Clear search

Close search

Google apps

Main menu