Re: Ways to change the behavior of a block



On 4/30/07, Robert Klemme <shortcutter@xxxxxxxxxxxxxx> wrote:
On 30.04.2007 17:10, Brian Guthrie wrote:
> On 4/30/07, Robert Klemme <shortcutter@xxxxxxxxxxxxxx> wrote:
>> 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
>>
>>
>
> 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;
> 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:

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

That would work, I think. I'll do that. Thanks for the advice.

.



Relevant Pages

  • Re: Ways to change the behavior of a block
    ... On 4/30/07, Robert Klemme wrote: ... filtering each call through some contract ... def to_i ... ... contract any?(String, hash_of?(Symbol, Fixnum)) => String ...
    (comp.lang.ruby)
  • SCWC 90: The winner
    ... ***Uses a different def from the rest. ... every word in this clue is well-crafted. ... The phrase is 'contract killer' but as the given word is only ... surface reading is not alluring. ...
    (rec.puzzles.crosswords)
  • Re: Ways to change the behavior of a block
    ... filtering each call through some contract ... def to_i ... ... contract any?(String, hash_of?(Symbol, Fixnum)) => String ... The goal is to extend it to support block contracts: ...
    (comp.lang.ruby)
  • Optimizing a single slow method
    ... but one method is so incredibly slow that ... def Contract.open ... # puts line ... contract = Contract.open ...
    (comp.lang.ruby)
  • Re: Embedded vs. Non-embedded Tests
    ... place on the road and the telemetry provides almost as much info to the ... Allows you to move most testing code into the contract, the unit tests are then merely running your code with contracts enabled. ... def test_case ... $ cat builtin_tests.rb ...
    (comp.lang.ruby)