Problems with lexical scoping
- To: mathgroup at smc.vnet.net
- Subject: [mg108105] Problems with lexical scoping
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Mon, 8 Mar 2010 06:15:39 -0500 (EST)
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
- Follow-Ups:
- Re: Problems with lexical scoping
- From: DrMajorBob <btreat1@austin.rr.com>
- Re: Problems with lexical scoping