Ответ 1
Lambdas такие странные, их поведение отличается, когда у вас меньше двух аргументов. Для получения дополнительной информации просмотрите эту статью.
Этот код работает как ожидалось (ничего не делает, даже не вызывает предупреждения/ошибки):
l = lambda {|i|}
l.call(1)
Этот код выдает предупреждение (предупреждение: несколько значений для параметра блока (0 для 1)):
l = lambda {|i|}
l.call
И этот код выходит из строя с ошибкой (ArgumentError: неправильное количество аргументов (0 для 2)):
l = lambda {|i, y|}
l.call
Я думал, что лямбда требует передачи всех аргументов.
И со второго примера я вижу, что это не так. Почему он работает, когда задан только один аргумент и работает как ожидалось (с ошибкой с ошибкой) с более чем одним аргументом?
PS: ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]
UPDATE: Я проверил эти образцы с ruby 1.9.1p376. И он работает так, как ожидалось - второй пример также вызывает ошибку. Похоже, что это функция версии 1.8 (или = 1.8)
Lambdas такие странные, их поведение отличается, когда у вас меньше двух аргументов. Для получения дополнительной информации просмотрите эту статью.
Этот script расскажет вам все, что вам нужно знать о закрытии в Ruby.
# So, what the final verdict on those 7 closure-like entities?
#
# "return" returns from closure
# True closure? or declaring context...? Arity check?
# --------------- ----------------------------- -------------------
# 1. block (called with yield) N declaring no
# 2. block (&b => f(&b) => yield) N declaring no
# 3. block (&b => b.call) Y except return declaring warn on too few
# 4. Proc.new Y except return declaring warn on too few
# 5. proc <<< alias for lambda in 1.8, Proc.new in 1.9 >>>
# 6. lambda Y closure yes, except arity 1
# 7. method Y closure yes
Когда лямбда ожидает аргументы, и мы их не предоставляем, или мы предоставляем неверное количество аргументов, генерируется исключение.
l = lambda { |name| puts "Today we will practice #{name} meditation." }
l.call
ArgumentError: wrong number of arguments (given 0, expected 1)
Мы можем использовать метод arity, чтобы узнать количество ожидаемых аргументов:
l.arity # Output: => 1
Подобно методам, lambdas принимает все следующие типы параметров/аргументов:
Следующие примеры иллюстрируют синтаксис лямбда, который принимает несколько типов аргументов.
# Stabby syntax
l = -> (cushion, meditation="kinhin", *room_items, time:, posture: "kekkafuza", **periods, &p) do
p.call
end
# Regular syntax
l = lambda do |cushion, meditation="kinhin", *room_items, time:, posture: "kekkafuza", **periods, &p|
p.call
end
l.call("zafu", "zazen", "zabuton", "incense", time: 40, period1: "morning", period2: "afternoon" ) { puts "Hello from inside the block, which is now a proc." }
Output:
Hello from inside the block, which is now a proc.
Lambdas обрабатывает аргументы так же, как методы. Существует полное объяснение всех приведенных выше параметров/аргументов в этом сообщении в блоге о методах.