3

I'm writing a DSL for a project and I've run into an issue involving local variables bleeding into nested procs when I don't want them to. It seems like no matter what I try, I can't overwrite a local variable's value with something from another scope once it's been set into a proc's binding.

an example of what I'm trying to get to work:

class Obj
  def foo
    :foo
  end
end

def run_proc(context, &block)
  context.instance_exec(&block)
end

def run_example(context)
  # This `foo` the local var that ends up in the binding of
  # the proc on the next line that I can't seem to overwrite
  foo = :bar   
  run_proc(context) { foo }
  # ^ I want to be able to eval `foo` based on the passed context obj
end

obj = Obj.new
# I want all three of these calls to return `:foo`
obj.foo                   #=> :foo  # works as expected
obj.instance_exec { foo } #=> :foo  # works as expected
run_example(obj)          #=> :bar  # doesn't work, since the `run_example`
                                    #  method's local `foo` var takes precedence
                                    #  over the passed object's `foo` method

I did some digging around and found answers with a similar approach to what I've been trying: Change the binding of a Proc in Ruby. I've also looked into the possibility of undefining the local variables in a proc's binding but this answer claims doing so is impossible: Undefine variable in Ruby.

So my question now is this: Should I just give up trying to nest procs and/or find a workaround that doesn't have local var/method name conflict issues, or is there actually a way to get around this?

1 Answer 1

2

You can use self.foo explicitely

Using it will call the bindings of the object self currently refers to rather then the closure of the state when proc/block is created.

Sign up to request clarification or add additional context in comments.

1 Comment

foo() will also work as it enforces the method call over the local variable definition

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.