How can one document a function with a variable number of arguments in YARD?
Asked Answered
G

2

10

I have a function that take a variable number of arguments, like this:

def myfun(*args)
  # ...
end

All args are of the same type (Symbol), so right now I document the function like if there were only one argument, saying it can take more than one, e.g.:

# this function doesn’t do anything
# @param [Symbol]: this argument does something, you can add more symbols
#                  if you want
def myfun(*args)
  # ...
end

Is there a built-in way to handle this case?

Garfieldgarfinkel answered 27/4, 2014 at 20:11 Comment(0)
O
11

The following makes sense because args is an Array inside the method, although none of the params are an Array as such:

# this function doesn’t do anything
#
# @param [Array<Symbol>] args these arguments do something
# @return [nil]
def myfun(*args)
  # ...
end

Note the * is dropped from the param name in the comment. This is just to be consistent - args is an Array, but *args is not.

A quick search shows quite a few projects using this style, including inside Yard's own .rb files (e.g. see source for initialize in Verifier class) - although no examples of this convention are given in the guide.

Oedema answered 27/4, 2014 at 20:57 Comment(0)
S
4

Neil Slater's answer is as far as I know the best one for an unstructured argument list.

But for methods that use *args to accept any of a fixed set of possible parameter lists, there's @overload. E.g., for Enumerable#find_index, one could write something like:

# Compares each entry in _enum_ with value or passes to _block_.
# Returns the index for the first for which the evaluated value
# is non-false. If no object matches, returns `nil`.
# 
# @overload find_index(value)
#   Finds the first index of the specified value.
#   @param value [Object] the value to find
#   @return [Integer, nil] the index, or `nil` if no element matches
# @overload find_index(&block)
#   Finds the index of the first value matching
#   the specified block.
#   @yieldparam [Object] element the element to match against
#   @yieldreturn [Boolean] whether the element matches
#   @return [Integer, nil] the index, or `nil` if no element matches
# @overload find_index
#   @return [Enumerator] a new enumerator
def find_index(*args)
  # (...)
end

This will get documented as:

#find_index(value) ⇒ Integer?
#find_index {|element| ... } ⇒ Integer?
#find_index ⇒ Enumerator

Compares each entry in enum with value or passes to block. Returns the index for the first for which the evaluated value is non-false. If no object matches, returns nil.

Overloads:

#find_index(value) ⇒ Integer?

Finds the first index of the specified value.

(...etc.)

Stationmaster answered 29/1, 2021 at 20:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.