Подтвердить что ты не робот

Рубиновые лямбда-аргументы

Этот код работает как ожидалось (ничего не делает, даже не вызывает предупреждения/ошибки):

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)

4b9b3361

Ответ 1

Lambdas такие странные, их поведение отличается, когда у вас меньше двух аргументов. Для получения дополнительной информации просмотрите эту статью.

Ответ 2

Этот 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

Ответ 3

Когда лямбда ожидает аргументы, и мы их не предоставляем, или мы предоставляем неверное количество аргументов, генерируется исключение.

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 принимает все следующие типы параметров/аргументов:

  • Позиционные параметры (обязательные и необязательные)
  • Одиночный параметр splat (*);
  • Параметры ключевого слова (обязательно и необязательно);
  • Двойной параметр splat (**);
  • Явный параметр блока с префиксом амперсанда (&).

Следующие примеры иллюстрируют синтаксис лямбда, который принимает несколько типов аргументов.

# 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 обрабатывает аргументы так же, как методы. Существует полное объяснение всех приведенных выше параметров/аргументов в этом сообщении в блоге о методах.