0

I'm learning about the use of symbols in Ruby and have realized they act largely as references to variables, keys in hash tables, and even as a way of sending blocks in methods.

My questions is, what exactly are symbols, such as :+ :- :*, referencing when I use them in a method?

e.g. using :+ to sum all the values in an array:

puts [1,2,3].reduce(:+) 
 => 6

gives the same result as:

puts [1,2,3].reduce {|sum, i| sum += i}
=> 6

and if I create my own version of :+

a = lambda {|sum,i| sum += i}
puts [1,2,3].reduce(&a)
=> 6

My first thought is therefore that :+ references {|sum, i| sum += i} as an explicit block but I've had trouble finding information to confirm that.

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367

2 Answers2

5

The symbol you pass to reduce will be interpreted as a name of a method to call on each element. So this

collection.reduce(:foo)

is equivalent to this

collection.reduce { |memo, element| memo.foo(element) }

The reason it works with sums is that + operator is actually just a method on numbers.

 1.+(3) # => 4

My first thought is therefore that :+ references {|sum, i| sum += i} as an explicit block

Not sure what you mean there, but :+ most certainly does not reference this block. Or any block. Or anything.

Symbols are just names. They don't point to anything. Deciding what they mean is up to the code that uses them.

Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
  • Aha! So in my example, .reduce takes the :+ symbol and associates it with one of its methods? Thank you for your response! – Einar Stensson Dec 23 '15 at 15:47
  • Yes, `+` method will be called on each element of the collection being reduced. In this case elements are number which actually _do_ have such method. This wouldn't work as well with, say, Books. – Sergio Tulentsev Dec 23 '15 at 15:50
4

A symbol is not a reference to variables, keys in hash tables, or as a way of sending blocks as you claim. The truth is that a symbol is used to describe these things as designed by the person who wrote the respective method that uses them, and actual mapping of a symbol to these things is done within the respective method.

For you particular example, :+ is not referencing {|sum, i| sum += i}, or any other block; it is a peculiarity of the alternative syntax of reduce that allows a symbol to be passed, and converts that symbol to a block. The corresponding block, though close to it, it not what you thought, but is: {|sum, i| sum + i}.

sawa
  • 165,429
  • 45
  • 277
  • 381