Hi,
Anyone know why thse two forms of "unless" behave differently?
irb
irb(main):001:0> foo = true unless defined?(foo)
=> nil
irb(main):002:0> unless defined?(fooo) ; fooo = true ; end
=> true
thx
···
--
Posted via http://www.ruby-forum.com/\.
Hi,
Anyone know why thse two forms of "unless" behave differently?
> irb
irb(main):001:0> foo = true unless defined?(foo)
=> nil
irb(main):002:0> unless defined?(fooo) ; fooo = true ; end
=> true
thx
--
Posted via http://www.ruby-forum.com/\.
From playing around it doesn't look like unless is "behaving differently"
Ruby has created a label for foo since it thinks it is going to be assigning
it something (dynamic language)
For example
foo = true unless defined?(foo)
=> nil
unless defined?(fooo); fooo = true; end
=> true
foo
=> nil
fooo
=> true
foo = true unless defined?(foom)
=> true
foo
=> true
Basically it looks like foo appears to exist but it doesn't really exist yet
so the first unless "acts" oddly. This is very interesting though. Perhaps
someone who knows what they are talking about can tell us why it appears to
behave this way.
···
On Thu, Feb 18, 2010 at 12:49 PM, Farhad Farzaneh <ff@onebeat.com> wrote:
--
"Hey brother Christian with your high and mighty errand, Your actions speak
so loud, I can’t hear a word you’re saying."
-Greg Graffin (Bad Religion)
oddity in the way the code is parsed:
% echo "foo = true unless defined?(foo)" | parse_tree_show
s(:if, s(:defined, s(:lvar, :foo)), nil, s(:lasgn, :foo, s(:true)))
% echo "unless defined?(fooo) ; fooo = true ; end" | parse_tree_show
s(:if, s(:defined, s(:call, nil, :fooo, s(:arglist))), nil, s(:lasgn, :fooo, s(:true)))
···
On Feb 18, 2010, at 11:49 , Farhad Farzaneh wrote:
Hi,
Anyone know why thse two forms of "unless" behave differently?
irb
irb(main):001:0> foo = true unless defined?(foo)
=> nil
irb(main):002:0> unless defined?(fooo) ; fooo = true ; end
=> true
Your latter code snippet treats "fooo" in defined? as a method call. This is because the assignment inside the conditional hasn't been parsed yet, and hasn't affected the lookup tables.
The former doesn't have this problem because the body of the conditional is parsed first.
···
On Feb 18, 2010, at 13:44 , Farhad Farzaneh wrote:
Ryan Davis wrote:
On Feb 18, 2010, at 11:49 , Farhad Farzaneh wrote:
Hi,
Anyone know why thse two forms of "unless" behave differently?
irb
irb(main):001:0> foo = true unless defined?(foo)
=> nil
irb(main):002:0> unless defined?(fooo) ; fooo = true ; end
=> true
oddity in the way the code is parsed:
% echo "foo = true unless defined?(foo)" | parse_tree_show
s(:if, s(:defined, s(:lvar, :foo)), nil, s(:lasgn, :foo, s(:true)))
% echo "unless defined?(fooo) ; fooo = true ; end" | parse_tree_show
s(:if, s(:defined, s(:call, nil, :fooo, s(:arglist))), nil, s(:lasgn,
:fooo, s(:true)))
Cool, any chance you could give a short description for those of us that
have never really thought about the parser or used parse_tree_show?
Ryan Davis wrote:
irb(main):002:0> unless defined?(fooo) ; fooo = true ; end
Cool, any chance you could give a short description for those of us that
have never really thought about the parser or used parse_tree_show?
Your latter code snippet treats "fooo" in defined? as a method call.
This is because the assignment inside the conditional hasn't been parsed
yet, and hasn't affected the lookup tables.
The former doesn't have this problem because the body of the conditional
is parsed first.
Thanks. To make sure I understand: In the first case,
foo = true unless defined?(foo)
the parser encounters 'foo', adds it to the symbol table, and then sees
the defined? call, so the net result is that foo is defined, but has nil
value. As such, if we're ever going to use defined? as a conditional,
it should precede any other mention of the token (foo).
Is this correct?
···
On Feb 18, 2010, at 13:44 , Farhad Farzaneh wrote:
--
Posted via http://www.ruby-forum.com/\.
No, it isn't necessarily defined. AT PARSE TIME it sees the initial foo and decides it is a local variable so it treats the foo in defined?(foo) as a local variable. AT RUN TIME it evaluates the defined?(foo) and acts accordingly.
···
On Feb 18, 2010, at 16:04 , Farhad Farzaneh wrote:
Ryan Davis wrote:
On Feb 18, 2010, at 13:44 , Farhad Farzaneh wrote:
irb(main):002:0> unless defined?(fooo) ; fooo = true ; end
Cool, any chance you could give a short description for those of us that
have never really thought about the parser or used parse_tree_show?
Your latter code snippet treats "fooo" in defined? as a method call.
This is because the assignment inside the conditional hasn't been parsed
yet, and hasn't affected the lookup tables.
The former doesn't have this problem because the body of the conditional
is parsed first.
Thanks. To make sure I understand: In the first case,
foo = true unless defined?(foo)
the parser encounters 'foo', adds it to the symbol table, and then sees
the defined? call, so the net result is that foo is defined, but has nil
value. As such, if we're ever going to use defined? as a conditional,
it should precede any other mention of the token (foo).
I should also point out: almost all of this is of no consequence. You almost never use defined? on a local variable like this. You usually use it on a const, ivar, cvar, or global, and all of those are unambiguous.
···
On Feb 18, 2010, at 16:04 , Farhad Farzaneh wrote:
Ryan Davis wrote:
On Feb 18, 2010, at 13:44 , Farhad Farzaneh wrote:
irb(main):002:0> unless defined?(fooo) ; fooo = true ; end
Cool, any chance you could give a short description for those of us that
have never really thought about the parser or used parse_tree_show?
Your latter code snippet treats "fooo" in defined? as a method call.
This is because the assignment inside the conditional hasn't been parsed
yet, and hasn't affected the lookup tables.
The former doesn't have this problem because the body of the conditional
is parsed first.
Thanks. To make sure I understand: In the first case,
foo = true unless defined?(foo)
the parser encounters 'foo', adds it to the symbol table, and then sees
the defined? call, so the net result is that foo is defined, but has nil
value. As such, if we're ever going to use defined? as a conditional,
it should precede any other mention of the token (foo).
Farhad Farzaneh wrote:
I should also point out: almost all of this is of no consequence. You
almost never use defined? on a local variable like this. You usually use
it on a const, ivar, cvar, or global, and all of those are unambiguous.
Thanks. I sometimes use it in Rails partials rendering, where I may
pass an optional local variable, but if it isn't passed, I want to set
it to some default value.
BTW, I wonder,
In templates, local variables are created dynamically (e.g., the
programmer passes a hash of "variables" to the template engine). So how
can Ruby know, in the template code, that a "name" refers to a variable?
By default Ruby thinks names are method invocations and since there's no
assignment, Ruby has no way to know these are variables...
···
--
Posted via http://www.ruby-forum.com/\.
that's a rails question. Please take it to a rubyonrails forum (or dig up the code--but I really don't recommend that).
···
On Feb 18, 2010, at 23:06 , Albert Schlef wrote:
Farhad Farzaneh wrote:
I should also point out: almost all of this is of no consequence. You
almost never use defined? on a local variable like this. You usually use
it on a const, ivar, cvar, or global, and all of those are unambiguous.
Thanks. I sometimes use it in Rails partials rendering, where I may
pass an optional local variable, but if it isn't passed, I want to set
it to some default value.
BTW, I wonder,
In templates, local variables are created dynamically (e.g., the
programmer passes a hash of "variables" to the template engine). So how
can Ruby know, in the template code, that a "name" refers to a variable?
By default Ruby thinks names are method invocations and since there's no
assignment, Ruby has no way to know these are variables...
Maybe it's clearer like this:
if false
foo = 123
end
puts foo # nil
puts bar # undefined local variable or method 'bar'
That is, for a bare word expression like 'foo' ruby has to decide
whether to parse it as a method call - as foo() or self.foo - or as a
local variable reference.
It makes the decision based on whether there has been a previous
assignment of the form "foo = ..." parsed earlier in the code. This is
regardless of whether the code is actually executed, because we haven't
started executing any of it yet.
"earlier" in the code is strictly left-to-right.
foo = 123 if not defined?(foo)
At the point of defined?, "foo = ..." has already been seen, and so
bareword foo is known to be a local variable, and therefore the symbol
is 'defined' as a local variable at this point in the source code,
whether or not an assignment has actually been made.
···
--
Posted via http://www.ruby-forum.com/.