Self.x=(value) in private?

Hello Rubyists,

I am slightly confused with calling a private method:

···

--------------------------------------------------
class Foo
  def without_self
    x=5
  end
  def with_self
    self.x=5
  end
  def call_priv_with_self
    self.priv
  end
  
  private
  
  def x=(value)
    puts "x=#{value}"
  end

  def priv
    puts "priv"
  end
   
end

Foo.new.without_self # no output
Foo.new.with_self # output "x=5"
Foo.new.call_priv_with_self # bang
--------------------------------------------------

I guess the first call is just an assignment to the variable x. But
from my understanding of pickaxe2, 329, Variable/Method Ambiguity this
should not be the case, because Ruby did not encounter an assignment
before.

The second call works, although it is a private method and I learned
that private methods must not have a receiver, as 'proved' in line
three.

So my two questions are: why is there no method call in
Foo#without_self? And why does self.x= report an error?

Patrick

Hi Patrick,

class Foo
  def without_self
    x=5
  end

  def with_self
    self.x=5
  end
  
  private
  
  def x=(value)
    puts "x=#{value}"
  end

[...]

Why is there no method call in Foo#without_self?

An expression that looks like ‘identifier = value’ always
sets a variable, and never calls a method. This is simply
the way the language is defined.

When you want to call a setter method on the current object,
you *have* to say ‘self.foo = bar’, precisely because if you
leave out the ‘self.’, you will just create a local variable.

(You may encounter code that has each setter method aliased
to a names like ‘set_foo’ or ‘set_bar’. This of course
removes the need for the ‘self.’ prefix, because ‘set_foo’
and ‘set_bar’ can be called directly.)

And why does self.x= [not] report an error?

As you have already pointed out yourself, private methods
may not normally be called with an explicit receiver.
However, there is an exception to this rule which says that
private setter methods *may* be called with an explicit
receiver, provided that explicit receiver is exactly ‘self’.
(No other receiver, not even ‘(self)’, is excused.)

Of course, this exception exists precisely because it would
otherwise be very difficult to call a private setter method.

···

--
Daniel Brockman <daniel@brockman.se>

    So really, we all have to ask ourselves:
    Am I waiting for RMS to do this? --TTN.

Daniel,

thank you for your explanations.

[...]

An expression that looks like ‘identifier = value’ always
sets a variable, and never calls a method. This is simply
the way the language is defined.

Then this part in Pickaxe II is the first section that irritates me.

Now that I know that this behaviour is intentional, I can use it in my
coode.

Regards,

Patrick

I just want to make sure I fully understand this.

Isn't the preferred way of doing this the following?

@foo = bar

Is this equivalent to

self.foo = bar

Is this true?

An expression that looks like '@attr-name = value' always calls a
method whose name is 'attr-name='.

···

On 7/25/05, Daniel Brockman <daniel@brockman.se> wrote:

An expression that looks like 'identifier = value' always
sets a variable, and never calls a method. This is simply
the way the language is defined.

When you want to call a setter method on the current object,
you *have* to say 'self.foo = bar', precisely because if you
leave out the 'self.', you will just create a local variable.

--
R. Mark Volkmann
Partner, Object Computing, Inc.

Patrick Gundlach wrote:

Daniel,

thank you for your explanations.

[...]

An expression that looks like ‘identifier = value’ always
sets a variable, and never calls a method. This is simply
the way the language is defined.

Then this part in Pickaxe II is the first section that irritates me.

Now that I know that this behaviour is intentional, I can use it in my
coode.

A writer method (ending in =) is a bit of a special case.
Ordinary methods work as you were expecting.

Hal

What's wrong with the Pickaxe II here? Can you point to the problem section?

James Edward Gray II

···

On Jul 25, 2005, at 8:05 AM, Patrick Gundlach wrote:

An expression that looks like ‘identifier = value’ always
sets a variable, and never calls a method. This is simply
the way the language is defined.

Then this part in Pickaxe II is the first section that irritates me.

> An expression that looks like 'identifier = value' always
> sets a variable, and never calls a method. This is simply
> the way the language is defined.
>
> When you want to call a setter method on the current object,
> you *have* to say 'self.foo = bar', precisely because if you
> leave out the 'self.', you will just create a local variable.

I just want to make sure I fully understand this.

Isn't the preferred way of doing this the following?

@foo = bar

Is this equivalent to

self.foo = bar

Is this true?

Often it has the same effect.

An expression that looks like '@attr-name = value' always calls a
method whose name is 'attr-name='.

No it's the other way round. Most methods looking like 'attr_name='
are implemented like this:

    # public accessor method
    def attr_name=(val)
        # Set instance variable @attr_name
        # @attr_name is only accessible in methods of self
        @attr_name = val
    end

Let's look at an example:

    % cat foo.rb
    class Foo
        def initialize
           @text = ""
        end
        def text=(val)
            # an empty string is a "true value" in Ruby,
            # nil is a "false value"
            @text = val || ""
        end
        def text
            # just return @text
            @text
        end
        def set_nil
            @text = nil
        end
    end

    a = Foo.new
    a.text = nil
    b = Foo.new
    b.set_nil
    p a.text
    p b.text
    % ruby foo.rb
    ""
    nil

···

On Thursday 28 July 2005 23:59, Mark Volkmann wrote:

On 7/25/05, Daniel Brockman <daniel@brockman.se> wrote:

--
Stefan

An expression that looks like =91identifier =3D value=92 always
sets a variable, and never calls a method. This is simply
the way the language is defined.

Then this part in Pickaxe II is the first section that irritates me.

What's wrong with the Pickaxe II here? Can you point to the problem =20
section?

Oh, I see, I misread the example. I was talking about 'Variable/Method
Ambiguity', Chapter 22, page 329 and I thought that is also related to
assignment. But that is not stated there. Thanks for asking again, so I
reread the section and made things clearer. (Although the description
of Attribute Assignment, p. 350 did not mention the special case that
these methods can be private).

Patrick

[...]

> An expression that looks like '@attr-name = value' always calls a
> method whose name is 'attr-name='.

No it's the other way round. Most methods looking like 'attr_name='
are implemented like this:

    # public accessor method
    def attr_name=(val)
        # Set instance variable @attr_name
        # @attr_name is only accessible in methods of self
        @attr_name = val
    end

Let's look at an example:

    % cat foo.rb
    class Foo
        def initialize
           @text = ""
        end
        def text=(val)
            # an empty string is a "true value" in Ruby,
            # nil is a "false value"
            @text = val || ""
        end
        def text
            # just return @text
            @text
        end
        def set_nil
            @text = nil

              # replace the above line with:
              # self.text = nil
              # and the method text= we've defined above will
              # be called

        end
    end

    a = Foo.new
    a.text = nil
    b = Foo.new
    b.set_nil
    p a.text
    p b.text
    % ruby foo.rb
    ""
    nil

HTH,
  Stefan

···

On Friday 29 July 2005 00:24, Stefan Lang wrote:

On Thursday 28 July 2005 23:59, Mark Volkmann wrote: