Created
September 23, 2014 04:54
-
-
Save ldanz/359dee688467a10f7fc2 to your computer and use it in GitHub Desktop.
Unary ampersand demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
###### Symbol#to_proc | |
# Putting & in front of a symbol calls the symbol's to_proc method (Symbol#to_proc) and then converts the proc into a block. | |
# | |
# &:foomethod converts :foomethod into a block that takes the first yieldparam as the receiver and any later yieldparams as | |
# argumentds and calls :foomethod | |
# Array#map yields one parameter, so it's the receiver, and you can only use methods that accept an empty param list. | |
p [1,2,3].map(&:succ) # => [2, 3, 4] | |
begin | |
[1,2,3].map(&:+) | |
rescue ArgumentError => e | |
p [e.class, e.message] # => [ArgumentError, "wrong number of arguments(0 for 1)"] | |
end | |
# Array#reduce yields two parameters, so the first one (the accumulator) is the receiver, and the second is passed in as the | |
# single argument to the method. | |
p [1,2,3].reduce(&:+) # => 6 | |
begin | |
p [1,2,3].reduce(&:succ) | |
rescue ArgumentError => e | |
p [e.class, e.message] # => [ArgumentError, "wrong number of arguments(1 for 0)"] | |
end | |
# A contrived example of an iterator (ManyFoos#iterate) that yields three parameters and a method (Foo#add_and_multiply) that | |
# takes two parameters. | |
class Foo | |
def initialize(x) | |
@x = x | |
end | |
def to_s | |
"Foo_#{@x}" | |
end | |
def add_and_multiply(sumand, multiplier) | |
self.class.new((@x + sumand) * multiplier) | |
end | |
end | |
class ManyFoos | |
def initialize(*args) | |
@foos = args.map { |arg| Foo.new(arg) } | |
end | |
def iterate | |
@foos.map do |foo| | |
yield(foo, 1, 3) | |
end | |
end | |
end | |
manyfoos = ManyFoos.new(4, 6, 8) | |
p manyfoos.iterate(&:add_and_multiply) # => [Foo_15, Foo_21, Foo_27] | |
###### Method#to_proc | |
# Putting & in front of a method calls the method's to_proc method (Method#to_proc) and then converts the proc into a block. | |
# | |
# &method(:foomethod) converts method(:foomethod) into a block that uses the current self as the receiver and uses all the | |
# yieldparams as arguments. | |
begin | |
[1,2,3].map(&method(:succ)) | |
rescue NameError => e | |
p [e.class, e.message] # => [NameError, "undefined method `succ' for class `Object'"] | |
end | |
# We'll define some methods on Bar and then call them using &method(:methodname), in a context where self is Bar | |
module Bar | |
def self.add_one(x) | |
x + 1 | |
end | |
def self.add_numbers(x, y) | |
x + y | |
end | |
def self.array_map_add_one(array) | |
array.map(&method(:add_one)) | |
end | |
def self.array_map_add_numbers(iterator) | |
iterator.reduce(&method(:add_numbers)) | |
end | |
end | |
# An example with one yieldparam | |
p Bar.array_map_add_one([1,2,3]) # => [2, 3, 4] | |
# An example with two yield params | |
p Bar.array_map_add_numbers([1,2,3,4]) # => 10 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment