Prev: DXF Writer?
Next: System handling of undef_method
From: Ryan Davis on 19 Feb 2010 03:09 On Feb 18, 2010, at 17:48 , Farhad Farzaneh wrote: > Ryan Davis wrote: >> On Feb 18, 2010, at 16:04 , Farhad Farzaneh wrote: >> >>>> yet, and hasn't affected the lookup tables. >>> 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. > > 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. Perhaps there's a better way of doing this... var ||= default
From: Ryan Davis on 19 Feb 2010 03:10 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... that's a rails question. Please take it to a rubyonrails forum (or dig up the code--but I really don't recommend that).
From: Brian Candler on 20 Feb 2010 06:28 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/.
From: Eric Christopherson on 20 Feb 2010 23:09 On Thu, Feb 18, 2010 at 5:18 PM, Ryan Davis <ryand-ruby(a)zenspider.com> wrote: > 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. And: On Sat, Feb 20, 2010 at 5:28 AM, Brian Candler <b.candler(a)pobox.com> wrote: > 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. I think I understand the gist of this -- if the parser has seen foo already, it is considered "defined" -- but how does the distinction of method vs. local variable matter in this context? As far as I can tell, defined? works the same on local variable names and method names.
From: Brian Candler on 21 Feb 2010 16:42
Eric Christopherson wrote: > So: > > def foo; 456; end unless defined? foo > puts foo > > will print 456, because at parse time foo is undefined, even though it > gets made into a method name at runtime. Almost - perhaps I muddied things a bit. At parse time, in the above code, foo is not 'undefined'; it is known that it must be a method name, because it's not a local variable. But it's not known whether there will be a method called foo at the time this code is executed. So, the result of defined?(foo) is decided at runtime. But if foo is a local variable at that point in the source code (which is decided at parse time), then you always know that the result of defined?(foo) will be "local-variable", since the parse tree contains "NODE_LVAR foo"; the parser had already chosen foo to be a local variable, and this is a fact which cannot be altered subsequently. I don't think the MRI interpreter actually optimises away defined?(LVAR) to a constant at parse time as I might have implied, but in theory it could. For methods, the result is not known until runtime. Example: >> 2.times { puts defined?(foo); def foo; end } nil method => 2 -- Posted via http://www.ruby-forum.com/. |