Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ruby, define []= operator, why can't control return value?

Tags:

ruby

Trying to do something weird that might turn into something more useful, I tried to define my own []= operator on a custom class, which you can do, and have it return something different than the value argument, which apparently you can't do. []= operator's return value is always value; even when you override this operator, you don't get to control the return value.

class Weird 
  def []=(key, value)
    puts "#{key}:#{value}"
    return 42
  end
end

x = Weird.new
x[:a] = "a"
  output "a:a"
  return value => "a"  # why not 42?

Does anyone have an explanation for this? Any way around it?

ruby MRI 1.8.7. Is this the same in all rubys; Is it part of the language?

like image 663
jrochkind Avatar asked Jun 16 '11 03:06

jrochkind


People also ask

What does += mean in Ruby?

+= is not a real Ruby operator, and the expression above is simply an abbreviation for: x = x + 1. Abbreviated assignment cannot be combined with parallel assignment: it only works when there is a single lvalue on the left and a single value on the right.


2 Answers

Note that this behavior also applies to all assignment expressions (i.e. also attribute assignment methods: def a=(value); 42; end).

My guess is that it is designed this way to make it easy to accurately understand assignment expressions used as parts of other expressions.

For example, it is reasonable to expect x = y.a = z[4] = 2 to:

  1. call z.[]=(4,2), then
  2. call y.a=(2), then
  3. assign 2 to the local variable x, then finally
  4. yield the value 2 to any “surrounding” (or lower precedence) expression.

This follows the principle of least surprise; it would be rather surprising if, instead, it ended up being equivalent to x = y.a=(z.[]=(4,2)) (with the final value being influenced by both method calls).


While not exactly authoritative, here is what Programming Ruby has to say:

  • Programming Ruby (1.8), in the Expressions section:

    An assignment statement sets the variable or attribute on its left side (the lvalue) to refer to the value on the right (the rvalue). It then returns that value as the result of the assignment expression.

  • Programming Ruby 1.9 (3rd ed) in section 22.6 Expressions, Conditionals, and Loops:

    (right after describing []= method calls)

    The value of an assignment expression is its rvalue. This is true even if the assignment is to an attribute method that returns something different.

like image 159
Chris Johnsen Avatar answered Sep 17 '22 13:09

Chris Johnsen


It’s an assignment statement, and those always evaluate to the assigned value. Making this different would be weird.

I suppose you could use x.[]= :a, "a" to capture the return value.

like image 37
Josh Lee Avatar answered Sep 19 '22 13:09

Josh Lee