Ответ 1
В документах, к которым вы привязались:
Возвращает количество аргументов, которые не будут игнорироваться. Если объявлен блок без аргументов, возвращается 0. Если известно, что блок принимает ровно n аргументов, возвращает n. Если блок имеет необязательные аргументы, возвращаем -n-1, где n - количество обязательных аргументов. Прок без объявления аргументов - это тот же самый блок, объявляющий || как его аргументы.
То, что doc забывает упомянуть, заключается в том, что procs и лямбда не обрабатывают аргументы точно так же, как например:
>> p = proc { |a = 1, b| b }
=> #<Proc:[email protected](irb):1>
>> l = lambda { |a = 1, b| b }
=> #<Proc:[email protected](irb):2 (lambda)>
>> p.call
=> nil
>> l.call
ArgumentError: wrong number of arguments (0 for 1..2)
from (irb):2:in `block in irb_binding'
from (irb):4:in `call'
from (irb):4
from /usr/local/bin/irb:12:in `<main>'
Изменить: язык программирования Ruby от O'Reilly - это тот, у которого немного больше деталей:
6.5.3 Arity of Proc
Арктичность proc или лямбда - это количество аргументов, которые она ожидает. (Слово происходит от суффикса "ary" унарного, двоичного, тернарного, и т.д.) Объекты Proc имеют метод arity, который возвращает количество аргументы, которые они ожидают. Например:
lambda{||}.arity # => 0. No arguments expected lambda{|x| x}.arity # => 1. One argument expected lambda{|x,y| x+y}.arity # => 2. Two arguments expected
Понятие arity запутывается, когда Proc принимает произвольное количество аргументов в окончательном аргументе * -prefixed. Когда Proc допускает необязательные аргументы, метод arity возвращает отрицательное число формы -n-1. Возвращаемое значение этой формы указывает, что Proc требует n аргументов, но необязательно может принимать дополнительные аргументы также. -n-1 известен как дополнение к n, и вы можете инвертируйте его с помощью оператора ~. Поэтому, если arity возвращает отрицательное число m, то ~ m (или -m-1) дает вам количество необходимых аргументов:
lambda {|*args|}.arity # => -1. ~-1 = -(-1)-1 = 0 arguments required lambda {|first, *rest|}.arity # => -2. ~-2 = -(-2)-1 = 1 argument required
Существует одна окончательная морщина метода arity. В Ruby 1.8, Proc объявлен без всякой аргументации (т.е. без каких-либо || символы) могут быть вызваны с любым количеством аргументов (и эти аргументы игнорируются). Метод arity возвращает -1, чтобы указать, что нет необходимых аргументов. Это изменилось в Ruby 1.9: a Proc объявленный как это имеет arity 0. Если это лямбда, то это error, чтобы вызвать его с любыми аргументами:
puts lambda {}.arity # –1 in Ruby 1.8; 0 in Ruby 1.9
Изменить 2: Стефан добавляет точную причину, по которой они отличаются в комментарии:
http://www.ruby-doc.org/core-2.0/Proc.html#method-i-call
Для
procs
, созданного с помощьюlambda
или->()
, возникает ошибка, если неправильное количество параметров передается вProc
с несколькими параметрами. Дляprocs
, созданного с помощьюProc.new
илиKernel.proc
, дополнительные параметры молча отбрасываются.