Questionable behavior

I’m getting some very strange behavior from a conditional statement –
I can;t imagine how it is happeneing and I wondering if I stumbled upon
some sort of bug in Ruby. Although I have no idea how it could even
occuer, perhaps someone else can see it. Here’s the code:

p pkg
p pkg.gem
p pkg.gem
if pkg.gem
p “HERE”
pkg = pkg.merge( pkg.gem )
end
p pkg

This prints

#<OpenObject…>
nil
nil
nil

Notice it does not print “HERE” yet by that last print pkg has somehow
become nil! Note that I repeated ‘p pkg.gem’ to show that it has
nothing to do with calling this statment. Now if I remark out the pkg
assignment:

p pkg
p pkg.gem
p pkg.gem
if pkg.gem
p “HERE”
#pkg = pkg.merge( pkg.gem )
end
p pkg

I get

#<OpenObject…>
nil
nil
#<OpenObject…>

As it should be. How is this possible?

FYI
Ubuntu Linux
ruby 1.8.4 (2005-12-24) [i486-linux]

Thanks,
T.

On May 26, 2006, at 9:54 AM, [email protected] wrote:

  p "HERE"

  #pkg = pkg.__merge__( pkg.gem )

As it should be. How is this possible?
I’d be happy to test it here and see if I can replicate it. But I
don’t know what an OpenObject is.
-Mat

Hi,

On Fri, 26 May 2006 15:54:21 +0200, [email protected] wrote:

I’m getting some very strange behavior from a conditional statement –
I can;t imagine how it is happeneing and I wondering if I stumbled upon
some sort of bug in Ruby. Although I have no idea how it could even
occuer, perhaps someone else can see it. Here’s the code:

No, that is no bug, it’ a feature :wink:

here pkg is a method call

p pkg
p pkg.gem
p pkg.gem
if pkg.gem
p “HERE”
after this line pkg is a local variable (because you assign to it)
pkg = pkg.merge( pkg.gem )
end
unintialized local variables default to nil, so it prints nil
p pkg

This prints

#<OpenObject…>
nil
nil
nil

If you want the method call you can use pkg().

Here is another example:

$ cat lvar_tst.rb
def a
“method”
end

def test
p a
p a()
if false
a = 23
end
p a
p a()
end

test
$ ruby lvar_tst.rb
“method”
“method”
nil
“method”

This is just the way Ruby (it’s parser) handles local variables, but I
think matz said that this will be made more “consistent” in future
versions (i.e. if something is a lvar at some point in a scope it will
be
an lvar everywhere in this scope and you might get a warning for your
above code, like “use of lvar before initialization”)

Hope that helps,
Dominik

It would be tricky to run the test in that the code is pretty deep
inside my application. If your willing though I would be happy to send
you the whole package to try. FYI, it’s the Reap project.

OpenObject is similar to OpenStruct and can be found in Ruby F.s.

Thanks,
T.

Dominik B. wrote:

I’m getting some very strange behavior from a conditional statement –
I can;t imagine how it is happeneing and I wondering if I stumbled upon
some sort of bug in Ruby. Although I have no idea how it could even
occuer, perhaps someone else can see it. Here’s the code:

No, that is no bug, it’ a feature :wink:

Oh, I love those kind of “features”… NOT!

This is just the way Ruby (it’s parser) handles local variables, but I
think matz said that this will be made more “consistent” in future
versions (i.e. if something is a lvar at some point in a scope it will be
an lvar everywhere in this scope and you might get a warning for your
above code, like “use of lvar before initialization”)

Why does it do this and why is that a good solution? How unintuitive
can it possibly be? Why doesn’t it just convert the refernce to a lvar
when it evaluates? Why does the parser have to look ahead and
pre-judge the reference. You got code evaluating in a false condition
–so anti-dynamic!

Sigh. Okay so referncing it as a local var --EVEN IN UNEVALUATED CODE
changes a refernce to a local variable. Great! I was trying to take
advantage of the isomorphism of local vars and metods --which I thought
WAS a feature. So much for that.

Thanks Dominik,
T.

Ah, despite my rant, there is an easy solution. And it makes it very
clear the oddness of the way Ruby parser work here:

  if pkg.gem
    pkg = pkg.__merge__( pkg.gem )
  else
    pkg = pkg
  end

It won’t work without the ‘pkg = pkg’.

T.

Sounds like it’s pretty wrapped up. Interesting fix. And something
to keep in mind for later. Hopefully later version of ruby will
print warnings on this sort of thing.
-Mat