10 comments

[ 1.8 ms ] story [ 24.3 ms ] thread
Stupid name for a blog post, neat Ruby trick.

&&= is less well known than ||=. RTFA for examples.

There is a tiny inaccuracy in this post:

@value ||= "foo" is more efficient than

    @value = @value || "foo"
As it actually evaluates as follows:

    @value || @value = "foo"
This is especially good when working with hashes, as the left hand side is only evaluated once, not twice.
Interesting.

For the example cited, you could also use ActiveRecord::Dirty

  def clean_summary
    self.summary = summary.squish if self.summary_changed?
  end
Not quite because the summary could change to nil, but it brings up a good point. There's often a better way in Rails, but &&= is native Ruby so it's especially useful in non-Rails applications.
Does Python have this?
Don't think so, but I wouldn't want it anyway, the Ruby syntax being as it is. I think the CoffeeScript equivalents are more intuitive:

  @current_user ?= User.find()
  # as opposed to @current_user ||= User.find()
and

  @summary = excerpt?.squish
  # as opposed to @summary &&= excerpt.squish
Python doesn't need it; the savings from not double-evaluating things aren't there. Additionally, Python lore is to expand this idiom to an if statement, for explicitness, especially in polymorphic situations where you actually want to check for "<expr> is None" rather than "bool(<expr>)". Both of these examples are Railsy; equivalent Djangoy statements in form validation would have to deal with None:

    if data["incoming"] is None:
        data["incoming"] = "Default value"

    ...

    if data["incoming"]:
        data["incoming"] = data["incoming"].strip()
Because of Python's string immutability, there's no point to dodging the assignment; you're still going to incur new string creation anyway.
I'm sort of torn on using these magic operators in Ruby, and i've used ruby since the 1.4 days.

For example this:

    some_var &&= replace_var()
    some_var ||= initialize_var()
versus a more conventional/idiomatic if:

    some_var = (some_var) ? replace_var() : initialize_var()
||= turns out to be rather useful as a general assign once operator, but i'm having a hard time justifying use of &&=. That and I find myself after learning Erlang to try to assign only once when possible to make debugging easier.

While ||= isn't strictly needed, it makes assigning to class/module variables in a single line easier in general. I'm not sure I agree with the Python "always expand to an if statement" methodology though, it just seems like a bit of unneeded yak shaving. (note: i don't use rails so your post may be specific to web frameworks and I'm off my rocker, if so disregard. >.<)

I feel like my Ruby brain just grew a little ... very neat Thanks for that.