From: Eric Mahurin Date: 2005-10-02T01:20:16+09:00 Subject: ideas for an RCR: variable locality I would like to start this thread with end goal being to create an RCR to control variable locality in the language (or determine that there is already a reasonable alternative). Problem: Within a method you can't reuse a variable name for a local variable. Some changes in ruby 2 may help the issue, but also hurt it in another way. Example: For performance reasons, I'm having my package (grammar - generic parser), generate flattened (reduce calls/stack depth) code. As long as each "method" (to be flattened) is simple enough that it doesn't require local variables I'm OK. But as soon one of these need a local variable, I'm in trouble - that variable could step on the toes of another including one just like it that it calls/flattens. Possible solutions: 1. Do nothing in the language. Ruby coders should architect around the problem and accept any limitations. A possible solution to the above problem would be to use a stack (Array) for each of these local variables to manually get locality - or ignore performance issues. 2. Take advantage of the fact that in Ruby 2 block arguments are always local. A localize method could be created that call a block and that block would make the variables that it wanted local arguments to the block. Unfortunately, this solution doesn't help the performance issue above - it worsens it using at least 2 call levels. x = 0 a,b = 1,2 z = localize { |x,y| # doesn't modify outside x x = a+b # use a and b from outside y = a-b x*y } 3. Use "def" to make a method (dummy unused name - _local) on the fly and call it. Any variables that the code needed would have to be passed in as arguments since all variables inside would be local. Sort of an opposite approach #2 where the arguments are local and everything else inside has the same scope. This is doable with no change to the language, but is quite ugly and has performance issues. x = 0 a,b = 1,2 def _local(a,b) x = a+b y = a-b x*y end z = _local(a,b) 4. Have a new block syntax to localize variables inside - maybe {{ ... }} instead of { ... }. Too be more convenient than #3, you'd want an easy way to grab variables in the containing scope. When the code tries to read a local variable not yet defined, it would get the value from the variable of the same name in the containing scope. x = 0 a,b = 1,2 z = lambda {{ # all variables inside here are local # initialize a/b from outside since not defined x = a+b y = a-b x*y }}.call # could have a method do the call for you 5. New localizing construct. This construct would be to begin/end as the above #4 {{...}} would be to plain blocks. The same handling of undefined local variables would occur (intialize from outside). x = 0 a,b = 1,2 # reuse module keyword to prevent new keyword conflicts z = module x = a+b y = a-b x*y end 6. Make "module" (and probably "class" and "def") handle reading an undefined local variable like #4 and #5 (instead of raising an exception immediately, try initializing it from the containing scope). With this, we could use an unused dummy module name to solve the problem at hand (in addition to adding flexibility to do other things): x = 0 a,b = 1,2 z = module Dummy x = a+b y = a-b x*y end Personally, I'd like to see #4, #5, and #6, but any of those 3 might do (#4 if there was a fast builtin block evaluator - no additional stack depth). Any opinions on the topic? Any other ideas? __________________________________________________ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com