||= with 1.8 and 1.9?

Right, the question is why in Ruby 1.9 is using the 'not a test'
returned from the setter method in the case of ||= unlike Ruby 1.8.x
and like itself in the = case:

To make it a bit clearer by moving the assignments out of the p calls:

puts RUBY_VERSION

class OrOrEquals
  def test
    @test
  end

  def test=(test)
    @test = test
    'not test'
  end
end

o = OrOrEquals.new

direct = o.test = 'a test'
p direct
o.test = nil
with_oror = o.test ||= 'a test'
p with_oror
p o.test
o.test = nil

$ multiruby or_or_equals.rb
/opt/local/lib/ruby/site_ruby/1.8/rubygems/source_index.rb:144:
warning: /Users/rick/.gem/ruby/1.8/specifications: Permission denied

VERSION = 1.8.6-p368
CMD = ~/.multiruby/install/1.8.6-p368/bin/ruby or_or_equals.rb

1.8.6
"a test"
"a test"
"a test"

RESULT = 0

VERSION = 1.8.7-p160
CMD = ~/.multiruby/install/1.8.7-p160/bin/ruby or_or_equals.rb

1.8.7
"a test"
"a test"
"a test"

RESULT = 0

VERSION = 1.9.1-p0
CMD = ~/.multiruby/install/1.9.1-p0/bin/ruby or_or_equals.rb

1.9.1
"a test"
"not test"
"a test"

I've raised this on ruby-core. I'm interested to see what Matz & co
have to say.

···

On Wed, Aug 26, 2009 at 2:49 PM, Aldric Giacomoni<aldric@trevoke.net> wrote:

Joel VanderWerf wrote:

Well, then... It -IS- assigning something, isn't it, since there's no
value to @test ? Why does it return something other than the result of
the assignment?

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Brian Candler wrote:

The method name is 'x=' and it was called using 'obj.x='. Where's the
sugar?

The parentheses in (10) are not delimiting arguments of a method call;
they are just bracketing a value expression. Note:

class Foo; def bar=(x,y,z); 123; end; end

=> nil

Foo.new.send(:bar=,7,8,9)

=> 123

Foo.new.bar=(7,8,9)

SyntaxError: compile error
(irb):3: syntax error, unexpected ',', expecting ')'
Foo.new.bar=(7,8,9)
               ^
  from (irb):3
  from :0

Similarly:

Foo.new.bar= 7,8,9

ArgumentError: wrong number of arguments (1 for 3)
  from (irb):4:in `bar='
  from (irb):4
  from :0

Wow. Thanks for the explanation.

.
.
.
.
.
.
.
.
..
.
.

···

--
Posted via http://www.ruby-forum.com/\.

Right, the question is why in Ruby 1.9 is using the 'not a test'
returned from the setter method in the case of ||= unlike Ruby 1.8.x
and like itself in the = case:

According the rubyspec project:

  language/variables_spec.rb:
    describe "Operator assignment 'var op= expr'" do
      it "is equivalent to 'var = var op expr'" do
        x = nil
        (x ||= 17).should == 17
        x.should == 17
        (x ||= 2).should == 17
        x.should == 17
    describe "Operator assignment 'obj.meth op= expr'" do
      it "is equivalent to 'obj.meth = obj.meth op expr'" do
        @x.a = nil
        (@x.a ||= 17).should == 17
        @x.a.should == 17
        (@x.a ||= 2).should == 17
        @x.a.should == 17
    describe "Operator assignment 'obj[idx] op= expr'" do
      it "is equivalent to 'obj[idx] = obj[idx] op expr'" do
        x = [1,nil,12]
        (x[1] ||= 17).should == 17
        x.should == [1,17,12]
        (x[1] ||= 2).should == 17
        x.should == [1,17,12]
      it "returns result of rhs not result of =" do
        a = VariablesSpecs::Hashalike.new
        (a[123] = 2).should == 2
        (a[123] ||= 2).should == 123
        (a[nil] ||= 2).should == 2

The specs don't address the case of a 'hijacked' setter, but they do
give the impression that the ruby1.9 behaviour is incorrect.

I've raised this on ruby-core. I'm interested to see what Matz & co
have to say.

Yes, should be interesting.

···

On Wed, Aug 26, 2009 at 3:46 PM, Rick DeNatale<rick.denatale@gmail.com> wrote:

Hi --

···

On Thu, 27 Aug 2009, brabuhr@gmail.com wrote:

On Wed, Aug 26, 2009 at 3:46 PM, Rick DeNatale<rick.denatale@gmail.com> wrote:

Right, the question is why in Ruby 1.9 is using the 'not a test'
returned from the setter method in the case of ||= unlike Ruby 1.8.x
and like itself in the = case:

According the rubyspec project:

language/variables_spec.rb:
   describe "Operator assignment 'var op= expr'" do
     it "is equivalent to 'var = var op expr'" do

It isn't, though, at least in the ||= case (see Joel W.'s post).
Matz's characterization of it to me at RubyConf (or somewhere) was:

   x ||= y same as x || x = y

David

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Q: What's the best way to get a really solid knowledge of Ruby?
A: Come to our Ruby training in Edison, New Jersey, September 14-17!
    Instructors: David A. Black and Erik Kastner
    More info and registration: http://rubyurl.com/vmzN

Yeah, that version matches my mental model.

x ||= y
    x = x || y
    x || x = y

x += y
    x = x + y
    x + x = y # :slight_smile:

o.x ||= y
    o.x = o.x || y
      # .x= is always called
    o.x || o.x = y
      # .x= is not always called

o.x += y
    o.x = o.x + y

Then maybe ||= and += should be split apart in rubyspec:
  describe "var += expr" it "is equivalent to 'var = var op expr'"
  describe "var ||= expr" it "is equivalent to 'var || var = expr'"

···

On Wed, Aug 26, 2009 at 5:23 PM, David A. Black<dblack@rubypal.com> wrote:

Hi --

On Thu, 27 Aug 2009, brabuhr@gmail.com wrote:

According the rubyspec project:

language/variables_spec.rb:
describe "Operator assignment 'var op= expr'" do
it "is equivalent to 'var = var op expr'" do

It isn't, though, at least in the ||= case (see Joel W.'s post).
Matz's characterization of it to me at RubyConf (or somewhere) was:

x ||= y same as x || x = y

It's approximately the same as certainly closer than x = x || y

There's a difference in what happens if x is not previously defined

···

On Wed, Aug 26, 2009 at 5:23 PM, David A. Black<dblack@rubypal.com> wrote:

It isn't, though, at least in the ||= case (see Joel W.'s post).
Matz's characterization of it to me at RubyConf (or somewhere) was:

x ||= y same as x || x = y

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Hi,

According the rubyspec project:

language/variables_spec.rb:
   describe "Operator assignment 'var op= expr'" do
     it "is equivalent to 'var = var op expr'" do

It isn't, though, at least in the ||= case (see Joel W.'s post).
Matz's characterization of it to me at RubyConf (or somewhere) was:

  x ||= y same as x || x = y

Basically, "var op= expr" works like "var = var op expr" but left hand
side expression (var) is evaluated only once. For ||=, it is same as

  x = (x || y)

but

  x || (x = y)

is semantically same (well, almost).

              matz.

···

In message "Re: ||= with 1.8 and 1.9 ?" on Thu, 27 Aug 2009 06:23:01 +0900, "David A. Black" <dblack@rubypal.com> writes:

Hi --

···

On Thu, 27 Aug 2009, Rick DeNatale wrote:

On Wed, Aug 26, 2009 at 5:23 PM, David A. Black<dblack@rubypal.com> wrote:

It isn't, though, at least in the ||= case (see Joel W.'s post).
Matz's characterization of it to me at RubyConf (or somewhere) was:

x ||= y same as x || x = y

It's approximately the same as certainly closer than x = x || y

There's a difference in what happens if x is not previously defined

True. Maybe this?

   defined?(x) && x || x = y

David

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Q: What's the best way to get a really solid knowledge of Ruby?
A: Come to our Ruby training in Edison, New Jersey, September 14-17!
    Instructors: David A. Black and Erik Kastner
    More info and registration: http://rubyurl.com/vmzN

Hi --

Hi,

>> According the rubyspec project:
>>
>> language/variables_spec.rb:
>> describe "Operator assignment 'var op= expr'" do
>> it "is equivalent to 'var = var op expr'" do
>
>It isn't, though, at least in the ||= case (see Joel W.'s post).
>Matz's characterization of it to me at RubyConf (or somewhere) was:
>
> x ||= y same as x || x = y

Basically, "var op= expr" works like "var = var op expr" but left hand
side expression (var) is evaluated only once. For ||=, it is same as

x = (x || y)

but

x || (x = y)

is semantically same (well, almost).

The hash case, though, definitely points to x || (x = y):

h = Hash.new(5)

=> {}

h[:x] = (h[:x] || 1)

=> 5

h

=> {:x=>5}

h[:z] || (h[:z] = 1)

=> 5

h

=> {:x=>5}

h[:y] ||= 1

=> 5

h

=> {:x=>5}

David

···

On Thu, 27 Aug 2009, Yukihiro Matsumoto wrote:

In message "Re: ||= with 1.8 and 1.9 ?" > on Thu, 27 Aug 2009 06:23:01 +0900, "David A. Black" <dblack@rubypal.com> writes:

--
David A. Black / Ruby Power and Light, LLC / http://www.rubypal.com
Q: What's the best way to get a really solid knowledge of Ruby?
A: Come to our Ruby training in Edison, New Jersey, September 14-17!
    Instructors: David A. Black and Erik Kastner
    More info and registration: http://rubyurl.com/vmzN

I've never understood ||=. As a result, I would never use it in my
code. As far as I'm concerned, I can explicitly write what I want
rather than trust some unpredictable, quirky short hand operator.

···

--
Posted via http://www.ruby-forum.com/.