It's possible to call a lambda from another lambda:
first = -> { 'Ok' }
second = -> { first.call }
puts second.call
# => 'Ok'
but when the order is reversed:
first = -> { second.call }
second = -> { 'Ok' }
puts first.call
the code fails with a NameError
:
lambda_order.rb:1:in `block in <main>': undefined local variable or method `second' for main:Object (NameError)
Did you mean? send
from lambda_order.rb:3:in `<main>'
even though :second
seems to be a local variable inside the scope of first
:
first = -> { local_variables }
second = -> { 'Ok' }
p first.call
# => [:first, :second]
I only use lambdas for golfing purposes so I'm not sure what's going on with the scope. Replacing second
by a method or a constant lambda fixes the NameError
. It seems related to this question but in my case, both lambdas are defined in main
.
Could you please explain?
first = -> { defined? second }
second = -> { 'Ok' }
p first.call
results nil => The variable "second" is not defined in the lambda "first".
first = -> { binding.receiver }
second = -> { 'Ok' }
p first.call
results main => This means that it uses the current binding of main and thus the variable "second" is defined only in the binding.
first = -> { binding.local_variable_get(:second).call }
second = -> { 'Ok' }
p first.call
results "Ok". That's why the code also prints "Ok" when I ask for the content of the variable "second" of the binding.
Summary: The variable "second" is not defined in the lambda "first". The variable "second" is only defined in the binding. Therefore, the output of "local_variables" also returns "second" because the information is retrieved from the binding.
I also learned something myself. I hope I could help you!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With