Project

General

Profile

Actions

Feature #15357

closed

Proc#parameters returns incomplete type information

Added by larskanis (Lars Kanis) almost 4 years ago. Updated 7 months ago.

Status:
Closed
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:90135]

Description

The current implementation of Proc#parameters differentiate between lambda? true and false.
This is presumably due to the fact, that procs use tricks to apply arguments differently than lambda and methods.

Unfortunately proc{}.parameters states all :req parameters as :opt, so that these both types of parameters are not distinguishable. This information loss leads to the situation that two different proc signatures return an equal parameters list, but behave differently:

pr = proc{|a,b=2| [a,b] }
pr.parameters  # => [[:opt, :a], [:opt, :b]]
pr.call(:a)    # => [:a, 2]  # :a is interpret as the first parameter

pr = proc{|a=1,b| [a,b] }
pr.parameters  # => [[:opt, :a], [:opt, :b]]
pr.call(:a)    # => [1, :a]  # :a is interpret as the second parameter

That means that the current return values of proc{}.parameters are not suitable to build wrapper or proxy objects for a proc. In Eventbox a workaround is used: The proc is passed to define_method and the method parameters are retrieved instead. That way the list of parameters can be retrieved including :req and :opt differentiation, so that a wrapper proc can be built.

The application of argument assignment tricks is a property of the Proc object - not a property of single parameters. Therefore it shouldn't be applied to Proc#parameters in addition - at least not in a way that discards valuable information. The property of the Proc object is already readable through Proc#lambda?, so that there's no need to apply this property to Proc#parameters as well.

My proposal is to unify proc{}.parameters and lambda{}.parameters, so that proc{}.parameters shows positional arguments without default value as type :req as well.


Files

proc-parameters-req-15357.patch (5.15 KB) proc-parameters-req-15357.patch jeremyevans0 (Jeremy Evans), 08/28/2019 02:11 AM

Related issues 1 (0 open1 closed)

Related to Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given ProcRejectedActions
Actions #1

Updated by larskanis (Lars Kanis) almost 4 years ago

  • Subject changed from Unify proc{} and lambda{}.parameters to Proc#parameters returns incomplete type information
  • Description updated (diff)

Updated by jeremyevans0 (Jeremy Evans) about 3 years ago

I don't think the current behavior is a bug, as the parameters for a non-lambda proc are optional. Also, changing the behavior could be backwards incompatible.

I propose instead a lambda keyword to Proc#parameters, which would return the parameters as if the proc were a lambda. Attached is a patch that implements this.

Updated by larskanis (Lars Kanis) over 2 years ago

Sorry for my late answer! I didn't get a notification mail.

As noted above: The application of argument assignment tricks is a property of the Proc object - not a property of single parameters. Therefore it shouldn't be applied to Proc#parameters in addition to Proc#lambda? . I therefore think it's kind of bug.

Nevertheless your patch looks like a good alternative, which keeps backward compatibility and doesn't discard information when called as proc.parameters(lambda:true). Would you still mind to merge it?

Actions #4

Updated by Eregon (Benoit Daloze) over 2 years ago

  • Related to Feature #16499: define_method(non_lambda) should not change the semantics of the given Proc added

Updated by Eregon (Benoit Daloze) over 2 years ago

I agree, and discussed that a bit in #16499.

I think Proc#parameters should expose source-level information, not interpret it according to Kernel#lambda?.

Updated by jeremyevans0 (Jeremy Evans) about 2 years ago

@matz (Yukihiro Matsumoto) considered this during the March 2020 developers meeting, but has not yet made a decision on it.

Updated by matz (Yukihiro Matsumoto) 7 months ago

Hmm, I accept lambda: keyword argument (default false). There might be a better candidate than lambda but it's acceptable at least.

Matz.

Updated by Eregon (Benoit Daloze) 7 months ago

A lambda: kwarg when it's meant to be used for non-lambda Procs seems confusing.
How about parameters(from: :source), and the default would be parameters(from: :behavior)?
Could also be parameters(from_source: true/false) or so.

Actions #9

Updated by jeremyevans (Jeremy Evans) 7 months ago

  • Status changed from Open to Closed

Applied in changeset git|b6804d62f822237e136e698e006c913df9990ec2.


Make Proc#parameters support lambda keyword for returning parameters as if lambda

This makes it easier to use Proc#parameters to build wrappers.

Implements [Feature #15357]

Actions

Also available in: Atom PDF