deffooo=Object.newlocal_var='local_var'method_lambda=->{local_var}o.define_singleton_method(:lambda_method,&method_lambda)method_proc=o.method(:lambda_method).to_procputsmethod_proc.()putseval('local_var',method_lambda.binding)putso.lambda_methodputseval('local_var',method_proc.binding)# undefined local variable or method `local_var'endfoo
when executed as a method it has access to local_var as expected
but the binding of the bound method proc does not
deffooo=Object.newlocal_var='local_var'method_lambda=->{local_var}o.define_singleton_method(:lambda_method,&method_lambda)method_proc=o.method(:lambda_method).to_procputsmethod_proc.()putseval('local_var',method_lambda.binding)putso.lambda_methodputseval('local_var',method_proc.binding)# undefined local variable or method `local_var'endfoo
when executed as a method it has access to local_var as expected
but the binding of the bound method proc does not
in ruby 2.2.2 the above code crashes the vm
should also underscore that the bound method proc has access to local_var: method_proc.()
but its binding does not eval('local_var', method_proc.binding), so there's a clear discrepancy between a proc and its binding
Subject changed from for methods defined from procs, the binding of the resulting bound method proc does not have access to the original proc's closure environment to for methods defined from procs, the binding of the resulting bound_method.to_proc does not have access to the original proc's closure environment
ruby -v changed from ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux] to ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
deffooo=Object.newlocal_var='has access to captured variable'original_proc=->{local_var}o.define_singleton_method(:method_from_proc,&original_proc)method_proc=o.method(:method_from_proc).to_procputs"original_proc.call #{original_proc.()}"puts"original_proc.binding #{original_proc.binding.eval('local_var')}"puts"#method_from_proc #{o.method_from_proc}"puts"method(:method_from_proc).to_proc.call #{method_proc.()}"puts"method(:method_from_proc).to_proc.binding #{method_proc.binding.eval('local_var')rescue"does not have access to captured variable: #{$!.inspect}"}"endfoo
method(:method_from_proc).to_proc.binding does not have access to captured variable: #<NameError: undefined local variable or method local_var'`
Local variables are not set up in the context of a binding from a method.
$ruby-e'def m(v=12);v;end; p method(:m).to_proc.binding.eval("v")'Traceback(mostrecentcalllast):2:from-e:1:in`<main>'
1: from -e:1:in `eval'
-e:1:in `<empty iseq>':undefinedlocalvariableormethod`v' for main:Object (NameError)
Local variables are not set up in the context of a binding from a method.
$ruby-e'def m(v=12);v;end; p method(:m).to_proc.binding.eval("v")'Traceback(mostrecentcalllast):2:from-e:1:in`<main>'
1: from -e:1:in `eval'
-e:1:in `<empty iseq>':undefinedlocalvariableormethod`v' for main:Object (NameError)
You are accessing a local variable in the method (which does not exist until the method is invoked), whereas I am accessing a variable outside the method, captured by the proc that defined the method, which does exist outside the invocation of the method. So your example does not explain the behavior that I am highlighting.
To try answer my own question, I can see how this might not be a bug if method.to_proc returns a proc that is no way related to the proc that defined the method. Such a proc simply forwards the args to the method and knows nothing about the original proc binding. I initially thought that it would somehow inherit the binding of the original proc.