Lambda — разновидность Proc со строгой проверкой аргументов и локальным return. Обычный proc допускает пропущенные позиционные аргументы и лишние значения; return пытается выйти из метода, где proc был определён. Если этот метод уже завершился, возможен LocalJumpError. Различить варианты можно методом lambda?.
Чем отличаются lambda и Proc в Ruby?
Оба варианта представляют объект Proc, но по-разному проверяют аргументы и обрабатывают return. Показываем различие на небольших примерах.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
В Ruby и лямбда, и обычная процедура являются объектами Proc: их можно сохранить, передать методу и вызвать через call. Оба варианта замыкают окружающий контекст. Отличия касаются прежде всего аргументов и управления возвратом.
Аргументы
Лямбда проверяет сигнатуру как метод:
sum = ->(a, b) { a + b }
p sum.call(1, 2) # 3
# sum.call(1) # ArgumentError
Обычный proc с такими позиционными параметрами заполняет недостающие значения nil, а лишние игнорирует:
pair = proc { |a, b| [a, b] }
p pair.call(1) # [1, nil]
p pair.call(1, 2, 3) # [1, 2]
Это определённое поведение, а не случайность. Но операция внутри proc всё равно может завершиться ошибкой — например, если сложить число с nil.
Return
def with_lambda
-> { return 'lambda' }.call
'method continues'
end
def with_proc
proc { return 'method ends' }.call
'unreachable'
end
p with_lambda # "method continues"
p with_proc # "method ends"
В первом случае return завершает только лямбду; во втором — окружающий метод. Если обычный proc пережил этот метод и затем выполняет такой return, возникает LocalJumpError.
Для самостоятельного callback с привычным контрактом аргументов часто удобна лямбда. Обычный proc полезен, когда нужна семантика блока. Проверка lambda? показывает, какой вариант перед нами. Семантика Proc и lambda