Inexplicable Argument Error

I am encountering a very strange argument error. I simplified my code
so that it focuses on the specific issue. Fortunately (or
unfortunately) the simplified code continued to produce the error. The
error that I am getting is:

./test1:18: syntax error, unexpected ‘,’, expecting ‘)’
@@myClassVar.capture=(‘myKey’,‘myValue’)

And here is the code that produces it:

class Class1
def initialize()
@capture = Hash.new
end
def capture=(key,value)
@capture[key]=value
end
def capture(key)
return @capture[key]
end
end
class Class2
@@myClassVar=Class1.new()
def Class2.xtol()
@@myClassVar.capture=(‘myKey’,‘myValue’)
return @@myClassVar.capture()
end
end
puts(Class2.xtol())

I’m tearing my hair out over this one; so, any help would be greatly
appreciated. Thanks.

   ... doug

                              ^

On Wed, Jun 6, 2012 at 2:33 PM, Doug J. [email protected]
wrote:

./test1:18: syntax error, unexpected ‘,’, expecting ‘)’
@@myClassVar.capture=(‘myKey’,‘myValue’)

What are you trying to do? If you’re trying to assign capture an
array, you need square brackets, not parens.

-Dave

2012/6/6 Doug J. [email protected]:

@@myClassVar.capture=(‘myKey’,‘myValue’)

Methods ending with = can usually only take one argument – as you
experienced, two arguments are not supported by the parser.

(Except for []= methods, which takes two arguments, or using some ugly
tricks, which you don’t want to use anyway.)

– Matma R.

Methods ending with = can usually
only take one argument

YIKES! I was not aware of that limitation. It certainly explains the
error message which had left me completely baffled.

I substituted an _ for the = and everything works perfectly. I won’t be
forgetting this real soon. Thanks so much.

 ... doug

2012/6/6 Doug J. [email protected]:

Methods ending with = can usually
only take one argument

YIKES! I was not aware of that limitation. It certainly explains the
error message which had left me completely baffled.

I substituted an _ for the = and everything works perfectly. I won’t be
forgetting this real soon. Thanks so much.

Just so we’re clear – this is a parser limitation, not a language
one. You can (and you did) declare such a method with multiple
arguments, and that didn’t cause the error. You could even call it
with “obj.send :method=, arg1, arg2”.

However, “obj.method=(a,b)” is not interpreted as “call method= on
obj with arguments a, b”, but as “assign (a,b) to
obj.method”, and there’s no such thing as “(a,b)”. (Technically that
assign is then converted to another function call, but let’s skip
that.)

– Matma R.

On Jun 6, 2012, at 13:38 , Doug J. wrote:

YIKES! I was not aware of that limitation. It certainly explains the
error message which had left me completely baffled.

I substituted an _ for the = and everything works perfectly. I won’t be
forgetting this real soon. Thanks so much.

It’d be more idiomatic to rename the methods [] and []=.

It’d be more idiomatic to rename the methods [] and []=.

I like it. It’s apparent that there are a number of ways to skin this
cat. I’m just glad that I now understand the issue. As I said, I was
tearing my hair out. Thanks to all.

 ... doug

2012/6/6 Bartosz Dziewoński [email protected]:

However, “obj.method=(a,b)” is not interpreted as “call method= on
obj with arguments a, b”, but as “assign (a,b) to
obj.method”, and there’s no such thing as “(a,b)”. (Technically that
assign is then converted to another function call, but let’s skip
that.)

Ruby methods ending in “=” are special:

def foo=(var)
return 42
end

foo=“HELLO”
=> “HELLO”

It returns “HELLO” instead of 42. So it’s clear that the parses treats
those methods in a “different” way.

On 08.06.2012 02:14, Iñaki Baz C. wrote:

It returns “HELLO” instead of 42. So it’s clear that the parses treats
those methods in a “different” way.

The method is never called in your example. Instead, you assign a value
to a local variable named “foo”.

def foo=(var)
puts “foo was called with ‘#{var}’.”
42
end

Assignment to local variable, method is never called:

foo=“hello”
=> “hello”

foo
=> “hello”

Use explicit receiver to ensure we call the method:

self.foo=“hello”
foo was called with ‘hello’.
=> “hello”

Call method by using Object#send:

send(:foo=, “hello”)
foo was called with ‘hello’.
=> 42

Notice how the two ways to call the method give different results.

2012/6/8 Lars H. [email protected]:

The method is never called in your example. Instead, you assign a value to a
local variable named “foo”.

def foo=(var)
puts “foo was called with ‘#{var}’.”
42
end

Yes, sorry, my fault, I failed to add the self receiver in the example.

Thanks a lot.

Hi,

You actually can assign multiple values, if you use assignment syntax:

my_object.val = 1, 2

This will wrap 1 and 2 into an array and assign it to the single
parameter of the val= method. Not exactly what you want, but it works
just as well.

By the way, this is also the reason why = methods don’t accept multiple
parameters: The syntax would simply collide with Ruby’s multiple
assignment syntax.

Anyway, I think you shouldn’t use = methods the way you do. They are not
meant to be called directly and used as normal methods. Their only
purpose is to fake the attribute syntax of classical object oriented
languages.

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 08.06.2012 10:57, schrieb Jan E.:

Hi,

You actually can assign multiple values, if you use assignment
syntax:

my_object.val = 1, 2

This will wrap 1 and 2 into an array and assign it to the single
parameter of the val= method. Not exactly what you want, but it
works just as well.

Not necessarily. The array is only assigned to the parameter if Ruby
doesn’t find anything else to assign to.

ruby -v: ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]

irb(main):001:0> class Foo
irb(main):002:1> def foo=(val)
irb(main):003:2> p val
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> f = Foo.new
=> #Foo:0x00000002704430
irb(main):007:0> f.foo = 1, 2
[1, 2]
=> [1, 2]
irb(main):008:0> x, f.foo = 1, 2 #<----
2
=> [1, 2]
irb(main):009:0> x
=> 1
irb(main):010:0>

This way, x gets the 1 and the foo= assignment method gets the 2.

Anyway, I think you shouldn’t use = methods the way you do. They
are not meant to be called directly and used as normal methods.
Their only purpose is to fake the attribute syntax of classical
object oriented languages.

Agreed.

Valete,
Marvin
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.19 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJP0fjSAAoJELh1XLHFkqhaESkH/2LDd4Wmt6ufa4aouWxTD/Yc
5O4trypQwBjFUL4Tbn6wIdGRsnfM0KxOw2yHzEg10rj24goasZvk3MpeLLPvpg4Z
SUVob5XuwV051Rx9l0ViHQrTVN6ajUCaq/Me2PFNHCFOxgwG67v81lWSUrjVNaaP
fnRwNG1Q5P8Z4+POAMya2TpxKv+8PsXi+JRMWgVw2t5yxkY9ob1cklDiHsgRVcKC
XbjllPoTbTHg/7/rvjNoD7UENUYII0DwD1vlm7Qgp9sDhMGUHzoAEBakyU5K436+
VTRNNReE1d18x0W5lhXq22iSzvAAS8Z3kK/SbVdPWTRqwQMDsfC5226xRqAO938=
=Hd35
-----END PGP SIGNATURE-----