[MacRuby-devel] Weird behaviour for a weird line of code

Ryan Davis ryand-ruby at zenspider.com
Mon Nov 15 13:50:49 PST 2010


On Nov 14, 2010, at 18:37 , Mark Rada wrote:

> Now, when I try this out in macirb: (Case #3)
> 
>   require 'uri'
>   test = URI.parse url unless (url = 'http://macruby.org/').nil?  # error
>   test = URI.parse url unless (url = 'http://wikipedia.org/').nil? # works
> 
> If it doesn't work in the second case, why does it start working in the third case?

First off, I hate this style of coding. If you didn't assign in a conditional you'd avoid all of this crap to begin with. Assigning in conditionals is just a sloppy and error prone way of coding and you should avoid it. This has been a known anti-pattern in any algol-esque language since at least the 80s.

That said... This actually has nothing to do with macruby and is an effect of the ruby parser. It is about variable visibility.

In case 3:

+ The first line has "URI.parse url" followed by "unless (url = ...).nil?"
  + The first 'url' is actually parsed as a method call because the word has never been seen before and wasn't added to the variable table. The second url DOES add url to the variable table.
+ The second line has the same thing, but by now, "url" has been added to the variable table. This lets everything be parsed as a variable at parse time.

Here is how you should code it:

>   require 'uri'
>   url  = "http://macruby.org/"
>   test = URI.parse url if url
>   url  = "http://wikipedia.org/"
>   test = URI.parse url if url

no variable parse ambiguity. no testing for nil specifically (.nil? is almost NEVER needed, just test for truthiness--imagine what happens when someone sets url to false with your code). clean. readable.

Your code all it's nerdiness:

s(:block,
 s(:if, s(:call, s(:lasgn, :url, s(:str, "http://macruby.org/")),
          :nil?, s(:arglist)),
   nil,
   s(:lasgn, :test,
    s(:call, s(:const, :URI), :parse,
      s(:arglist, s(:call, nil, :url, s(:arglist)))))), # HERE IT IS A CALL
 s(:if, 
   s(:call, s(:lasgn, :url, s(:str, "http://wikipedia.org/")), :nil?,
     s(:arglist)),
   nil,
   s(:lasgn, :test,
    s(:call, s(:const, :URI), :parse, s(:arglist, s(:lvar, :url))))))



More information about the MacRuby-devel mailing list