Skip to content

keep properties of given blocks #278

Open
@md-work

Description

@md-work

Since #242 (Func contract's return value isn't enforced with blocks) was fixed in contracts-0.15, given blocks are being put into a lambda. So the forwarded block isn't 100% identical with the original one. Especially it's arity and it's source_location changed.

Please keep as many properties as possible of the original block, especially the arity.

Or find a way to forward the original block without breaking #242 again. So the original block could be kept. I'd really appreciate any ideas for this, because it might be the cleanest solution!

 


 

Commit for #242, introducing this bug: 13e56bd#diff-a45dd775c2769b9ab16a23f9d4560adc
lib/contracts/call_with.rb

@@ -73,7 +75,8 @@ module Contracts
                  method.call(*args, &blk)
                else
                  # original method name referrence
-                 method.send_to(this, *args, &blk)
+                 added_block = blk ? lambda { |*params| blk.call(*params) } : nil
+                 method.send_to(this, *args, &added_block)
                end
 
       unless @ret_validator[result]

 


 

I especially need the arity to stay unchanged. Some examples about arity:

def a(&b)
  puts b.arity
end

a {|x| puts x}
=> 1

a {|x,y| puts x+y}
=> 2

a {puts ''}
=> 0

a {|*x| puts x}                                                                                                   
=> -1                                                                                                                                   

 

A very "simple" way how to keep the arity is using eval (see below). But I hope we find a better way.

--- a/lib/contracts/call_with.rb
+++ b/lib/contracts/call_with.rb
@@ -81,7 +81,15 @@ module Contracts
                  method.call(*args, &blk)
                else
                  # original method name reference
-                 added_block = blk ? lambda { |*params| blk.call(*params) } : nil
+                 added_block = nil
+                 if blk
+                    params_ary = []
+                    for i in 1..blk.arity
+                      params_ary << 'x_'+i.to_s
+                    end
+                    params_str = params_ary.join(',')
+                    added_block = eval('lambda { |'+params_str+'| blk.call('+params_str+') }')
+                 end
                  method.send_to(this, *args, &added_block)
                end

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions