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?

···

--
Iñaki Baz Castillo
<ibc@aliax.net>

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.

···

On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

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?

--
Iñaki Baz Castillo
<ibc@aliax.net>

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

···

2008/5/8, Iñaki Baz Castillo <ibc@aliax.net>:

Any reason for this? It seems that << is a littled "hardcoded", isn't?

--
Iñaki Baz Castillo
<ibc@aliax.net>

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"]

···

On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

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")

--
Rick DeNatale

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

> 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

Why??

···

2008/5/8, Iñaki Baz Castillo <ibc@aliax.net>:

2008/5/8, Iñaki Baz Castillo <ibc@aliax.net>:

                                   from :0

--
Iñaki Baz Castillo
<ibc@aliax.net>

Jason Roelofs [2008-05-08 14:50]:

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?

--
Iñaki Baz Castillo
<ibc@aliax.net>

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

···

On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

--
Jens Wille, Dipl.-Bibl. (FH)
prometheus - Das verteilte digitale Bildarchiv für Forschung & Lehre
Kunsthistorisches Institut der Universität zu Köln
Albertus-Magnus-Platz, D-50923 Köln
Tel.: +49 (0)221 470-6668, E-Mail: jens.wille@uni-koeln.de
http://www.prometheus-bildarchiv.de/

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 Iñaki Baz Castillo <ibc@aliax.net>:

2008/5/8, Iñaki Baz Castillo <ibc@aliax.net>:

2008/5/8, Iñaki Baz Castillo <ibc@aliax.net>:

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

--
use.inject do |as, often| as.you_can - without end

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

Thanks.

···

2008/5/8, Jens Wille <jens.wille@uni-koeln.de>:

Jason Roelofs [2008-05-08 14:50]:

> On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:
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"]

--
Iñaki Baz Castillo
<ibc@aliax.net>

Hi --

Jason Roelofs [2008-05-08 14:50]:

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"]

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

···

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

2008/5/8, Jens Wille <jens.wille@uni-koeln.de>:

On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz Castillo <ibc@aliax.net> wrote:

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

Why can't I redefine "<<" method to allow two parameters?
Posted by Iñaki Baz Castillo (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.

···

--
Posted via http://www.ruby-forum.com/\.

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"]

···

On Thu, May 8, 2008 at 10:18 AM, David A. Black <dblack@rubypal.com> wrote:

Hi --

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

> 2008/5/8, Jens Wille <jens.wille@uni-koeln.de>:
>
> > Jason Roelofs [2008-05-08 14:50]:
> >
> >
> > > On Thu, May 8, 2008 at 8:42 AM, Iñaki Baz Castillo <ibc@aliax.net> > wrote:
> > >
> > 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"]
> >
>
>
> 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]

--
Rick DeNatale

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

Hi --

···

On Fri, 9 May 2008, Jimmy Kofler wrote:

Why can't I redefine "<<" method to allow two parameters?
Posted by Iñaki Baz Castillo (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]

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

David

--
Rails training from David A. Black and Ruby Power and Light:
   INTRO TO RAILS June 9-12 Berlin
   ADVANCING WITH RAILS June 16-19 Berlin
   INTRO TO RAILS June 24-27 London (Skills Matter)
See http://www.rubypal.com for details and updates!

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

···

2008/5/8 Rick DeNatale <rick.denatale@gmail.com>:

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"]

--
use.inject do |as, often| as.you_can - without end

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