# Ways to change the behavior of a block

**URL:** <https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266>\
**Category:** Ruby\
**Created:** [April 30, 2007, 7:33am UTC](https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266 "2007-04-30T07:33:10Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Brian\_Guthrie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7bcc69/32.png) [@Brian\_Guthrie](https://www.ruby-forum.com/u/Brian_Guthrie)\
**Post date:** [April 30, 2007, 7:33am UTC](https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266/1 "2007-04-30T07:33:10Z")

</div>

I’d like to be able to change the behavior of a call to a block (I’m  
working on a design-by-contract system and would like to be able to  
check the block’s signature, filtering each call through some contract  
check) and I was wondering if anyone had any advice. It’s easy enough  
to override Proc#call, but doing so doesn’t appear to affect calls to  
implicit blocks with using the yield keyword. Is it even possible to  
do this?

Cheers,

Brian Guthrie

---

<div class="post-metadata">

**Author:** ![Brian\_Guthrie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7bcc69/32.png) [@Brian\_Guthrie](https://www.ruby-forum.com/u/Brian_Guthrie)\
**Post date:** [April 30, 2007, 12:06pm UTC](https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266/2 "2007-04-30T12:06:27Z")

</div>

On 30.04.2007 07:31, Brian Guthrie wrote:

> I’d like to be able to change the behavior of a call to a block (I’m  
> working on a design-by-contract system and would like to be able to  
> check the block’s signature, filtering each call through some contract  
> check) and I was wondering if anyone had any advice. It’s easy enough  
> to override Proc#call, but doing so doesn’t appear to affect calls to  
> implicit blocks with using the yield keyword. Is it even possible to  
> do this?

If I understand you properly you want to be checking the argument list  
in the _calling_ method.

irb(main):003:0\> def f(&b)  
irb(main):004:1\> raise ArgumentError unless b.arity == 4  
irb(main):005:1\> b[0,1,2,3]  
irb(main):006:1\> end  
=\> nil  
irb(main):007:0\> f {|a,b| p a,b}  
ArgumentError: ArgumentError  
from (irb):4:in `f’  
from (irb):7  
from :0  
irb(main):008:0\> f {|a,b,c,d| p a,b}  
0  
1  
=\> nil

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![Brian\_Guthrie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7bcc69/32.png) [@Brian\_Guthrie](https://www.ruby-forum.com/u/Brian_Guthrie)\
**Post date:** [April 30, 2007, 5:10pm UTC](https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266/3 "2007-04-30T17:10:50Z")

</div>

On 4/30/07, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> in the _calling_ method.  
> from :0  
> irb(main):008:0\> f {|a,b,c,d| p a,b}  
> 0  
> 1  
> =\> nil
> 
> Kind regards
> 
> ```
> robert
> 
> ```

It’s a bit more complicated than that, but that’s the idea. If you’re  
curious, the library is called Handshake ([handshake.rubyforge.org](http://handshake.rubyforge.org);  
haven’t made an announcement as it’s not quite mature yet). It  
supports (among other things) argument contracts of the form:

contract String =\> Integer  
def to\_i …

contract “foo” =\> 1…3  
def foo …

contract any?( String, hash\_of?(Symbol, Fixnum) ) =\> String  
def accepts\_string\_or\_hash …

The goal is to extend it to support block contracts:

contract [String, Block(String =\> Integer)] =\> Integer

The Handshake library surrounds an object that includes the  
appropriate module with a proxy object and checks everything that  
passes across that barrier. That means that I can easily manipulate  
any incoming Proc objects, extending the instance so that Proc#call is  
required to check an argument list. The problem is that changing the  
behavior of Proc#call does _not_ affect the behavior of yield:

class Proc  
def weird(\*args)  
puts “weird call!” if args.length \> 0 && args[0] == “weird”  
orig\_call(\*args)  
end  
alias :orig\_call :call  
alias :call :weird  
end

def weird\_call(str, &block)  
block.call(str)  
end

def weird\_yield(str)  
yield(str)  
end

In IRB:

> > weird\_call(“weird”) { true }  
> > weird call!  
> > =\> true  
> > weird\_yield(“weird”) { true }  
> > =\> true

Cheers,

Brian

---

<div class="post-metadata">

**Author:** ![Brian\_Guthrie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7bcc69/32.png) [@Brian\_Guthrie](https://www.ruby-forum.com/u/Brian_Guthrie)\
**Post date:** [April 30, 2007, 5:34pm UTC](https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266/4 "2007-04-30T17:34:58Z")

</div>

On Apr 30, 2007, at 11:10 AM, Brian Guthrie wrote:

> The Handshake library surrounds an object that includes the  
> appropriate module with a proxy object and checks everything that  
> passes across that barrier. That means that I can easily manipulate  
> any incoming Proc objects, extending the instance so that Proc#call is  
> required to check an argument list. The problem is that changing the  
> behavior of Proc#call does _not_ affect the behavior of yield:

The ‘yield’ mechanism is not a method call and so you won’t be able  
to intercept it by redefining methods. You would have to hack on the  
Ruby interpreter itself.

I’ll admit to be pretty leary of something that redefines Proc#call  
at the class level (vs. via singleton methods on particular procs).

Gary W.

---

<div class="post-metadata">

**Author:** ![Brian\_Guthrie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7bcc69/32.png) [@Brian\_Guthrie](https://www.ruby-forum.com/u/Brian_Guthrie)\
**Post date:** [April 30, 2007, 5:30pm UTC](https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266/5 "2007-04-30T17:30:58Z")

</div>

On 30.04.2007 17:10, Brian Guthrie wrote:

> > If I understand you properly you want to be checking the argument list  
> > from (irb):7
> 
> def foo …  
> passes across that barrier. That means that I can easily manipulate  
> any incoming Proc objects, extending the instance so that Proc#call is  
> required to check an argument list. The problem is that changing the  
> behavior of Proc#call does _not_ affect the behavior of yield:

Then just create another block that will invoke the original and do the  
checks.

def f(&b)  
bb = lambda {|\*a|  
raise ArgumentError unless a.size == 4  
result = b[\*a[0…4]]  
raise “Whatever” unless Array === result  
result  
}  
other\_method(&bb)  
end

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![Brian\_Guthrie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7bcc69/32.png) [@Brian\_Guthrie](https://www.ruby-forum.com/u/Brian_Guthrie)\
**Post date:** [April 30, 2007, 6:03pm UTC](https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266/6 "2007-04-30T18:03:02Z")

</div>

On Apr 30, 2007, at 11:42 AM, Brian Guthrie wrote:

> It’s the sort of library that shouldn’t necessarily be used in  
> production code anyway, though, due to the performance hit you take  
> from having to run each and every single method call through a filter.

Makes sense. Reminds me of Eiffel’s ability to monitor pre/post  
conditions during development but to turn off those checks in  
production.

One of the things that I thought was really nice about Eiffel’s  
pre-condition checks was that any pre-condition exceptions were  
raised in the caller’s context, which is conceptually where the  
error exists. I think that would be difficult to do in Ruby without  
support in the runtime.

Gary W.

---

<div class="post-metadata">

**Author:** ![Brian\_Guthrie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7bcc69/32.png) [@Brian\_Guthrie](https://www.ruby-forum.com/u/Brian_Guthrie)\
**Post date:** [April 30, 2007, 6:18pm UTC](https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266/7 "2007-04-30T18:18:04Z")

</div>

On 4/30/07, Gary W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> One of the things that I thought was really nice about Eiffel’s  
> pre-condition checks was that any pre-condition exceptions were  
> raised in the caller’s context, which is conceptually where the  
> error exists. I think that would be difficult to do in Ruby without  
> support in the runtime.
> 
> Gary W.

You can actually get a certain amount of the way there. I’m currently  
supporting a number of different checks:

- invariants
- pre/post conditions
- method argument checks

There are a variety of different failure conditions for these. If a  
post-condition check fails then the blame lies with the method in  
question. If a precondition check fails then the caller is at fault.  
Invariant checks are very difficult to pinpoint: if an invariant  
doesn’t hold before a method is called it’s very hard to figure out  
why.

I’m currently doing my best to raise in the context of the method  
around which the contract is placed but it’s very difficult to raise  
in the right place and to assign blame correctly. Raising in the  
context of the caller may be impossible without, as you suggest,  
support in the runtime. My understanding is that libraries exist for  
deriving a useful call stack but I haven’t explored them yet.

There’s a gem if you’re curious but the documentation isn’t as good as  
I’d like yet, and there are a few bugs. You may also want to check  
out Florian Groß’s ruby-contract.

Brian Guthrie

---

<div class="post-metadata">

**Author:** ![Brian\_Guthrie](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/7bcc69/32.png) [@Brian\_Guthrie](https://www.ruby-forum.com/u/Brian_Guthrie)\
**Post date:** [April 30, 2007, 5:43pm UTC](https://www.ruby-forum.com/t/ways-to-change-the-behavior-of-a-block/93266/8 "2007-04-30T17:43:59Z")

</div>

On 4/30/07, Gary W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> to intercept it by redefining methods. You would have to hack on the  
> Ruby interpreter itself.
> 
> I’ll admit to be pretty leary of something that redefines Proc#call  
> at the class level (vs. via singleton methods on particular procs).
> 
> Gary W.

Indeed. The example I gave did that for simplicity’s sake but the  
library would only modify the incoming objects.

It’s the sort of library that shouldn’t necessarily be used in  
production code anyway, though, due to the performance hit you take  
from having to run each and every single method call through a filter.

Brian
