

(1..100).inject(&:+) - mightybyte
http://weblog.raganwald.com/2008/02/1100inject.html

======
mhartl
I use Symbol#to_proc every day. I've never cared for the term "inject", though
(or Python's "reduce", for that matter); I find SICP's "accumulate" much more
mnemonic.

For what it's worth,

(1..100).to_a.sum

works in Rails, though

(1..100).sum

doesn't.

------
Xichekolas
Hahaha... Reg, it's like you wrote this in response to the recent article on
Monkeypatching floating around here... Thanks! I enjoyed your writing as much
as always... and it's especially timely today.

(<http://news.ycombinator.com/item?id=123071> if you don't know to which I am
referring.)

~~~
raganwald
Weeeel...

The truth is, I wrote the idea behind this a while back using String#to_proc
to compare the way Ruby (roll your own) and Python (Guido decides) evolve. But
considering I have no Python experience, I never published the post.

Then today, for some reason, I was thinking about Open Classes again :-)

------
spydez
Anyone want to explain that code to someone who doesn't know Ruby?

~~~
gregwebs
The way to write this in ruby without extending the symbol class is

    
    
      (1..100).inject { |acc, n| acc + n }
    

inject is a left fold or a reduce- it applies the function {acc + n} to each
element in a list (or array) where acc is the result of the last function
application.

For such a simple function, all we need is the knowledge that we are adding,
which is contained in the symbol '+', representing the addition method. So
Ideally we would like to write

    
    
      (1..100).inject( :+ )
    

The semicolon is how you tell ruby you are using a symbol. Yes, you can write
a simple sum function, but the point is that this code is more flexible in a
very powerful way- we can use other functions then inject and add.

Method calling in Ruby is actually message passing. So instead of calling

    
    
       1.+ 2   # => 3
    

You can say

    
    
      1.send( :+, 2 )   # => 3
    

So we are not trying to convert a symbol to a proc. What we are trying to do
is continually send the message ':+' to inject's built in accumulator, with
every member of the list (or array) as an argument.

In ruby, the brackets are like a function, but it is actually a closure of
class Proc. You can convert a different class to a proc (if it supports it) by
calling to_proc.

Ruby has a syntactic shortcut, '&' for converting to a proc. Normally it
actually makes the code clearer because it is also used when passing Procs
onto other methods, and is a nice type annotation. So we can hack this
syntactic shortcut to create

    
    
      (1..100).inject( &:+ )
    

So by defining how '&' works by defining to_proc, we can make it create a
closure (or Proc) which sends the ':+' symbol, along with any arguments that
are yielded to the Proc. In this case, every value from (2..100) is yielded to
the Proc. (1 will be the starting value of the accumulator.)

You can accomplish a lot of things with a closure, including this hack. But to
me this shows that ruby was not designed as a functional programming language,
and how by using Ruby's dangerous flexibility you can manage to warp it
towards your needs.

After learning more languages, Ruby is starting to become pretty ugly to me,
but somehow people keep managing to ignore all its faults, make little hacks
like these, and be very productive with it.

~~~
raganwald
"After learning more languages, Ruby is starting to become pretty ugly to me,
but somehow people keep managing to ignore all its faults, make little hacks
like these, and be very productive with it."

When I first saw it, I wondered why anyone would want this irregular little
language when they could just use Smalltalk or Scheme. An early rant asked why
I have to know the difference between a block and a Proc: why the &^(%*)(& do
I have to know when to use a block, when to use a Proc, and how to convert
between them???

~~~
mdemare
For those who think the above is pretty tame and have been using it for years,
we've got a series on our blog where we introduce and discuss a new method
every day.

<http://blog.rubyenrails.nl/articles/category/daily_method>

Here we create a to_proc method for Hash:
[http://blog.rubyenrails.nl/articles/2008/02/26/a-hash-is-
a-f...](http://blog.rubyenrails.nl/articles/2008/02/26/a-hash-is-a-function-
hash-to_proc)

~~~
raganwald
I subscribe to the series and enjoy it. I hadn't seen Hash#to_proc, I look
forward to considering the possibilities carefully...

------
henning
The VB.NET equivalent is Enumerable.Range(1, 100).Sum, which seems clearer to
me. Why is this so impressive? If Visual Basic comes close to your beloved
code snippet, it's probably not that big of a deal.

In real life, the answer is to know some math and realize that 1 + ... + n =
n(n+1)/2, so the entire thing is pointless anyway.

(And if you want to add methods to a given class ad-hoc, you can do it
statically with extension methods; Sum is an extension method.)

~~~
raganwald
The article does _not_ claim that this is a good thing! It claims that the
line of code says a lot about Ruby the language.

~~~
henning
That it's obsessed with obfuscatory, slow language constructs?

~~~
raganwald
Let me ask you a question: you arrived at the top of the article with a
preconceived idea about Ruby. Did reading the article give you any insight,
did you learn something about Ruby or about yourself by reading the post?

If not, please downmod it, I have failed.

~~~
mynameishere
_or about yourself_

At the risk of getting even _more_ downmods for saying true things here, can I
just point out that it's a little arrogant to pretend that a blog post about
Ruby is going to move someone towards self-actualization?

Anyway, have you failed? No. You wanted to show us your favorite line of Ruby
code, and you did.

As for me, I don't really have a favorite "one line" of code, but I fondly
remember when I was a kid typing in Nibble Magazine's "one and two-liner"
programs. Actually, the "lines" were lines as defined by the Apple II's
command line buffer limit. Here's an example:

[http://www.apple2.org.za/mirrors/ground.icaen.uiowa.edu/appl...](http://www.apple2.org.za/mirrors/ground.icaen.uiowa.edu/apple8/Pgms/rotatecube.bas)

Maybe I'm not a sufficiently abstract person. My favorite two lines of code
was an honest-to-god graphical car driving program in two lines of APPLESOFT
BASIC [1]. Two lines of code in a language so crappy it's basically a joke.
And yet...a full-on-graphical-car-racing program. I'm strongly tempted to
think that APPLESOFT BASIC is superior to Ruby, based on the evidence I've
seen.

Point is: The next time you show a feature of a langauge, maybe make it solve
a problem, or create something real, rather than just showing how few
characters it takes to do something banal. Adding numbers together? Seriously,
it's a solved problem.

[1] Sorry for the capital letters, but I'm in Apple mode now:

<http://www.apple2.org/images/Literature/a2/BlueBook.JPEG>

~~~
raganwald
"have you failed? No. You wanted to show us your favorite line of Ruby code,
and you did."

Actually, I wanted to discuss how Ruby's open classes promote language
innovation from the fringe, not to try to impress you with how clever that
line of code is.

"The next time you show a feature of a langauge, maybe make it solve a
problem, or create something real, rather than just showing how few characters
it takes to do something banal."

And there you have why my article failed you: you think it is about how useful
that line of code is, or how clever it is, or what problem it solves, when I
think it is an example of how Ruby is different from centrally planned
language.

Is it great code? Of course not. Symbol#to_proc may even be an evolutionary
dead end, AFAICT it's just a way to make OO code pretend that it's functional
code.

Your criticisms point out that I need to work harder on establishing and
communicating my theses, thank you.

------
rontr
If Symbol#to_proc is so great, I'd like to see how it can elegantly express
something that can't be hidden behind a simple library function. In any decent
language the programmer would write "sum(1,100)". Even if the function's
implementation in Python/Java/C++/Smalltalk/Lisp/etc required a few more
characters, it wouldn't be a meaningful difference. Does Symbol#to_proc add
any _real_ power to Ruby or beyond enabling such linguistic brain teasers?

~~~
raganwald
Your question takes my breath away. May I quote you?

~~~
rontr
Only if you first answer it.

~~~
raganwald
There are so many answers! Here are a few:

The article does not claim that (1..100).inject(&:+) is great. It claims that
it is a totemic example of Ruby code.

There is nothing that technique X can do that technique Y cannot do given that
X and Y are both Turing Equivalent. Of course you can write a library function
to sum numbers. Do you also need a library function for the product of
numbers?

If so, you now know of a salient difference between the two approaches. One
needs a function for each thing you want to do, the other gives you some
pieces you combine in different ways to do what you want. Is one better than
the other? That's up to you to decide, you are the programmer. Ruby lets you
write your program either way.

Now, Symbol#to_proc doesn't, in my opinion, add what I would call power.
That's because you can always use a block or a lambda wherever you would use a
symbol. But I may not have written the article well: the powerful and
dangerous feature in Ruby is not Symbol#to_proc, it's _Open Classes_.
Symbol#to_proc is an example of something you can do with an Open Class.
Something else you can do with an Open Class is Hash#to_proc. Something else
is Object#andand, a low-rent version of the Maybe Monad in Haskell.

I consider Open Classes to be powerful and dangerous. Am I advocating them? Of
course not, it is up to you to decide whether they are a good idea or not.
What I find interesting about them is that Rubyists are pushing the language
in new directions with them, like Symbol#to_proc. The idea of a language
growing from the fringe is also powerful and dangerous. The fringe is an
uneducated, seething mass.

------
mattjones
To some degree, using open classes is just how you write functions in Ruby.

Say there exists a class called Errors in some Ruby library. It doesn't have
an each() method, but I'd like it to. Nobody would complain if I wrote a
function each_error() which took an Errors object as an argument. Reopening
the Errors class and giving it an each() method is the way you do that in
Ruby, and it's not really any more dangerous.

~~~
foonamefoo
Then lets say you packaged that up as a library. Another guy did the same
thing, but it worked a little different. Now random code breaks.

~~~
ken
It turns out not to be a problem in practice. I could list the 20 things I
hate most about Ruby and the 20 things I hate most about Rails, and this
wouldn't make either list. I don't know that I've ever seen it happen.

And on the "technically, could it happen?" side, sure, it could. You can also
write a Java library that, in weird cases, could screw up other Java
libraries, but the Java folks (even as much as they love to try to keep you
safe) don't care, either.

Besides, "each" is quite standard in Ruby. Defining it to mean something other
than "call the proc with each element, in order" would be weirdbad, like a C++
programmer defining operator+ to mean subtraction. If you do something
weirdbad like that, your library deserves to lose.

------
mynameishere
That sort of thing, for all of its doubtless glories, represents nothing so
much as a contempt of the _next programmer_ who has to deal with it. We're
just moving bits and bytes around here, people. Please sum up the numbers and
don't introduce any mysteries into the plumbing.

 _ALL OF THE REAL INNOVATION IN SOFTWARE IS RELATED TO THE PROBLEM DOMAIN AND
NOT THE LANGUAGE_

~~~
pg
If you're saying something that's actually true, you don't need to use all
uppercase.

~~~
mynameishere
ONE PLUS ONE EQUALS TWO.

God, I hope I didn't just rip open the space/time continuum.

~~~
futureNameHere
Indeed you did. I'm from the future to tell you that really don't need to use
caps.

------
Tichy
Actually he is wrong about Java: people did add features to it without
changing Java itself, for example AspectJ, and CLIB (I think is the name) that
generates Java Code on the fly. Hibernate uses it, for example, to change the
behaviour of the mapped Objects behind the scene.

~~~
raganwald
You would be amazed what people will do to Java. Just the other day I was
reading something here about writing Java code using an Excel spread sheet.
I'm pretty sure that wasn't in any of the JSRs.

------
akehurst
Why I hate ruby.

~~~
mrtron
Since I don't use ruby either...I tried a web based interpreter.

    
    
       >> (1..100).inject(&:+)                                                 
       TypeError: wrong argument type Symbol (expected Proc)                   
         from (irb):1         
    

I also am not a fan of doing things a thousand different obscure ways. I like
doing things one way, and having that way highly optimized. Typing 10
characters or 20 characters doesn't impact my programming speed, I spend far
more time thinking about how to do things the right way.

edit:

Ok, did his monkeypatch and it worked. You get 5050. So it is equiv to
sum(range(101)) in python, and much less readable. I fail to see why this is a
good thing.

~~~
raganwald
"I fail to see why this is a good thing."

Why _what_ is a good thing? Why that line of code is a good thing? maybe it
isn't, maybe arrays need a sum method, maybe you could just write:

(1..100).inject { |acc, n| acc + n }

...and get the same result. But the article has nothing to do with why that
line of code is a good thing, it is about the fact that being able to modify
the Symbol class in this manner is what makes a langauge like Ruby evolve from
the bottom up.

So... do you think _that_ is a good thing? Or a bad thing?

~~~
mrtron
I think that style of code is rather hard to read and really doesn't add any
functionality that couldn't be done in a much more readable way in the same
number of characters.

So I am wondering why the author thinks its so fantastic.

As for developing the language, I am usually for flexibility and allowing
anything to be modified, however this type of change strikes me as not very
useful.

~~~
raganwald
"I am usually for flexibility and allowing anything to be modified, however
this type of change strikes me as not very useful."

That's entirely the point. If you are in favour of flexibility, you have to
accept that people will use it for all sorts of things, not just ones you
like.

~~~
mrtron
I was talking about the fact that they are making that change on the core
language. Providing the flexibility is different from putting it in the
language.

Anyways, I don't really care, saying anything other than 'I love ruby' is
shunned anyways.

~~~
raganwald
"saying anything other than 'I love ruby' is shunned anyways."

Well... I welcome criticism of Ruby. Please say whatever you like in a comment
right on the post.

I've never shied away from writing about the things in Ruby that irritate me.
How else will we progress if we don't scratch when we have an itch?

------
dusklight
So just out of curiosity .. what do you think is the most beautiful way to
right the equivalent code in arc?

~~~
tel
In this case, the "equivalent" code isn't a line that produces the same
result, but is instead a line that illustrates the dynamic culture of the
given language's evolution.

For Arc, right now, practically every line is an equivalent.

~~~
dusklight
Well okay let me elaborate on my question.

pg has stated that code brevity is one of the main design goals of arc. But
what is pretty obvious is that code brevity is not the only consideration. It
is desirable to be able to write very short code, but it should be readable as
well. If you write very short code that is difficult for other people to read,
that is bad enough. If you write very short code that ends up being difficult
even for yourself to read -- then we have a problem.

The above ruby code snippet is a great example of code where reducing the
length not only did not reduce readability, but actually increased it. I know
some people have complained about it being obfuscated on this board. But to
me, and I am sure to a number of other people on this board, it was easy to
understand, intuitive even.

so .. in arc, what would be a similar way to create a list of numbers from 1
to 100, and to evaluate the sum of that list?

~~~
tel
That question is somewhat interesting just a little off-topic in this thread.

In Arc, that line would be:

    
    
       (reduce + (range 1 100))
    

which is nice, but not much different from Scheme. Pretty readable.

------
kommissar
What does the &: do in Ruby?

~~~
raganwald
Actually, it's &(:+) not &:(+). The & takes its argument and converts from a
Proc to a block. :+ is a symbol that implements the method #to_proc to give
you a block that sums its receiver and its argument.

~~~
kommissar
Oh, cool. I knew the colon meant a Ruby symbol, but I did not know that you
could use & to convert a Proc to block.

