Переписывание JavaScript break-to-label в Ruby - PullRequest
4 голосов
/ 14 февраля 2011

Я портирую библиотеку JavaScript на Ruby и натолкнулся на следующее безумие (сильно сокращенное):

function foo(){
  if (foo) ...
  loop:
    while(go()){
      if (...) break;
      switch(...){
        case a:
          break loop;  
        case b:
        case c:
          if (...) break loop;
          ...
          break;
        case d:
          if (...) break loop;
          // fall through
        case e:
          if (...) break loop;
          ...
          break;    
        case f:
          if (...) break loop;
          object_init:
            do{
              switch(...){
                case a:
                  ...
                  break;
                case b:
                  ...
                  break object_init;        
              }
            } while(...);              
            ...
            break;
      }
    }
}

(Вы можете просмотреть весь ужас в строках 701-1006 .)

Как бы вы переписали это в Ruby?В частности:

  • Обработка смешанных break и break loop и
  • Обработка случайных «провалов», возникающих в коммутаторе

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

Edit : Как глупо с моей стороны;JavaScript «проваливается» следующим образом:

switch(xxx){
  case a:
    aaa;
  case b:
    bbb;
  break;
}

может быть легко переписан в Ruby как:

case xxx
  when a, b
    if a===xxx
      aaa
    end
    bbb
end

1 Ответ

4 голосов
/ 14 февраля 2011

Есть несколько методов, которые будут работать для этого.

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

  2. Вы можете определить внешние циклы с помощью lambda , а затем немедленно вызвать их на следующей строке.Это позволит вам использовать оператор return в качестве многоуровневого break , а созданное закрытие позволит вам по-прежнему получать доступ к переменным внешней области.

  3. Вы можете вызвать исключение и спасти его.

  4. (добавлено Phrogz) Как указано в ответе, связанном с @jleedev, вы можетеиспользовать бросок / ловить, например,

    catch(:loop) do
      case ...
        when a
          throw :loop
        when b, c
          throw :loop if ...
        ...
      end
    end
    
...