[vim/vim] Add `get({func}, 'arity')` to determine the number of expected arguments to a funcref (Issue #15097)

10 views
Skip to first unread message

Austin Ziegler

unread,
Jun 24, 2024, 10:29:40 AM6/24/24
to vim/vim, Subscribed

Is your feature request about something that is currently impossible or hard to do? Please describe the problem.

There appears to be no way to get the expected arity a function (builtin or user-defined). I have some functional code that I want to add which would work better if I could change how it works based on the number of expected arguments. I’ve called it arity because that's what Ruby, Elixir, and other languages with functional behaviours call it that.

export def All(expr: any, fn: any): bool
  if expr->empty()
    return true
  endif

  var Fn = Ref(fn)

  if Fn->type() == v:t_func
    var arity = Fn->get('arity')->len()

    if arity == 1
      if expr->type() == v:t_dict
        for [k, v] in Items(expr)
          if !Fn([k, v]) | return false | endif
        endfor
      else
        for v in expr->deepcopy()
          if !Fn(v) | return false | endif
        endfor
      endif
    elseif arity == 2
      for [k, v] in Items(expr)
        if !Fn(k, v) | return false | endif
      endfor
    else
      throw 'Invalid argument count for ' .. string(Fn)
    endif

    return true
  elseif Fn->type() == v:t_string
    return None(expr, printf('!(%s)', Fn))
  endif

  throw 'Invalid type ' .. typename(Fn) .. ' for ' .. string(Fn)
enddef

Describe the solution you'd like

An additional {what} for get({func}, {what}), called "arity". The specification would be similar to that of Ruby:

Returns an indication of the number of arguments accepted by a method. Returns a nonnegative integer for methods that take a fixed number of arguments. For Ruby methods that take a variable number of arguments, returns -n-1, where n is the number of required arguments. Keyword arguments will be considered as a single additional argument, that argument being mandatory if any keyword argument is mandatory. For methods written in C, returns -1 if the call takes a variable number of arguments.

Thus:

def Func() # => arity 0
def Func(a: any) #=> arity 1
def Func(a: any, b: any) # => arity 2
def Func(a: any, b: any = null) # => arity -2
def Func(a: any, ...b: list<any>) # => arity -2

If preferred, this could be replaced with multiple calls or return a dict with multiple values:

def Func() # => {required: 0, optional: 0, varargs: false}
def Func(a: any) # => {required: 1, optional: 0, varargs: false}
def Func(a: any, b: any) # => {required: 2, optional: 0, varargs: false}
def Func(a: any, b: any = null) # => {required: 1, optional: 1, varargs: false}
def Func(a: any, ...b: list<any>) # =. {required: 1, optional: 0, varargs: true}

I primarily care about required arguments for my use case, but optional and varargs may be useful for other cases.

For vim9script it may also be useful to be able to get the argument types on reflection, but that's probably a different feature altogether.

Describe alternatives you've considered

Unless this is implemented, I will be implementing a fixed argument list requirement, which I would rather not do, because the used code reads better without the extra argument if not required.


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/15097@github.com>

Christian Brabandt

unread,
Jul 9, 2024, 12:32:40 PM7/9/24
to vim/vim, Subscribed

Closed #15097 as completed via 48b7d05.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issue/15097/issue_event/13443144230@github.com>

Reply all
Reply to author
Forward
0 new messages