E
Eric Mahurin
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 =3D 0
a,b =3D 1,2
z =3D localize { |x,y| # doesn't modify outside x
x =3D a+b # use a and b from outside
y =3D 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 =3D 0
a,b =3D 1,2
def _local(a,b)
x =3D a+b
y =3D a-b
x*y
end
z =3D _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 =3D 0
a,b =3D 1,2
z =3D lambda {{
# all variables inside here are local
# initialize a/b from outside since not defined
x =3D a+b
y =3D 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.=20
The same handling of undefined local variables would occur
(intialize from outside).
x =3D 0
a,b =3D 1,2
# reuse module keyword to prevent new keyword conflicts
z =3D module=20
x =3D a+b
y =3D 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 =3D 0
a,b =3D 1,2
z =3D module Dummy
x =3D a+b
y =3D 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=20
http://mail.yahoo.com=20
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 =3D 0
a,b =3D 1,2
z =3D localize { |x,y| # doesn't modify outside x
x =3D a+b # use a and b from outside
y =3D 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 =3D 0
a,b =3D 1,2
def _local(a,b)
x =3D a+b
y =3D a-b
x*y
end
z =3D _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 =3D 0
a,b =3D 1,2
z =3D lambda {{
# all variables inside here are local
# initialize a/b from outside since not defined
x =3D a+b
y =3D 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.=20
The same handling of undefined local variables would occur
(intialize from outside).
x =3D 0
a,b =3D 1,2
# reuse module keyword to prevent new keyword conflicts
z =3D module=20
x =3D a+b
y =3D 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 =3D 0
a,b =3D 1,2
z =3D module Dummy
x =3D a+b
y =3D 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=20
http://mail.yahoo.com=20