Двустороннее назначение Ruby с блоком/proc/lambda?

Очень приятно записывать

@foo ||= "bar_default"

или

@foo ||= myobject.bar(args)

но я искал, есть ли способ написать что-то вроде

@foo ||= do
  myobject.attr = new_val
  myobject.other_attr = other_new_val
  myobject.bar(args)
end

примерно эквивалентный в фактически функциональном коде чем-то вроде

@foo = if [email protected]?
         @foo
       else
         myobject.attr = new_val
         myobject.other_attr = other_new_val
         myobject.bar(args)
       end

И я полагаю, что я мог бы написать свой собственный глобальный метод, такой как "getblock", чтобы обернуть и вернуть результат любого общего блока, но мне интересно, есть ли уже встроенный способ сделать это.

Ответы

Ответ 1

Вы можете использовать begin.. end:

@foo ||= begin
  # any statements here
end

или, возможно, подумайте о факторизации содержимого блока в отдельный метод.

Ответ 2

Я обычно пишу это так:

@foo ||= (
  myobject.attr = new_val
  myobject.other_attr = other_new_val
  myobject.bar(args)
)

Ответ 3

@foo ||= unless @foo
  myobject.attr = new_val
  myobject.other_attr = other_new_val
  myobject.bar(args)
end