Calling a block with some context


#1

I would like to be able to call a block / proc / lambda with the current
context (as well as the context it was created in):

def make_proc
Proc.new {puts from_calling_context}
end

proc = make_proc
from_calling_context = ‘Hello from the calling context’
call_with_my_context( proc )

… Something like that.

Thanks for any thoughts,
Benjohn


#2

On Tue, 2006-05-02 at 17:17 +0900, removed_email_address@domain.invalid wrote:

I would like to be able to call a block / proc / lambda with the current
context (as well as the context it was created in):

def make_proc
Proc.new {puts from_calling_context}
end

proc = make_proc
from_calling_context = ‘Hello from the calling context’
call_with_my_context( proc )

This is something that’s been discussed quite a bit I think, with the
general conclusion being that it’s not possible to rebind procs like
this.

You can emulate it up to a point, but with some potentially serious
quirks, e.g:

require ‘facet/binding’
require ‘ostruct’

def call_with_my_context(blk)
Binding.of_caller do |b|
o = OpenStruct.new
b.local_variables.each { |v| o.send("#{v}=", b[v]) }
r = o.instance_eval(&blk)
o.methods.select { |m| m =~ /[^=]=$/ }.each { |v| v = v[0…-2]; b[v]
= o.send(v) }
r
end
end

def make_proc
avar = :lex_scope
Proc.new do |ret| # only need arg if you want to change vars outside
the proc
puts avar
puts from_calling_context;
ret.from_calling_context = ‘changed’ # such as here
“result”
end
end

blk = make_proc
from_calling_context = ‘Hello from the calling context’
puts call_with_my_context(blk)
puts from_calling_context

Outputs: