Вырваться из начала / конца блока рано - PullRequest
2 голосов
/ 17 апреля 2019

Я хочу выйти из блока начала / конца, все еще присваивая переменную, которой назначен ее результат.

def foo
  @foo ||= begin
    puts "running"

    return "leaving early" if true # would be some sort of calculation

    # Other calculations
  end
end

То, что я надеюсь, произойдет

> foo
running
=> leaving early
> foo
=> leaving early

Чтофактически происходит

> foo
running
=> leaving early
> foo
running
=> leaving early

Код не работает, потому что return завершает весь метод без установки @foo.Использование break или next работает только в циклах.Работает ли что-нибудь в блоке начала так, как я думаю?

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

  • Назначение переменной в блоке начала и возврат
  • Помещение оставшейся части начального блока в оператор if
  • Выполнение вычисления перед начальным блоком

Похоже, существует много связанных вопросов овырывается из блоков, но я не могу найти тот, который отвечает этой конкретной версии (возможно, потому что это невозможно).

1 Ответ

8 голосов
/ 18 апреля 2019

Я думаю, что вы избавите себя от огромного количества раздоров, если просто поместите всю эту логику в свой собственный метод:

def foo
  @foo ||= compute_foo
end

def compute_foo
  puts "running"

  return "leaving early" if true # would be some sort of calculation

  # Other calculations
end

Это отделяет вычисления от запоминания, делаяего проще тестировать и рассуждать, и это довольно распространенный шаблон проектирования в Ruby и других языках.

Конечно, есть способы сделать то, что вы просите.Наиболее очевидным решением является немедленный анонимный процесс:

def foo
  @foo ||= (proc do
    puts "running"

    next "leaving early" if true # would be some sort of calculation

    # Other calculations
  end)[] # or .call or .()
end

Но вы, конечно же, не сделаете ни себе, ни будущим сторонникам этого кода никаких одолжений.

...