Close and Go BackBack to Viget

A Confusing Rubyism

Ben Scofield
Ben Scofield, Development Director, July 12, 2008 5

The following code has the potential to be terribly confusing:

if x = some_method
  monkify
else
  rhinofy
end

In Ruby, the return value of an assignment statement is the value assigned (run a = 1 in irb and you'll see it returns 1), so this code can be understood as:

  1. Evaluate some_method and assign the value to x
  2. If the new value of x evaluates to true, run monkify
  3. If the new value of x evaluates to false, run rhinofy

Unfortunately, however, most developers are much more accustomed to seeing the equality operator == in conditionals, which means that often we'll misinterpret that code as:

  1. Evaluate some_method and compare the result to x
  2. If they are the same, run monkify
  3. If they are different, run rhinofy

In the interest of clarity, then, it's probably better to avoid using an assignment statement in a conditional. Of course, other concerns may override the need for clarity - but it's something to keep in mind.

Morgan Roderick said on 07/15 at 12:36 PM

Interesting.

I’ve been (mis)using similar behaviour in javascript for years.


var i = 0, car;
while( car = cars[i++]){
// do stuff
}

I suppose that the reason it works is exactly the same reason it works in Ruby ... but in this case I think the code is actually very easy to read.

TJ Stankus said on 07/24 at 11:02 AM

Good point Ben.

It makes it slightly less confusing if the method in the conditional is named some_method? and written like this:

x = if some_method?
      monkify
    else
      rhinofy
    end

Or, even better:

x = some_method? ? monkify : rhinofy

(Hopefully the code formats okay, that’s part of my point.)

TJ Stankus said on 07/24 at 11:04 AM

Well, the indention/whitespace didn’t work out in my comment above. I would typically indent the lines in the first example to line up with the if statement.

Ben said on 07/25 at 06:21 PM

Those are easier to read, TJ, but they don’t quite preserve the original intent of the code. In the example I provided, x is assigned the value from some_method, while in your rewrites it is assigned either the value from monkify or rhinofy, depending on the value returned from some_method.

TJ Stankus said on 07/26 at 01:32 AM

I should read the post more carefully before commenting. :) But, I guess that further proves your point - it is confusing! I agree, the better practice is to not use assignment in conditionals.

Trackback URL: http://www.viget.com/trackback/1192/

Comments for this entry were closed after 60 days.

Name:

Email:

URL:

Not a robot? Prove it by entering the word below.


Remember my personal information

Notify me of follow-up comments?

A Development Community for Viget Labs and Beyond

Every team member here at Viget Labs strives to be an innovator. We members of the development team are no different - that's why we're constantly engaging in community discussions and exploring the unknown that is the next generation of open-source web applications.

Viget Is Hiring!

Viget has job openings for Ruby Developers, Interns, and Front-End Developers. Learn More »

Recent Comments

I think that polymorphic_url(@commentable, :anchor => “comment_#{@comment.id}") should work. You can also refactor the “comment_#{@comment.id}” to a separated method, like dom_id, which returns the dom identifier of the comment.