【问题标题】:Rewriting JavaScript break-to-label in Ruby在 Ruby 中重写 JavaScript break-to-label
【发布时间】:2011-02-14 01:04:05
【问题描述】:

我正在将 a JavaScript library 移植到 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;
      }
    }
}

(您可以查看完整的恐怖on lines 701-1006。)

你会如何用 Ruby 重写它?具体来说:

  • 处理混合的breakbreak loop,以及
  • 处理交换机中偶尔发生的“失败”

据推测,一个很好的通用策略可以让我度过其他情况,比如嵌套的 object_init 中断也会发生。

编辑:我真傻;像这样的 JavaScript “失败”:

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

在 Ruby 中可以很容易地改写为:

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

【问题讨论】:

标签: javascript ruby break


【解决方案1】:

有多种技术可以解决这个问题。

  1. 我相信你已经想到了,但是为了记录,你可以从 nightmare 函数中提取方法,直到它的结构看起来更合理。

  2. 您可以使用 lambda 定义外部循环,然后立即在下一行调用它们。这将允许您将 return 语句用作多级 break 并且创建的闭包将允许您仍然访问外部范围变量。

  3. 您可以引发异常并挽救它。

  4. (由 Phrogz 添加) 正如@jleedev 链接的答案中所建议的,您可以使用 throw/catch,例如

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

【讨论】:

  • #2 有一些棘手的事情需要注意。如果 lambdawithin 中的任何循环是用 Proc 对象实现的,则 return 在其中一个 那些将从你的整个周围方法返回,而不仅仅是lambda。因此,例如,这意味着您不能在 lamba 中使用 5.times do ... end 之类的内容进行迭代,除非该循环不使用 return
  • 如果没有任何进一步的答案,我会接受这个。我建议如果你在你的技术列表中加入 throw/catch 效果会更好。
  • 我添加了 throw/catch 答案。随意重新编辑您的答案以包含它,因为您想要说出它并将我的名字从您的答案中删除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-13
  • 2014-02-07
  • 1970-01-01
  • 2012-08-27
  • 1970-01-01
  • 2016-07-17
  • 1970-01-01
相关资源
最近更新 更多