Feature #17721
closedProc.new should be able to contruct a lambda
Description
since procs and lambdas are of the same type, as long as Proc::new exists, it should be able to create either.
class Proc def augment self.class.new lambda? do call end end end
Updated by ko1 (Koichi Sasada) almost 4 years ago
- Status changed from Open to Rejected
could you make new ticket with more motivation/example/discussion?
Updated by bughit (bug hit) almost 4 years ago
Why a new ticket? What's wrong with this one? If you wanted clarification you didn't have to close it, and even now you can still reopen.
As to the substance, if you want to transform an existing proc or lambda in a way that involves creating a new one and calling the original from it, it makes sense to end up with the same "type" you started with (proc or lambda). The simplest example is negation:
class Proc def negate self.class.new do |*args, &block| not self.(*args, &block) end end end The above will turn a lambda into a proc. Why shouldn't the Proc constructor be able to create a lambda? Lambdas should have probably been a sub-type, but as long as they share the same type and hence constructor, it seems almost an obligation for it to be able to construct either: Proc.new(lambda: true)
Updated by naruse (Yui NARUSE) almost 4 years ago
- Status changed from Rejected to Feedback
A correct status of a ticket whose description doesn't have a use cases or user stories to discuss the validness of the request and the actual API design is "Feedback".e
Updated by Eregon (Benoit Daloze) almost 4 years ago
There is Kernel.send(lambda ? :lambda : :proc) { ... } if you really really need this.
But it's probably slow and Ruby implementations have troubles to optimize this as they have no idea when parsing if the block is for a proc or lambda.
Of course the more sensible thing would be:
class Proc def negate if lambda? lambda do |*args, &block| not self.(*args, &block) end else proc do |*args, &block| not self.(*args, &block) end end end end That has a significant advantage that a given block only has proc or lambda semantics but not both (and so using e.g., break is possible).
And also from looking at the backtrace you can know which it was.
I don't think it matters if negate e.g. always returns a lambda in this case (the caller can only observe the difference though Proc#lambda? and that shouldn't matter), so it should just be:
class Proc def negate -> (*args, &block) do not self.(*args, &block) end end end As discussed extensively in related tickets, it's a very bad idea to convert from proc to lambda or vice-versa, but at least this issue only suggests a polymorphic create with a literal block.
So the important question here is why do you need to preserve whether the source Proc was a lambda or not?