# Rebinding a Proc

**URL:** <https://www.ruby-forum.com/t/rebinding-a-proc/65569>\
**Category:** Ruby\
**Created:** [February 10, 2006, 9:43pm UTC](https://www.ruby-forum.com/t/rebinding-a-proc/65569 "2006-02-10T21:43:29Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 10, 2006, 9:43pm UTC](https://www.ruby-forum.com/t/rebinding-a-proc/65569/1 "2006-02-10T21:43:29Z")

</div>

Weird stuff ahead. I’m making (actually, remaking) a DSL. I’m  
re-visioning  
RHDL to take more advantage of metaprogramming tricks.

So I’d like the user to be able to declare a logic gate like so:

class AndGate \< RHDL  
inputs :a, :b  
inouts :bus  
outputs :a\_and\_b

```
define_behavior {
  puts "Inside of define_behavior: a is: #{a}, b is: #{b}"
  a_and_b = a & b
}

```

end

And then the user should be able to instantiate an AndGate like so:

andg = AndGate.instance() #optional args

The ‘inputs’, ‘inouts’ and ‘outputs’ methods create accessors for the  
signals  
at the class level so that they are then accessable in the block passed  
to  
define\_behavior.

Here’s some of the background from the RHDL class:

class RHDL  
class \<\< self  
def instance(\*args) #clones this class.  
puts “instance:self is: #{self}”  
klass = self.clone  
puts “klass.class is: #{klass.class}”  
klass  
end  
def define\_behavior(&b)  
@\_\_behavior = b  
puts “@behavior.class is: #{@\_\_behavior.class}”  
end  
def behavior  
@\_\_behavior  
end  
def run  
puts “in #{self}::run”  
puts "a is: #{a}, b is: #{b} "  
@\_\_behavior.call  
end  
def inports  
@\_\_inports ||=[]  
end  
def inoutports  
@\_\_inoutports ||=[]  
end  
def outports  
@\_\_outports ||=[]  
end  
def create\_accessor str  
instance\_eval “def #{str}=(val); puts “self is: #{self}”;  
@#{str} =  
val; end”  
instance\_eval “def #{str}; @#{str} ||=0; end”  
end  
def inputs \*in\_syms  
in\_syms.each {|input|  
inports \<\< Port.new(input.to\_s)  
create\_accessor input  
}  
end  
#… outputs, inouts, etc.  
end

Of course, the problem is in the block passed to the define\_behavior  
method.  
It’s defined within the context of the AndGate class definition above,  
so if  
we clone the AndGate class itself we find that the behavior is still  
determined  
by the context of the original AndGate class.

So If I do:

AndGate.a=1; AndGate.b=1  
AndGate.run #=\> 1

a = AndGate.instance()  
a.a=0; a.b=0  
a.run #=\> 1 (but should be 0; this is because the block is still  
evaluated  
in the context of AndGate class, not the clone of  
AndGate)

So when the AndGate class is cloned, is there a way to unbind the proc  
in the  
class’ @\_\_behavior class inst var and rebind it in the context of the  
new  
cloned class? (kind of what can be done with methods and UnboundMethod)

[I realize there are probably other ways to do this where this wouldn’t be an issue (use a method instead of a proc, for example) but I’m trying to maintain compatibility with the backend simulation guts of the current RHDL system.]

Phil

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 10, 2006, 11:15pm UTC](https://www.ruby-forum.com/t/rebinding-a-proc/65569/2 "2006-02-10T23:15:06Z")

</div>

You might want to replace this:

@\_\_behavior.call

… with this:

instance\_eval(&@\_\_behavior)

gegroet,  
Erik V. - [http://www.erikveen.dds.nl/](http://www.erikveen.dds.nl/)

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [February 10, 2006, 10:14pm UTC](https://www.ruby-forum.com/t/rebinding-a-proc/65569/3 "2006-02-10T22:14:07Z")

</div>

Sorry to respond to my own message, but sometimes it helps to write  
these  
things out. Here’s how I did it (look for changes in the RHDL class  
below):

> ```
> a_and_b = a & b
> 
> ```
> 
> class \<\< self  
> def instance(\*args) #clones this class.  
> puts “instance:self is: #{self}”  
> klass = self.clone  
> puts “klass.class is: #{klass.class}”  
> @ubm.bind(klass) #bind the unboundmethod to the cloned class  
> meth = klass.method(:do\_it) #get a method object from the newly  
> # bound ‘do\_it’ method.

```
   klass.set_behavior &meth #set cloned class' @__behavior proc
                               #to the new method object
                               #('&' converts to proc)

```

> ```
> klass
> 
> ```
> 
> end  
> def define\_behavior(&b)  
> @\_\_behavior = b  
> self.class.send(:define\_method, :do\_it, &b) #define a ‘do\_it’  
> method  
> @ubm = self.class.instance\_method(:do\_it) #create an unbound  
> method  
> puts “@behavior.class is: #{@\_\_behavior.class}”  
> end  
> #add a set\_behavior method:  
> def set\_behavior &b  
> @\_\_behavior = b  
> end

> end  
> end  
> def inputs \*in\_syms  
> in\_syms.each {|input|  
> inports \<\< Port.new(input.to\_s)  
> create\_accessor input  
> }  
> end  
> #… outputs, inouts, etc.  
> end

Now it seems to work:

> AndGate.a=1; AndGate.b=1  
> AndGate.run #=\> 1
> 
> a = AndGate.instance()  
> a.a=0; a.b=0  
> a.run #=\> 0 #a now is independent of AndGate

…seems to work, but it also seems a bit convoluted 😉

Phil
