On Tue, Jan 25, 2011 at 7:09 PM, Jon Leighton <j / jonathanleighton.com> wrote:
> Robert Klemme wrote in post #977336:
>> On Mon, Jan 24, 2011 at 7:18 PM, Jon Leighton <j / jonathanleighton.com>
>> wrote:
>>> Thanks for the explanation. FWIW I think it is a shame that postfix
>>> conditionals are semantically different to normal ones, but it's good to
>>> know why the difference occurs.
>>
>> See Gary's reply.
>
> Yes, I agree that it's surprising this is done at parse time. But
> regardless of the cause and effect it is still surprising (to me) that
> the two conditional syntaxes have different semantics :)

Why do you find that surprising?  Parse time is exactly the time when
things are done like

- determining which code sequence is a method call
- determining which code sequence is a class definition
...
- and also what code sequence denotes a variable name - and the kind
of variable (instance, local, class)

Ruby is dynamic but this does not mean that source code has arbitrary
semantic.  I guess the reason that a following assignment to a local
variable has no effect on prior usage of the identifier is compiler
efficiency.  If the assignment can be anywhere in local scope you need
more complex lookups or a second pass whereas with the current rule
you simply collect local variables you have seen so far and check each
identifier occurrence against the current set of known local
variables.

You might want to argue that one could make an exception for postfix
statements but that exception would only be efficient for the simple
case we discussed and be much harder for more complex expressions
before the postfix "if" (these expressions can even span multiple
lines).  Also, the rule would be more complicated which is always bad
because that would hinder learning the language (and maybe also bug
hunting).

>>> I started to wonder about this when I was using the following code:
>>>
>>> bla(foo) if foo = self.foo
>>>
>>> In other words, I was trying to put the value of the method foo into the
>>> local variable foo in order to avoid calling the method twice. To me the
>>> above is quite an elegant way of doing that, so it's a shame that it
>>> does not actually have the intended effect ;) [it all came crashing down
>>> when I renamed the foo variable]
>>
>> Frankly, I don't find this elegant at all.
>
> It's a matter of taste. I agree with you that in almost all situations
> that assignment during a conditional test is not nice.

I'd say it's not only taste: you should be aware of the implications.
The warning in the assignment is there for a good reason, namely
because it's a typical typing error to type "=" instead of "==".  This
will also make the code harder to read IMHO and might left the reader
wondering whether it was intentional or caused by named typing error.

> However, I liked this solution precisely because the local var was named
> exactly the same as the method. So the way I read it in my head was
> "call bla with foo, and oh btw, don't call the foo method twice". So in
> this situation the 'if foo = self.foo' was purely a performance tweak
> and nothing else. A side note, if you will - it didn't change the
> semantics of the statement.
>
> But as I say, it's a matter of taste. And it doesn't work anyway ;)

Well, at least you can do

foo = foo() and bla(foo)

Kind regards

robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/