a lambda: is_even = ->(n) { n % 2 == 0 } is_even.call(2) is_even.(2) is_even[2] # Don't do this! is_even === 2 # Don't do this either! case 2 when is_even # (case equality, ===) puts 'is even' end
instances (lambda and non lambda) • Modules or Classes with a `call` class method • Instances of classes having a `call` instance method • Any other object having a `call` method added to it directly.
end class C; def self.call; end end class I; def call; end end p callable?(-> {}) # -> true p callable?(Proc.new {}) # -> true p callable?(C) # -> true p callable?(I.new) # -> true The .() abbreviation can be used to call any and all of these!
is expected by preceding it with &. logger = MyLogger.new # The usual case is to pass a code block like this: logger.info { 'I am inside a block' } # But we can instead adapt a lambda: proclaimer = -> { 'I am inside a lambda' } MyLogger.new.info(&proclaimer) Using a Lambda Where a Code Block is Expected
can use a method where a lambda is expected using this notation: lambda(&method(:foo)) def foo puts 'Hello, world.' end fn = lambda(&method(:foo)) fn.() # Hello, World
ed the same way as in a code block: lambda { |param1, param2| } lambda do |param1, param2| end Lambda Syntax In the "stabby lambda" alternate syntax for Ruby versions >= 1.9, the parameter syntax is identical to method syntax: ->(param1, param2) {} ->(param1, param2) do end
anything interesting about the structure? def compute_something(input) compute_part = ->(part) do # ... end [compute_part.(input.left), compute_part.(input.right)] end left_part, right_part = compute_something(input) Imagine there were several lambdas there, and not only one. We can use lambdas as local nested functions:
to a Class class ComputerOfSomething def compute_part(part) # ... end # other lambdas would also be converted to methods def compute(input) [compute_part(input.left), compute_part(input.right)] end end left_part, right_part = ComputerOfSomething.new.compute(input)
compute_part(part) # ... end # other lambdas would also be converted to methods def compute(input) [compute_part(input.left), compute_part(input.right)] end end end left_part, right_part = ComputerOfSomething.compute(input)
# complex and long running task #1 fetch_type_2_data = -> { `whoami` } # complex and long running task #2 type_1_data, type_2_data = [ Thread.new(&fetch_type_1_data), Thread.new(&fetch_type_2_data), ].map(&:value) # now do something useful with type_1_data and type_2_data. puts "\nType 1 data:"; ap type_1_data puts "\nType 2 data:"; ap type_2_data
and Bindings name = 'Joe' f = -> { puts "Name is #{name}" } f.() # 'Name is Joe' f.binding.eval("name = 'Anil'") f.() # 'Name is Anil' name # 'Name is Anil'
using the send method: class ClassWithPrivateMethod private def my_private_method puts "Hey! You're invading my privacy!" end end ClassWithPrivateMethod.new.send(:my_private_method) # --> Hey! You're invading my privacy.
ClassWithLocalLambda def foo my_local_lambda = -> do puts "You can't find me." end # ... end end Can’t access this lambda from outside this method. So you can't get to it with a unit test either.
(event) do puts "This event occurred: #{ event}" end something.add_event_handler(event_handler) # Or, even more concisely, by eliminating the intermediate variable (this notation is very similar to # block notation): something.add_event_handler( -> (event) do puts "This event occurred: #{ event}" end)
call(n) n.even? end end class OddFilter def call(n) n.odd? end end def filter_one_to_ten(filter) (1 .. 10).select { |n| filter.(n) } end puts filter_one_to_ten(EvenFilter.new).to_s # [2, 4, 6, 8, 10]
lambdas instead, we can dispense with the ceremony and verbosity of classes. See how much simpler the code is! even_filter = -> (n) { n.even? } odd_filter = -> (n) { n.odd? } def filter_one_to_ten(filter) (1 .. 10).select { |n| filter.(n) } end puts filter_one_to_ten(even_filter).to_s # [2, 4, 6, 8, 10]
fi lter as a parameter, defaulting to a fi lter that returns true for all messages. def get_messages(count, timeout, filter = -> (_message) { true }) messages = [] while messages.size < count message = get_message(timeout) messages << message if filter.(message) end messages end
the code block approach is cryptic and not intention-revealing. The parameter list does not reveal that a fi lter is being passed. def get_messages(count, timeout) messages = [] while messages.size < count message = get_message(timeout) messages << message if (! block_given?) || yield(message) end messages end
be seen at https://github.com/keithrbennett/trick_bag/blob/master/lib/trick_bag/enumerables/bu ff ered_enumerable.rb. # Creates an instance with lambdas for fetch and fetch notify behaviors. # @param chunk_size the maximum number of objects to be buffered # @param fetcher lambda to be called to fetch to fill the buffer # @param fetch_notifier lambda to be called to when a fetch is done def self.create_with_lambdas(chunk_size, fetcher, fetch_notifier = nil)
module M CREATE_CLASS = -> do class ::IWasCreatedByALambda # ... end end def self.create_class CREATE_CLASS.() end end M.create_class if some_condition # some real condition would go here puts IWasCreatedByALambda.new # => #<IWasCreatedByALambda:0x000000010efabd88>
to the process of fi xing a number of arguments to a function, producing another function of smaller arity.” - Wikipedia fn_multiply_by = -> (factor) do -> (n) { factor * n } end tripler = fn_multiply_by.(3) tripler.(123) # => 369
and not a lambda that performs the partial application: def fn_multiply_by(factor) -> (n) { factor * n } end tripler = fn_multiply_by(3) tripler.(123) # => 369 Partial Application
with arguments, returns another lambda in which those arguments are pre fi lled (i.e. no longer need to be passed). Currying multiply_2_numbers = -> (x, y) { x * y } tripler = multiply_2_numbers.curry.(3) tripler.(123) # => 369 # or multiply_2_numbers = -> (x, y) { x * y } currier = multiply_2_numbers.curry tripler = currier.(3) tripler.(123) # => 369