Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to typedef a proc that can accept variable amount of params #1142

Open
hdoan741 opened this issue Jun 29, 2019 · 4 comments
Open

Ability to typedef a proc that can accept variable amount of params #1142

hdoan741 opened this issue Jun 29, 2019 · 4 comments
Labels
enhancement New feature or surprising current feature

Comments

@hdoan741
Copy link
Contributor

hdoan741 commented Jun 29, 2019

Problem

I'd like to typedef a proc that can accept variable amount of params

-> View on sorbet.run

# typed: true

class District::Relation
  extend T::Sig
end

module District::ClassMethods
  extend T::Sig

  sig { 
    params(
      name: Symbol, 
      body: T.proc.params(args: T.untyped).returns(T.untyped), 
      block: T.nilable(T.proc.void)
    ).void
  }
  def scope(name, body, block=nil); end
end

class District
  extend T::Sig
  extend District::ClassMethods

  scope :no_param, -> {
  }

  scope :two_params, -> (a, b) {
  }
end

Output

editor.rb:24: T.proc.returns(T.untyped) does not match T.proc.params(arg0: T.untyped).returns(T.untyped) for argument body https://srb.help/7002
    24 |  scope :no_param, -> {
    25 |  }
    editor.rb:13: Method District::ClassMethods#scope has specified body as T.proc.params(arg0: T.untyped).returns(T.untyped)
    13 |      body: T.proc.params(args: T.untyped).returns(T.untyped), 
              ^^^^
  Got T.proc.returns(T.untyped) originating from:
    editor.rb:24:
    24 |  scope :no_param, -> {
    25 |  }

Proposed solution

Something like that should be typecheck-able. In terms of API, there are several options:

T.proc.params(*a: T.untyped).void
T.proc.params(a: T.rest[T.untyped]).void
@hdoan741 hdoan741 added enhancement New feature or surprising current feature unconfirmed This issue has not yet been confirmed by the Sorbet team labels Jun 29, 2019
@hdoan741
Copy link
Contributor Author

hdoan741 commented Jun 29, 2019

It seems to work for an explicit block (sorbet.run link) but not a lambda (sorbet.run link)

(However, calling the block with variable number of argument would trigger error still, so maybe it's still the same)

@pje
Copy link
Contributor

pje commented Jun 29, 2019

Variadic procs are kinda fake-able by typedefing a T.any that just enumerates all the possible arities of the function: sorbet.run link

(Interestingly there appears to be a hard-coded limit of 10 args for all proc sigs.)

FWIW, this is kinda like what Scala does under the hood for variadic function types—their stdlib literally has Function1.scala through Function22.scala: https://github.com/scala/scala/blob/d46849d2b77fdc710fc00611e225ba371475a65a/src/library/scala/Function22.scala#L18

@hdoan741
Copy link
Contributor Author

hdoan741 commented Jun 29, 2019 via email

@searls
Copy link

searls commented Jun 11, 2023

👍 This would be terrific and allow Mocktail to specify the type of block parameters when we don't know anything about the block other than the fact that it's a block. In Mocktail's internal T::Struct value that tracks calls to faked methods, I've had to settle for the prop block: T.nilable(T.anything) for whether the invocation took a block

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or surprising current feature
Projects
None yet
Development

No branches or pull requests

4 participants