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) about 3 years ago
- Status changed from Open to Rejected
could you make new ticket with more motivation/example/discussion?
Updated by bughit (bug hit) about 3 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) about 3 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) about 3 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?