Ответ 1
Я использую это иногда, если я хочу присвоить что-то переменной, но мне нужно сначала вычислить значение, которое я хочу назначить. Это делает код немного более аккуратным таким образом. Я думаю, что это предпочтение пользователя. В основном вы говорите: я назначаю что-то foo, но для того, чтобы получить значение, которое я хочу, мне сначала нужно что-то сделать. Это особенно полезно при выполнении memoization, поэтому вместо
if @cache.nil?
do_something!
@cache = read_value
end
Вы можете сделать
@cache ||= begin
do_something!
read_value
end
То, что вы здесь используете, заключается в том, что интерпретатор Ruby имеет стек, и каждое выражение обычно толкает что-то в стеке или вынимает что-то из стека. Присвоение просто берет последнюю вещь из стека и присваивает ей (в этом случае последняя строка от начала/конца). Много раз зная это (стековый подход в Ruby) может быть полезным.
Я не думаю, что это нарушает наименьшее удивление, хотя, я думаю, это предпочтение пользователя, если вы хотите его использовать или нет.
Вы можете видеть, что это ничего не делает неожиданным, если посмотреть на то, что он написал в Ruby MRI 1.9:
RubyVM::InstructionSequence::compile("c = begin; a = 5; 6; end").to_a
[:trace, 1],
[:trace, 1],
[:putobject, 5],
[:setlocal, 2],
[:trace, 1],
[:putobject, 6],
[:dup],
[:setlocal, 3],
[:leave]
Трассировка предназначена только для отслеживания стека, вы можете игнорировать это. Dup дублирует последний элемент в стеке. В этом примере число локальной переменной a
равно 2
, а номер локальной переменной c
равен 3
(следовательно, putobject, 2
назначит переменной a
и т.д.).
Единственным побочным эффектом этого по сравнению с a = 5; c = 6
является команда dup
, что означает, что размер стека вашего метода будет больше на 1 слот. Но это не особенно важно, потому что это имеет какой-то эффект, когда интерпретатор находится внутри этого конкретного метода, а память для стека предварительно зарезервирована в любом случае, поэтому это означает, что указатель стека будет уменьшен на 1 больше, чем в противном случае. Так что вообще никаких изменений вообще нет. При включении оптимизаций даже dup
, вероятно, исчезнет.