Shadowing bug??

  • Thread starter Vasco Andrade e Silva
  • Start date
V

Vasco Andrade e Silva

Hi,

def f_ok(node)
func = lambda {|n| p:)in_lambda, n); n }
p node, func.call(node[:xpto]), node
end
f_ok({:xpto => "ohoh"})
:in_lambda
"ohoh"
{:xpto=>"ohoh"}
"ohoh"
{:xpto=>"ohoh"}

def f_ko(node)
func = lambda {|node| p:)in_lambda, node); node }
p node, func.call(node[:xpto]), node
end
f_ko({:xpto => "ohoh"})
:in_lambda
"ohoh"
{:xpto=>"ohoh"}
"ohoh"
"ohoh" # ohoh... should be {:xpto=>"ohoh"}, or not??

I can't get any kind of explanation for this. Does anybody have one?
Why "node" in lambda isn't shadowed correctly (as i expected, at least)?
Well "node" is shadowed correctly but seems to be producing side
effects...

Thanks,
Vasco Andrade e Silva
 
M

Marcin Raczkowski

Vasco said:
Hi,

def f_ok(node)
func = lambda {|n| p:)in_lambda, n); n }
p node, func.call(node[:xpto]), node
end
f_ok({:xpto => "ohoh"})
:in_lambda
"ohoh"
{:xpto=>"ohoh"}
"ohoh"
{:xpto=>"ohoh"}

def f_ko(node)
func = lambda {|node| p:)in_lambda, node); node }
p node, func.call(node[:xpto]), node
end
f_ko({:xpto => "ohoh"})
:in_lambda
"ohoh"
{:xpto=>"ohoh"}
"ohoh"
"ohoh" # ohoh... should be {:xpto=>"ohoh"}, or not??

I can't get any kind of explanation for this. Does anybody have one?
Why "node" in lambda isn't shadowed correctly (as i expected, at least)?
Well "node" is shadowed correctly but seems to be producing side
effects...

Thanks,
Vasco Andrade e Silva

I remember someone mentioned that it's possible to do some strange
things in lambda (modyfing variable passed beeing one of them), but
there's nothing in this funcition or lambda that would modify "node", i
think there might be a scope problem that makes node variable in
function beeing overvriten when part of node is in lambda


irb(main):014:0> def f_ko(node)
irb(main):015:1> func = lambda {|node| p:)in_lambda, node); node }
irb(main):016:1> p node, func.call("bleh"), node
irb(main):017:1> end
=> nil
irb(main):018:0> f_ko({:xpto => "ohoh"})
:in_lambda
"bleh"
{:xpto=>"ohoh"}
"bleh"
"bleh"
=> nil


this seems to confirm that using |node| will overwrite node in function,
i'm not sure if it's intended scope behaviour tho
 
T

tho_mica_l

This is a somewhat similar situation where a variable isn't all that
local:

x = 1
(2..3).each {|x|}
p x
=> 3

I think this is intended though and AFAIK this behaviour is subject
to
change in 2.0 and maybe has already changed in 1.9.
 
V

Vasco Andrade e Silva

tho_mica_l said:
This is a somewhat similar situation where a variable isn't all that
local:

x = 1
(2..3).each {|x|}
p x
=> 3 Exactly!


I think this is intended though and AFAIK this behaviour is subject
to
change in 2.0 and maybe has already changed in 1.9.

I tested in ruby1.9 and the "bug" seems fixed:
RUBY_VERSION "1.9.0"
x = 1
(2..3).each {|x|}
p x 1

f_ko({:xpto => "ohoh"})
:in_lambda
"ohoh"
{:xpto=>"ohoh"}
"ohoh"
{:xpto=>"ohoh"} # :)

Thank you people,
Vasco Andrade e Silva
 
P

Peña, Botp

From: tho_mica_l [mailto:[email protected]]=20
# x =3D 1
# (2..3).each {|x|}
# p x
# =3D> 3
#=20
# I think this is intended though and AFAIK this behaviour is subject
# to change in 2.0 and maybe has already changed in 1.9.

indeed.
C:\ruby1.9\bin>irb

irb(main):001:0> x =3D 1
=3D> 1
irb(main):002:0> (2..3).each {|x|}
=3D> 2..3
irb(main):003:0> p x
1
=3D> 1

kind regards -botp
 
R

Robert Klemme

2007/11/14 said:
I tested in ruby1.9 and the "bug" seems fixed:
:in_lambda
"ohoh"
{:xpto=>"ohoh"}
"ohoh"
{:xpto=>"ohoh"} # :)

Just let me add that even though this is fixed IMHO it is a bad idea
to use the same identifier in both cases if you want to keep them
separate. This can likely cause confusion.

Kind regards

robert
 
V

Vasco Andrade e Silva

Robert said:
Just let me add that even though this is fixed IMHO it is a bad idea
to use the same identifier in both cases if you want to keep them
separate. This can likely cause confusion.

I don't agreed with you. Shadowing, IMHO, is a very useful (and
powerful) way to express semantic and execute "best practices".

Example:
Imagine you want to process a tree (as i wanted). Suppose that in the
process of that computation you call "defn_to_sexp". This method
receives a node (tagged with :defn).
In this case i wanted to do a "special" process to the args branch of
the tree. So, and because i didn't want to declare another function
visible from class scope, i created a proc (process_args). This proc
should receive the tree branch (i.e. "node") and other variable witch
represents a computation over some other branch of defn's node.

Here goes a simple sample:
def defn_to_sexp(node)
process_args = lambda do |n, has_block|
...
end
...
has_block = process(...)
process_args.call(args_node(node), hash_block)
...
end

i have more semantic if i can call the word "node" instead of the word
"n" in lambda's arg: I want to shadow the node variable.
This is a case, IMHO, where it's a good idea "to use the same identifier
in both cases".

In this case i would wanted to write:
def defn_to_sexp(node)
process_args = lambda do |node, has_block|
... # i don't want to access to the outer node
# and "node" says more than "n"
end
...
has_block = process(...)
process_args.call(args_node(node), hash_block)
...
end


Regards,
Vasco Andrade e Silva
 
R

Robert Klemme

2007/11/15 said:
I don't agreed with you. Shadowing, IMHO, is a very useful (and
powerful) way to express semantic and execute "best practices".

Example:
Imagine you want to process a tree (as i wanted). Suppose that in the
process of that computation you call "defn_to_sexp". This method
receives a node (tagged with :defn).
In this case i wanted to do a "special" process to the args branch of
the tree. So, and because i didn't want to declare another function
visible from class scope, i created a proc (process_args). This proc
should receive the tree branch (i.e. "node") and other variable witch
represents a computation over some other branch of defn's node.

Here goes a simple sample:
def defn_to_sexp(node)
process_args = lambda do |n, has_block|
...
end
...
has_block = process(...)
process_args.call(args_node(node), hash_block)
...
end

i have more semantic if i can call the word "node" instead of the word
"n" in lambda's arg: I want to shadow the node variable.
This is a case, IMHO, where it's a good idea "to use the same identifier
in both cases".

In this case i would wanted to write:
def defn_to_sexp(node)
process_args = lambda do |node, has_block|
... # i don't want to access to the outer node
# and "node" says more than "n"
end
...
has_block = process(...)
process_args.call(args_node(node), hash_block)
...
end

IMHO you are abusing a lambda to get a nested method. This likely
also has performance impacts since the block has to be recreated on
every invocation of the method. In this case I'd rather use a private
helper method.

But I can see how you would want to use the same identifier in some
cases. I can only speak for myself: I did not feel the urge to do
this (yet).

Cheers

robert
 
V

Vasco Andrade e Silva

Robert said:
IMHO you are abusing a lambda to get a nested method. This likely
also has performance impacts since the block has to be recreated on
every invocation of the method. In this case I'd rather use a private
helper method.

But I can see how you would want to use the same identifier in some
cases. I can only speak for myself: I did not feel the urge to do
this (yet).

I think that has to do a lot with your "school".
Have a try with it, i'm sure you'll love it after while :p
Cheers

robert

Let me only add if you want performance in this case you could just do:
@process_args ||= lambda do |node, has_block|
... # i don't want to access to the outer node
# and "node" says more than "n"
end

this is a very simple cache system ;)

Regards,
Vasco
 
R

Robert Klemme

2007/11/16 said:
I think that has to do a lot with your "school".
Have a try with it, i'm sure you'll love it after while :p

This is a melody that drastically increases the likelihood that I do
*not* do it because it is usually used by people that want my money.
:))

From what I've seen so far I do not think I gain any advantages, so
sorry, I stick with my "old school". :)
Let me only add if you want performance in this case you could just do:
@process_args ||= lambda do |node, has_block|
... # i don't want to access to the outer node
# and "node" says more than "n"
end

this is a very simple cache system ;)

Yes, and it has the drawback to at least potentially hold on to
objects longer than needed... :)

Kind regards

robert
 
V

Vasco Andrade e Silva

Hi (again),

In "Programing Ruby: The Pragmatic Programmers Guide (2dn Ed.)" Book,
pp. 333:
<quote>
Block parameters are assigned values when the block is invoked.
...
If a local variable (including a block parameter) is first assigned in a
block, it is local to the block. If instead a variable of the same name
is already established at the time the block executes, the block will
inherit that variable.
</quote>

As far as i can see in that text it describes (spec's)
x = 1
(2..3).each {|x|}
p x
=> 3
to a correct case..

I need to know:
1) Is this the behavior we should expect from the ruby language (1.8)?
2) Since ruby (1.9) does not behave the same way:
x = 1
(2..3).each {|x|}
p x
=> 1
what should be the spec for block parameters?

Thanks (once more),
Vasco
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top