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

**URL:** <https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041>\
**Category:** Ruby\
**Created:** [May 8, 2008, 2:42pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041 "2008-05-08T14:42:57Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 2:42pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/1 "2008-05-08T14:42:57Z")

</div>

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?

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 2:51pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/2 "2008-05-08T14:51:14Z")

</div>

On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> my\_array = MyArray.new  
> Any reason for this? It seems that \<\< is a littled “hardcoded”, isn’t?
> 
> –  
> Iñaki Baz C.  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

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.

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 3:00pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/3 "2008-05-08T15:00:04Z")

</div>

2008/5/8, IÃ±aki Baz C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

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

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

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 3:01pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/4 "2008-05-08T15:01:15Z")

</div>

On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 3:03pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/5 "2008-05-08T15:03:37Z")

</div>

2008/5/8, IÃ±aki Baz C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> 2008/5/8, IÃ±aki Baz C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):
> 
> > 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??

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 3:20pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/6 "2008-05-08T15:20:17Z")

</div>

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

> > Any reason for this? It seems that \<\< is a littled “hardcoded”, isn’t?
> > 
> > –  
> > Iñaki Baz C.  
> > [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
> 
> 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 😉  
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

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 3:25pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/7 "2008-05-08T15:25:05Z")

</div>

2008/5/8 Iñaki Baz C. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ```
> ^
> 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

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 3:32pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/8 "2008-05-08T15:32:10Z")

</div>

2008/5/8, Jens W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ```
> 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.

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 5:17pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/9 "2008-05-08T17:17:53Z")

</div>

> 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.

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 4:19pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/10 "2008-05-08T16:19:45Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 5:33pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/11 "2008-05-08T17:33:47Z")

</div>

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? 🙂

David

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 5:53pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/12 "2008-05-08T17:53:19Z")

</div>

-----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? 🙂

Nothing that works. 😜

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](http://twitter.com/cynicalryan)  
Blog: [http://justarubyist.blogspot.com](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](http://enigmail.mozdev.org)

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

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 8, 2008, 6:09pm UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/13 "2008-05-08T18:09:53Z")

</div>

On Thu, May 8, 2008 at 10:18 AM, David A. Black [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
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/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![ISSSSaki\_Baz\_C](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/i/51bf81/32.png) [@ISSSSaki\_Baz\_C](https://www.ruby-forum.com/u/ISSSSaki_Baz_C)\
**Post date:** [May 9, 2008, 8:41am UTC](https://www.ruby-forum.com/t/why-cant-i-redefine-method-to-allow-two-parameters/137041/14 "2008-05-09T08:41:50Z")

</div>

2008/5/8 Rick DeNatale [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> [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
