开发者

Rewriting JavaScript break-to-label in Ruby

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 (...)开发者_StackOverflow中文版 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


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
    
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜