Aliased setter methods behave differently than other methods?

Here’s another question… I am aliasing and redefining certain methods,
determined at runtime. Normal methods work fine, but methods ending in
’=’ are not behaving the same. Here’s an example:

module Mymodule
def Mymodule.append_features(klass)
super(klass)
klass.module_eval do
def self.enalias(s)
alias_method((‘old_’ + s).intern, s.intern)
module_eval <<-EOF
def #{s}(arg)
puts 'hola ’ + arg
old_#{s}(arg)
end
EOF
end
end
end
end

class Myclass
def hello(s)
puts 'hello ’ + s
end
include Mymodule
end

class MyclassQ
def hello=(s)
puts 'hello ’ + s
end
include Mymodule
end

c = Myclass.new
c.hello(‘1’)
Myclass.enalias(‘hello’)
c.hello(‘2’)
c.old_hello(‘3’)
puts '-----'
q = MyclassQ.new
q.hello=(‘1’)
MyclassQ.enalias(‘hello=’)
q.hello=(‘2’)
q.old_hello=(‘3’)

This outputs the following:

hello 1
hola 2
hello 2
hello 3

···

hello 1
hola 2
hello 3

Notice that, in the class where the method is “hello=” rather than
"hello", the call to the old method fails somehow. Its output is skipped.

Am I missing something obvious here? Are the setters intended to act
differently somehow? BTW I get this output on both 1.6.8 and 1.8.

Hi,

Notice that, in the class where the method is “hello=” rather than
“hello”, the call to the old method fails somehow. Its output is skipped.

enalias for hello= will be excuted as bellow:

alias_method(('old_hello=').intern, 'hello='.intern)
module_eval <<-EOF
   def hello=(arg)
      puts 'hola ' + arg
      old_hello=(arg)		# just local variable assignment.
   end
EOF
···

At Fri, 18 Jul 2003 14:10:24 +0900, Jim Cain wrote:


Nobu Nakada

Okay, this works fine now for setters:

module_eval <<-EOF
def #{s}(arg)
puts 'hola ’ + arg
self.old_#{s}(arg)
end
EOF

But what about the generic case when you don’t know how many arguments a
method takes, and you don’t really want to know:

module_eval <<-EOF
def #{s}(*arg)
puts 'hola ’ + arg
self.old_#{s}(*arg) # syntax error
end
EOF

I get a syntax error on the method call, but only for setters. Is a
method with a name like “somemethod=” required to take exactly one argument?

Of course! Duh. I stared and stared at that one and never saw it from
Ruby’s point of view. Now I just have to figure out how to make it look
like a method call.

···

nobu.nokada@softhome.net wrote:

Hi,

At Fri, 18 Jul 2003 14:10:24 +0900, > Jim Cain wrote:

Notice that, in the class where the method is “hello=” rather than
“hello”, the call to the old method fails somehow. Its output is skipped.

enalias for hello= will be excuted as bellow:

alias_method(('old_hello=').intern, 'hello='.intern)
module_eval <<-EOF
   def hello=(arg)
      puts 'hola ' + arg
      old_hello=(arg)		# just local variable assignment.
   end
EOF

Jim Cain wrote:

Okay, this works fine now for setters:

module_eval <<-EOF
def #{s}(arg)
puts 'hola ’ + arg
self.old_#{s}(arg)
end
EOF

But what about the generic case when you don’t know how many arguments a
method takes, and you don’t really want to know:

module_eval <<-EOF
def #{s}(*arg)
puts 'hola ’ + arg
self.old_#{s}(*arg) # syntax error
end
EOF

I get a syntax error on the method call, but only for setters. Is a
method with a name like “somemethod=” required to take exactly one
argument?

Oops, sorry, I was too lazy to cut & paste. The last example should’ve been:

module_eval <<-EOF
def #{s}(*arg)
puts 'hola ’ + arg[0]
self.old_#{s}(*arg) # syntax error
end
EOF

But that of course does not address the syntax error on the old_ method
call.

irb(main):001:0> class Foo
irb(main):002:1> def x=(a,b)
irb(main):003:2> puts a,b
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> a = Foo.new
=> #Foo:0x81ae97c
irb(main):007:0> a.x=(1,2)
SyntaxError: compile error

But:

irb(main):008:0> a.send(:x=,1,2)
1
2
=> nil

Regards,

Brian.

···

On Sat, Jul 19, 2003 at 12:44:14AM +0900, Jim Cain wrote:

But what about the generic case when you don’t know how many arguments a
method takes, and you don’t really want to know:

module_eval <<-EOF
def #{s}(*arg)
puts 'hola ’ + arg
self.old_#{s}(*arg) # syntax error
end
EOF

I get a syntax error on the method call, but only for setters. Is a
method with a name like “somemethod=” required to take exactly one argument?

send(“old_#{whatever}”, arg)

Regards,

Brian.

···

On Fri, Jul 18, 2003 at 11:19:37PM +0900, Jim Cain wrote:

enalias for hello= will be excuted as bellow:

alias_method(('old_hello=').intern, 'hello='.intern)
module_eval <<-EOF
   def hello=(arg)
      puts 'hola ' + arg
      old_hello=(arg)		# just local variable assignment.
   end
EOF

Of course! Duh. I stared and stared at that one and never saw it from
Ruby’s point of view. Now I just have to figure out how to make it look
like a method call.

Wouldn’t self.method_name_here=(arg) do the trick?

Jason Creighton

···

On Fri, 18 Jul 2003 23:19:37 +0900 Jim Cain list@jimcain.us wrote:

enalias for hello= will be excuted as bellow:

alias_method(('old_hello=').intern, 'hello='.intern)
module_eval <<-EOF
   def hello=(arg)
      puts 'hola ' + arg
      old_hello=(arg)		# just local variable assignment.
   end
EOF

Of course! Duh. I stared and stared at that one and never saw it from
Ruby’s point of view. Now I just have to figure out how to make it look
like a method call.

(more or less):

Hi,

Notice that, in the class where the method is “hello=” rather than
“hello”, the call to the old method fails somehow. Its output is skipped.

enalias for hello= will be excuted as bellow:

alias_method(('old_hello=').intern, 'hello='.intern)
module_eval <<-EOF
   def hello=(arg)
      puts 'hola ' + arg
      old_hello=(arg)		# just local variable assignment.
   end
EOF

Of course! Duh. I stared and stared at that one and never saw it from
Ruby’s point of view. Now I just have to figure out how to make it look
like a method call.

Errmm, not obvious to me (a newbie). What’s the significance of the =
suffix in amethod name that makes it behave differently

?

Cheers,
Euan
Gawnsoft: http://www.gawnsoft.co.sr
Symbian/Epoc wiki: http://html.dnsalias.net:1122
Smalltalk links (harvested from comp.lang.smalltalk) http://html.dnsalias.net/gawnsoft/smalltalk

···

On Fri, 18 Jul 2003 23:19:37 +0900, Jim Cain list@jimcain.us wrote

nobu.nokada@softhome.net wrote:

At Fri, 18 Jul 2003 14:10:24 +0900, >> Jim Cain wrote:

That’s a lot of work :slight_smile:

self.old_hello=(arg)

that is,
self.old_#{s}(arg)

···

On Fri, Jul 18, 2003 at 11:52:52PM +0900, Brian Candler wrote:

alias_method(('old_hello=').intern, 'hello='.intern)
module_eval <<-EOF
   def hello=(arg)
      puts 'hola ' + arg
      old_hello=(arg)		# just local variable assignment.
   end
EOF

Of course! Duh. I stared and stared at that one and never saw it from
Ruby’s point of view. Now I just have to figure out how to make it look
like a method call.

 send("old_#{whatever}", arg)


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

damn my office is cold.
need a hot secretary to warm it up.
– Seen on #Linux

foo = x

is always interpreted as an assignment to local variable ‘foo’; and from
that point onwards in that method, ‘foo’ by itself is treated as a local
variable rather than a method. So, a local variable assignment takes
precedence over any method with the same name which might exist. Hence you
cannot call a method ‘foo=’ with the above syntax. You can however specify a
receiver (self.foo=) or use ‘send’, in which case it is unambiguously a
method call.

Ought to be documented here, but doesn’t appear to be :slight_smile:

Regards,

Brian.

···

On Sat, Jul 19, 2003 at 12:04:48AM +0900, Gawnsoft wrote:

Of course! Duh. I stared and stared at that one and never saw it from
Ruby’s point of view. Now I just have to figure out how to make it look
like a method call.

Errmm, not obvious to me (a newbie). What’s the significance of the =
suffix in amethod name that makes it behave differently