2010-02-09 3 views
17

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

l = lambda {|i|} 
l.call(1) 

Этот код выдает предупреждение (предупреждение: несколько значений для параметра блока (0 для 1)):

l = lambda {|i|} 
l.call 

И этот код с ошибкой (ArgumentError: неверное число аргументов (0 за 2)):

l = lambda {|i, y|} 
l.call 

I-й должно быть, чтобы лямбда требовала передачи всех аргументов.

И со второго примера я вижу, что это не так. Почему он работает, когда задан только один аргумент, и работает как ожидалось (с ошибкой с ошибкой) с более чем одним аргументом?

PS: рубин 1.8.6 (2008-08-11 287 номера патчей) [универсального darwin9.0]

UPDATE: Я проверил эти образцы с рубином 1.9.1p376. И он работает так, как ожидалось - второй пример также вызывает ошибку. Похоже, что это особенность версии 1.8 (или < = 1,8)

ответ

12

Lambdas странные, их поведение отличается от того, что у вас есть менее двух аргументов. Проверьте this article для получения дополнительной информации.

12

This script научит вас всему, что вам нужно знать о закрытии в Ruby.

# So, what's 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 
+0

Извините, но я не могу найти ответ. Не могли бы вы указать? –

+0

Добавил указатель :) – Trevoke

+0

Спасибо!Но так или иначе, до сих пор неясно, почему такое поведение существует (должно быть правильно - существует) –

2

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

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 

Так же, как методы, лямбда принять все из следующих типов параметров/аргументов:

  • Позиционные параметры (обязательно и необязательно)
  • Одиночный параметр 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 обрабатывает аргументы так же, как методы. Существует полное описание всех приведенных выше параметров/аргументов в this blog post about methods.

Смежные вопросы