Why (1..4).inject(&:+) works?

Hi rubyists,

I was just wondering why,

(1..4).inject(&:+) #=> 10

works ? (in Ruby 1.9.2)

I understand easily these:

(1..4).inject { |s, e| s + e } #=> 10
(1..4).inject(:+) #=> 10

I suppose it's calling :+.to_proc #=> #<Proc:0x2f52d8>

def a(&b); b; end
a(&:+)

=> #<Proc:0x2f52d8>

:+.to_proc

=> #<Proc:0x2f52d8>

p = a(&:+)

=> #<Proc:0x2f52d8>

p.arity

=> -1

p.call(1,2)

=> 3

p.call(1)

ArgumentError: wrong number of arguments(0 for 1)
    ...

p.call(1,2,3)

ArgumentError: wrong number of arguments(2 for 1)
   ...

p.call

ArgumentError: no receiver given

Well, that's strange: arity = -1, so normally only optional arguments. And
it expects 1 argument but want 2 ?
"no receiver given" : That means it knows it has a argument to act on like
a.+(b). How come ?
Would &:+ knows it need some object to act with "+"(o) ?

Have a nice day

Hi,

Can anyone suggest a faster alternative to String.split()? I need to call it very intensively and its quite a hotspot. I'm using ruby 1.8.7.

Cheers,
James

Benoit Daloze wrote:

Hi rubyists,

I was just wondering why,

(1..4).inject(&:+) #=> 10

works ? (in Ruby 1.9.2)

Works in 1.8.7 too, FWIW.

···

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

Benoit Daloze wrote:

"no receiver given" : That means it knows it has a argument to act on
like
a.+(b). How come ?
Would &:+ knows it need some object to act with "+"(o) ?

a + b is syntactic sugar for a.+(b), or a.send(:+,b) - you can see that
you have one receiver, and one argument.

If you google "symbol to_proc" you'll find some 1.8 implementations. The
first hit I get is PragDave's blog where he shows this code:

  class Symbol
    def to_proc
      proc { |obj, *args| obj.send(self, *args) }
    end
  end

Well, that's strange: arity = -1, so normally only optional arguments. And
it expects 1 argument but want 2 ?

You can see why that is from the implementation above. The method call
must have a receiver (obj), but we know how many other arguments to
take, so it accepts zero or more. It passes them all as arguments to the
method, whose name is the symbol itself.

···

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

irb(main):001:0> 1.send(:+)
ArgumentError: wrong number of arguments(0 for 1)
  from (irb):1:in `+'
  from (irb):1
  from /Users/rick/.rvm/ruby-1.9.1-p243/bin/irb:12:in `<main>'
irb(main):002:0> 1.send(:+, 2)
=> 3
irb(main):003:0> 1.send(:+, 2, 3)
ArgumentError: wrong number of arguments(2 for 1)
  from (irb):3:in `+'
  from (irb):3
  from /Users/rick/.rvm/ruby-1.9.1-p243/bin/irb:12:in `<main>'

···

On Thu, Oct 29, 2009 at 2:14 PM, Benoit Daloze <eregontp@gmail.com> wrote:

Hi rubyists,

I was just wondering why,

(1..4).inject(&:+) #=> 10

works ? (in Ruby 1.9.2)

I understand easily these:

(1..4).inject { |s, e| s + e } #=> 10
(1..4).inject(:+) #=> 10

I suppose it's calling :+.to_proc #=> #<Proc:0x2f52d8>

> def a(&b); b; end
> a(&:+)
=> #<Proc:0x2f52d8>
> :+.to_proc
=> #<Proc:0x2f52d8>

> p = a(&:+)
=> #<Proc:0x2f52d8>
> p.arity
=> -1
> p.call(1,2)
=> 3
> p.call(1)
ArgumentError: wrong number of arguments(0 for 1)
...
> p.call(1,2,3)
ArgumentError: wrong number of arguments(2 for 1)
...
> p.call
ArgumentError: no receiver given

Well, that's strange: arity = -1, so normally only optional arguments. And
it expects 1 argument but want 2 ?
"no receiver given" : That means it knows it has a argument to act on like
a.+(b). How come ?
Would &:+ knows it need some object to act with "+"(o) ?

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

use ruby inline

···

On Fri, Oct 30, 2009 at 03:23:01AM +0900, James French wrote:

Hi,

Can anyone suggest a faster alternative to String.split()? I need to call it very intensively and its quite a hotspot. I'm using ruby 1.8.7.

Cheers,
James

I can suggest you not thread hijack anymore. It is rude and messes up people who use real mail clients. Start a new mail.

···

On Oct 29, 2009, at 11:23 , James French wrote:

Can anyone suggest a faster alternative to String.split()? I need to call it very intensively and its quite a hotspot. I'm using ruby 1.8.7.

In fact, I knew about about the 1.8 implementations. I just forgot about it.
Thank to have cleared my ideas.

The current implementation looks like (of course it must be in C):

class Symbol
    def to_proc
        @to_proc ||= Proc.new { |*args| args.shift.send(self, *args) }
    end
end

···

2009/10/30 Rick DeNatale <rick.denatale@gmail.com>

On Thu, Oct 29, 2009 at 2:14 PM, Benoit Daloze <eregontp@gmail.com> wrote:
> Hi rubyists,
>
> I was just wondering why,
>
> (1..4).inject(&:+) #=> 10
>
> works ? (in Ruby 1.9.2)
>
> I understand easily these:
>
> (1..4).inject { |s, e| s + e } #=> 10
> (1..4).inject(:+) #=> 10
>
> I suppose it's calling :+.to_proc #=> #<Proc:0x2f52d8>
>
> > def a(&b); b; end
> > a(&:+)
> => #<Proc:0x2f52d8>
> > :+.to_proc
> => #<Proc:0x2f52d8>
>
> > p = a(&:+)
> => #<Proc:0x2f52d8>
> > p.arity
> => -1
> > p.call(1,2)
> => 3
> > p.call(1)
> ArgumentError: wrong number of arguments(0 for 1)
> ...
> > p.call(1,2,3)
> ArgumentError: wrong number of arguments(2 for 1)
> ...
> > p.call
> ArgumentError: no receiver given
>
> Well, that's strange: arity = -1, so normally only optional arguments.
And
> it expects 1 argument but want 2 ?
> "no receiver given" : That means it knows it has a argument to act on
like
> a.+(b). How come ?
> Would &:+ knows it need some object to act with "+"(o) ?

irb(main):001:0> 1.send(:+)
ArgumentError: wrong number of arguments(0 for 1)
        from (irb):1:in `+'
       from (irb):1
       from /Users/rick/.rvm/ruby-1.9.1-p243/bin/irb:12:in `<main>'
irb(main):002:0> 1.send(:+, 2)
=> 3
irb(main):003:0> 1.send(:+, 2, 3)
ArgumentError: wrong number of arguments(2 for 1)
        from (irb):3:in `+'
       from (irb):3
       from /Users/rick/.rvm/ruby-1.9.1-p243/bin/irb:12:in `<main>'

--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Thanks for the link - was not aware of that. Will definitely look into that.

···

-----Original Message-----
From: Reid Thompson [mailto:reid.thompson@ateb.com]
Sent: 29 October 2009 18:29
To: ruby-talk ML
Cc: Reid Thompson
Subject: Re: String.split

On Fri, Oct 30, 2009 at 03:23:01AM +0900, James French wrote:
> Hi,
>
> Can anyone suggest a faster alternative to String.split()? I need to
call it very intensively and its quite a hotspot. I'm using ruby 1.8.7.
>
> Cheers,
> James

use ruby inline

Was not being rude - was not aware of it. My mail client allows me to read and write text to people so its about as real as I need it to be.

···

-----Original Message-----
From: Ryan Davis [mailto:ryand-ruby@zenspider.com]
Sent: 29 October 2009 19:03
To: ruby-talk ML
Subject: Re: String.split

On Oct 29, 2009, at 11:23 , James French wrote:

> Can anyone suggest a faster alternative to String.split()? I need to
> call it very intensively and its quite a hotspot. I'm using ruby
> 1.8.7.

I can suggest you not thread hijack anymore. It is rude and messes up
people who use real mail clients. Start a new mail.