Why can't I redefine "<<" method to allow two parameters?

Hi, very exrtange:

class MyArray < Array
alias original_add <<
def <<(n,k)
original_add “#{n}: #{k}”
end
end

my_array = MyArray.new
=> []

my_array << (“Header”, “Value”)

SyntaxError: compile error
(irb):25: syntax error, unexpected ‘,’, expecting ‘)’
my_array << (“Header”, “Value”)
^

Any reason for this? It seems that << is a littled “hardcoded”, isn’t?

On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz C. [email protected] wrote:

my_array = MyArray.new
Any reason for this? It seems that << is a littled “hardcoded”, isn’t?


Iñaki Baz C.
[email protected]

The << operator is a special case handled by the parser, but you can
bypass that handling by calling the method directly:

my_array.<<(“Header”, “Value”)

which will of course look a ton better by just using a custom method:

my_array.add_stuff “Header”, “Value”

Jason R.

2008/5/8, Iñaki Baz C. [email protected]:

Any reason for this? It seems that << is a littled “hardcoded”, isn’t?

Sorry, it was a failure of mine. It works ok.

On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz C. [email protected] wrote:

my_array = MyArray.new
=> []

my_array << (“Header”, “Value”)

SyntaxError: compile error
(irb):25: syntax error, unexpected ‘,’, expecting ‘)’
my_array << (“Header”, “Value”)

The parser sees the << OPERATOR as taking a left and right argument,
and turns that into a message send to the left argument. If you want
to use additional arguments you need to be a bit more explicit and use
a little less syntactic sugar:

my_array.<<(“Header”,“Value”) # => [“Header: Value”]


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

2008/5/8, Iñaki Baz C. [email protected]:

2008/5/8, Iñaki Baz C. [email protected]:

Any reason for this? It seems that << is a littled “hardcoded”, isn’t?

Sorry, it was a failure of mine. It works ok.

Nooooooooo, it doesn’t work OK at all!!!

It just works if I call to the redefined << method with DOT and
arguments between ( ):

my_array.<<(“hola”,“pepe”) # Note the DOT in .<<
=> [“hola: pepe”]

my_array<<(“hola”,“pepe”) # Without DOT
SyntaxError: compile error
(irb):11: syntax error, unexpected ‘,’, expecting ‘)’
my_array<<(“hola”,“pepe”)
^
from (irb):11
from :0

Why??

Jason R. [2008-05-08 14:50]:

Any reason for this? It seems that << is a littled “hardcoded”, isn’t?


Iñaki Baz C.
[email protected]

The << operator is a special case handled by the parser, but you can
bypass that handling by calling the method directly:
the point is that you can’t call an operator with multiple
arguments. maybe something like this will suit you (note that you
don’t need to alias if you inherit from Array):

class MyArray < Array
def <<(a)
a = [
(a=*a)] # a.to_a.flatten_once :wink:
raise ArgumentError, “wrong number of arguments (#{a.size} for
2)” if a.size != 2

  super a.join(': ')
end

end

my_array = MyArray.new
my_array << [‘Header1’, ‘Value1’] # => [“Header1: Value1”]
my_array.<<(‘Header2’, ‘Value2’) # => [“Header1: Value1”,
“Header2: Value2”]

cheers
jens

2008/5/8 Iñaki Baz C. [email protected]:

                              ^
                              from (irb):11
                              from :0

Why??

As others have pointed out it is not an issue of method #<< but of the
syntax. In other words, the syntax allows for << just one argument to
the left and one to the right (similar to #+ and all other binary
operators). While you can define the method #<< to accept any number
of arguments the parser simply won’t call it with more than one
argument because that is a syntax error:

15:23:08 $ ruby -ce ‘1 << 2’
Syntax OK
15:23:11 $ ruby -ce ‘1 << 2 3’
-e:1: syntax error, unexpected tINTEGER, expecting $end
15:23:14 $ ruby -ce ‘1 << 2,3’
-e:1: syntax error, unexpected ‘,’, expecting $end
1 << 2,3
^
15:23:16 $

HTH

Kind regards

robert

2008/5/8, Jens W. [email protected]:

  raise ArgumentError, "wrong number of arguments (#{a.size} for

my_array.<<(‘Header2’, ‘Value2’) # => [“Header1: Value1”,
“Header2: Value2”]

Thanks to all. Finally I’ll just create a “add” method that will call
internally to << method using appropiate syntax:
self.<< (k, v)

Thanks.

Why can’t I redefine “<<” method to allow two parameters?
Posted by Iñaki Baz C. (Guest) on 08.05.2008 14:42
Hi, very exrtange:

my_array << (“Header”, “Value”)

This seems to work as well:

ruby -e ‘p [1,2,3] << 4 << 5’
#=> [1, 2, 3, 4, 5]

Cheers,

j.k.

Hi –

On Thu, 8 May 2008, Iñaki Baz C. wrote:

  a = [*(a=*a)]  # a.to_a.flatten_once ;-)

my_array << [‘Header1’, ‘Value1’] # => [“Header1: Value1”]
my_array.<<(‘Header2’, ‘Value2’) # => [“Header1: Value1”,
“Header2: Value2”]

Thanks to all. Finally I’ll just create a “add” method that will call
internally to << method using appropiate syntax:
self.<< (k, v)

I would just use Array#push:

[1,2,3].push(4,5)
=> [1, 2, 3, 4, 5]

David

Hi –

On Fri, 9 May 2008, Jimmy K. wrote:

ruby -e ‘p [1,2,3] << 4 << 5’
#=> [1, 2, 3, 4, 5]

What do you guys have against #push? :slight_smile:

David

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

David A. Black wrote:

|> ruby -e ‘p [1,2,3] << 4 << 5’
|> #=> [1, 2, 3, 4, 5]
|
| What do you guys have against #push? :slight_smile:

Nothing that works. :stuck_out_tongue_winking_eye:

Seriously, though: I prefer it. It makes it explicit what I’m doing.

No confusion possible with, say, a HERE doc (sp?), or a bitshift
operator.


Phillip G.
Twitter: twitter.com/cynicalryan
Blog: http://justarubyist.blogspot.com

~ - You know you’ve been hacking too long when…
…you almost get hit by a bus that pulled away from the stop without
looking and you say: PANIC: bus error
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.8 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkgjIWgACgkQbtAgaoJTgL8LNwCglHoCwu4F0n7zBSfKSQ+HySkm
9KEAnRRD2lzMy500iinYqwi+yPTqWMYj
=TxDg
-----END PGP SIGNATURE-----

On Thu, May 8, 2008 at 10:18 AM, David A. Black [email protected]
wrote:

Hi –

On Thu, 8 May 2008, Iñaki Baz C. wrote:

don’t need to alias if you inherit from Array):
end
internally to << method using appropiate syntax:
=> [1, 2, 3, 4, 5]
We seem to have lost track of what the OP was trying to do,

class MyArray < Array
alias original_add <<
def <<(n,k)
original_add “#{n}: #{k}”
end
end

He wants

[1,2,3].whatever_the_heck_he_decides_to_call_it(4,5) #=> [1,2,3, “4:5”]


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

2008/5/8 Rick DeNatale [email protected]:

[1,2,3].whatever_the_heck_he_decides_to_call_it(4,5) #=> [1,2,3, “4:5”]

There is always the option to work with an intermediary:

irb(main):001:0> class MyArray < Array
irb(main):002:1> ArrayAppender = Struct.new :array, :name do
irb(main):003:2* def <<(value)
irb(main):004:3> array.push “#{name}: #{value}”
irb(main):005:3> end
irb(main):006:2> end
irb(main):007:1> def <<(name)
irb(main):008:2> ArrayAppender.new self, name
irb(main):009:2> end
irb(main):010:1> end
=> nil
irb(main):011:0> a = MyArray.new
=> []
irb(main):012:0> a << 4 << 5
=> [“4: 5”]
irb(main):013:0>

Kind regards

robert