Skip to content

Instantly share code, notes, and snippets.

@ldanz
Created September 23, 2014 04:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ldanz/359dee688467a10f7fc2 to your computer and use it in GitHub Desktop.
Save ldanz/359dee688467a10f7fc2 to your computer and use it in GitHub Desktop.
Unary ampersand demo
#!/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