From: Robert Klemme Date: 2011-01-25T00:08:03+09:00 Subject: Re: The finer points of postfix conditionals. On Mon, Jan 24, 2011 at 3:22 PM, Jon Leighton wrote: > So it turns out the following results in a NoMethodError: > > foo if foo = 1 > > I.e. the assignment to foo in the conditional is not in-scope when the > 'then' part is evaluated. > > Obviously the following does not result in a NoMethodError: > > if foo = 1 >  foo > end > > I would expect them to work the same way. Does anybody know the reason > for this? How exactly is the first example parsed? This is not an issue of parsing as you can easily check: 15:56:20 ~$ ruby19 -ce 'foo if foo = 1' -e:1: warning: found = in conditional, should be == Syntax OK (Ignore the warning for the moment.) This has to do with the way Ruby deals with local variables and especially with the local variable method ambiguity. In short, a local variable is known from the point in code on where it first shows up on the left side of an assignment. Postfix "if" has the assignment after the "body" of the "if" while in the case of the "if" statement the assignment comes lexically before the access. See also http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html#UO > Secondly, suppose foo has not yet been assigned. The following results > in foo being assigned to nil: > > foo = 1 if false > > In fact, so does: > > if false >  foo = 1 > end > > and even: > > if false >  foo = 1 >  bar = 2 > end > > (results in both foo and bar being assigned nil) This is not exactly true: foo is not "assigned nil" but rather is foo initialized as a local variable and initially a variable refers nil. There is no assignment but because you have an assignment in code (even though it's no executed) the local variable comes into existence (see above). > Also consider: > > foo = 1 > foo = 2 if false > > This results in foo keeping its value of 1, not being assigned to nil. > So it is not simply the case that the second statement is parsed as: > > foo = (2 if false) Your assessment is correct. It is parsed as (foo = 2) if false Or, more general expr /if/ condition > Is anyone able to elaborate on what exactly the interpreter is doing in > these cases? I hope so. Please note also that the code "expr1 if var = expr2" can always be replaced by the much more readable var = expr2 expr1 if var or var = expr2 if var expr1 end or var = expr2 and expr1 # mind operator precedence! Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/