Rewriting JavaScript break-to-label in Ruby

别说谁变了你拦得住时间么 提交于 2019-12-10 16:07:32

问题


I'm porting a JavaScript library to Ruby, and have come across the following insanity (heavily abbreviated):

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;
      }
    }
}

(You can view the full horror on lines 701-1006.)

How would you rewrite this in Ruby? Specifically:

  • Handling the intermixed break and break loop, and
  • Handling the occasional "fall throughs" that occur in the switch

Presumably a good general strategy for these will get me through other situations, like the nested object_init breaking that also occurs.

Edit: How silly of me; a JavaScript "fall through" like this:

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

can easily be rewritten in Ruby as:

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

回答1:


There are multiple techniques that will work for this.

  1. I'm sure this has already occurred to you, but for the record, you could extract methods from the nightmare function until its structure looks more reasonable.

  2. You could define the outer loops with lambda and then immediately call them on the next line. This will allow you to use the return statement as a multi-level break and the closure that is created will allow you to still access the outer scope variables.

  3. You could raise an exception and rescue it.

  4. (Added by Phrogz) As suggested in the answer linked by @jleedev, you can use throw/catch, e.g.

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


来源:https://stackoverflow.com/questions/4988045/rewriting-javascript-break-to-label-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!