Arity (арити) — это понятие, которое описывает количество аргументов, ожидаемых функцией или блоком кода. В Ruby arity играет особую роль при работе с Proc и lambda, так как их поведение в этом аспекте существенно отличается.
Arity определяет:
Обычные Proc (созданные через Proc.new
или proc
) имеют гибкую arity:
nil
Пример:
pr = Proc.new { |a, b| [a, b] }
puts pr.call(1) #=> [1, nil]
puts pr.call(1, 2) #=> [1, 2]
puts pr.call(1, 2, 3) #=> [1, 2] (3 игнорируется)
Lambda (созданные через lambda
или ->
) имеют строгую arity:
Пример:
lm = ->(a, b) { [a, b] }
puts lm.call(1, 2) #=> [1, 2]
# lm.call(1) # ArgumentError (не хватает аргументов)
# lm.call(1, 2, 3) # ArgumentError (лишние аргументы)
означает
n-1` обязательных и один необязательный (rest arg)Примеры:
Proc.new {}.arity #=> 0
Proc.new { |x| }.arity #=> 1
Proc.new { |x, y| }.arity #=> 2
Proc.new { |*args| }.arity #=> -1
Proc.new { |x, *args| }.arity #=> -2
pr = Proc.new { |x, y=1, *z, &b| }
puts pr.parameters.inspect
#=> [[:opt, :x], [:opt, :y], [:rest, :z], [:block, :b]]
p = Proc.new { |a, b| puts "#{a.inspect}, #{b.inspect}" }
l = ->(a, b) { puts "#{a.inspect}, #{b.inspect}" }
p.call(1) #=> "1, nil"
# l.call(1) # ArgumentError
def test_proc
Proc.new { return "из Proc" }.call
"из метода"
end
def test_lambda
-> { return "из lambda" }.call
"из метода"
end
test_proc #=> "из Proc" (выход из метода)
test_lambda #=> "из метода" (возврат только из lambda)
pr = Proc.new { |x=1, y| [x, y] }
puts pr.call(2) #=> [1, 2] (неожиданно!)
lm = ->(x=1, y) { [x, y] }
puts lm.call(2) #=> [1, 2]
Proc подходит когда:
Lambda лучше когда:
Резюмируем: понятие arity в Ruby описывает "строгость" проверки аргументов у Proc и lambda. Обычные Proc имеют гибкую arity и не проверяют аргументы, тогда как lambda обладают строгой arity и ведут себя как методы. Понимание этих различий критически важно для правильного выбора между Proc и lambda в различных сценариях.
Методы arity
и parameters
позволяют интроспектировать ожидаемые аргументы во время выполнения, что может быть полезно для метапрограммирования и создания гибких API.