【问题标题】:C-style for loops in REBOLREBOL 中的 C 风格 for 循环
【发布时间】:2014-05-17 00:53:52
【问题描述】:

我尝试在 REBOL 中编写 C 风格的 for 循环:

for [i: 0] [i < 10] [i: i + 1] [
    print i
]

不过,此语法似乎不正确:

*** ERROR
** Script error: for does not allow block! for its 'word argument
** Where: try do either either either -apply-
** Near: try load/all join %/users/try-REBOL/data/ system/script/args...

REBOL 是否有任何类似于 C 风格的 for 循环的内置函数,还是我需要自己实现这个函数?

类 C 语言中的等效结构看起来像这样,但我不确定是否可以在 REBOL 中实现相同的模式:

for(i = 0; i < 10; i++){
    print(i);
}

【问题讨论】:

    标签: rebol rebol3


    【解决方案1】:

    由于 标签,我假设这个问题与 Rebol 3 有关。

    为 Rebol 3 提议的“CFOR”

    对于 Rebol 3,有一个非常类似于 C 风格 for 的“通用循环”的提议(得到了相当多的支持),因此目前使用 cfor 的名称还有:请参阅CureCode issue #884 了解所有血腥细节。

    这包括对 Ladislav 的原始实现的改进版本,为了便于参考,我将在此处复制当前(截至 2014 年 5 月 17 日)版本(没有广泛的内联 cmets 讨论实现方面):

    cfor: func [  ; Not this name
        "General loop based on an initial state, test, and per-loop change."
        init [block! object!] "Words & initial values as object spec (local)"
        test [block!] "Continue if condition is true"
        bump [block!] "Move to the next step in the loop"
        body [block!] "Block to evaluate each time"
        /local ret
    ] [
        if block? init [init: make object! init]
    
        test: bind/copy test init
        body: bind/copy body init
        bump: bind/copy bump init
    
        while test [set/any 'ret do body do bump get/any 'ret]
    ]
    

    Rebol 3 中用户级控制结构实现的一般问题

    对于 Rebol 3 中控制结构的所有用户级实现的一个重要的一般性评论:在 R3 中还没有类似于 Rebol 2 的 [throw] 属性(参见 CureCode issue #539),所以这种用户编写的(“夹层” ,在 Rebol 术语中)控制或循环功能通常存在问题。

    特别是,此 CFOR 会错误地捕获 returnexit。为了说明,请考虑以下函数:

    foo: function [] [
        print "before"
        cfor [i: 1] [i < 10] [++ i] [
            print i
            if i > 2 [return true]
        ]
        print "after"
        return false
    ]
    

    您会(正确地)期望 return 实际上从 foo 返回。但是,如果您尝试上述方法,您会发现这种期望令人失望:

    >> foo
    before
    1
    2
    3
    after
    == false
    

    这句话当然适用于所有在这个线程中作为答案给出的用户级实现,直到错误 #539 被修复。

    【讨论】:

      【解决方案2】:

      Ladislav Mecir 优化了 Cfor

      cfor: func [
        {General loop}
        [throw]
        init [block!]
        test [block!]
        inc [block!]
        body [block!]
      ] [
        use set-words init reduce [
          :do init
          :while test head insert tail copy body inc
        ]
      ]
      

      【讨论】:

      • 有趣。我从没想过 do reduce ['print "Hello"] 是否会比 do reduce [:print "Hello"] 效率低,尽管我可以理解为什么它可能是。但是将函数值放入块中有点奇怪。
      • 需要注意两点:(1.) 以上是 Rebol 2,(2.) 它需要 Ladislav 的 set-words library function 才能工作(在当前版本的 R2 或 R3 上,SET-WORDS 可能是替换为捆绑的 COLLECT-WORDS/set)。
      【解决方案3】:

      在这种特殊情况下,大多数人会使用的另一个控制结构是repeat

      repeat i 10 [print i]
      

      导致:

      >> repeat i 10 [print i]
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      

      我一般不经常使用loop,但可以在类似的程度上使用它:

      >> i: 1 
      >> loop 10 [print ++ i]
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      

      这些是一些有用的控制结构。不确定您是否在寻找 cfor,但您从其他人那里得到了答案。

      【讨论】:

      • 这个答案得到了我的投票,因为它为提问者指出了 Rebol 的工作方式。其他的也很好,展示了如何灵活的 Rebol 是通过创建提问者认为的在他的 Rebol 翻译中的精确函数。
      【解决方案4】:

      我已经实现了一个函数,其工作方式与 C for 循环相同。

      cfor: func [init condition update action] [
          do init
          while condition [
              do action
              do update
          ]
      ]
      

      这里是这个函数的一个示例用法:

      cfor [i: 0] [i < 10] [i: i + 1] [
          print i
      ]
      

      【讨论】:

      • 伟大的思想都一样! (我已经提议将完全相同的东西放在盒子里,名称相同。:-P) 请注意,您可以在函数规范方言中限制排版,例如使用 [init [block!] condition [block!] update [block!] action [block!]] (更不用说放入文档字符串,我想你知道吗?)考虑当前状态的 FOR一个笑话,应该是方言的,比如 for x [1 thru 10] [print x] 以 10 结尾和 for x [1 to 10] [print x] 以 9 结尾。如果您有意见,那仍在设计中。
      • 快速数据点,因为我遇到过它...我现在认为这应该简单地称为 for,循环方言采用 loopHere is an implementation。如果您还没有看过 Ren Garden 演示,它包含了大量这些建议。
      【解决方案5】:

      对于简单的初始值、上限和步长,以下工作:

      for i 0 10 2 
          [print i] 
      

      这非常接近 C for 循环。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-09
        • 2017-07-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-21
        相关资源
        最近更新 更多