打破递归函数

时间:2017-07-04 20:48:21

标签: recursion rebol rebol3 rebol2 red

我走过一组嵌套的街区,想要在找到我正在寻找的价值时停止走路。

由于超出此问题范围的原因,我不能将PARSE用于此特定问题,也不能将FOREACH用作looper:

walk: func [series [block!] criteria [block!]][
    use [value] compose/deep [
        while [not tail? series][
            value: pick series 1

            either block? value [
                walk value criteria
            ][
                (to paren! criteria)
            ]

            series: next series
        ]
    ]
]

如果我发现这个具体的价值,我想爆发。

walk [a [b c [d e] f] g] [if value = 'e [return value]]
; returns 'e

但是,我也想做一些不会爆发的行动:

walk [a [b c [d e] f] g] [
    collect [if find [c e] value [keep value]]
]
; returns [c e]

想尝试为包括Red在内的任何Rebol口味解决这个问题。任何关于效率的想法(我使用块而不是函数的原因)等也会受到欢迎。

2 个答案:

答案 0 :(得分:2)

我正在寻找的功能组合是CATCH / THROW。再一次,使用给定的函数:

walk: func [series [block!] criteria [block!]][
    use [value] compose/deep [
        while [not tail? series][
            value: pick series 1

            either block? value [
                walk value criteria
            ][
                (to paren! criteria)
            ]

            series: next series
        ]
    ]
]

我可以简单地将其包装如下:

catch [walk [a [b c [d e] f] g] [if value = 'e [throw value]]]
; returns 'e

一些笔记

  • 如果没有匹配项,我希望函数返回NONE

我只是让WALK返回NONE(我正在使用ALSO,以免留下尴尬的尾随none):

 walk: func [series [block!] criteria [block!]][
      also none use [value] compose/deep [
          while [not tail? series][
              value: pick series 1

              either block? value [
                  walk value criteria
              ][
                  (to paren! criteria)
              ]

              series: next series
          ]
      ]
  ]
  • 没有USE功能

这引入了一个复杂因素,因为我只希望将块绑定到单词VALUE。如果我按如下方式重写函数:

walk: func [series [block!] criteria [block!] /local value][
    do bind compose/deep [
        while [not tail? series][
            value: pick series 1

            either block? value [
                walk value criteria
            ][
                (to paren! criteria)
            ]

            series: next series
        ]
    ] 'value
]

然后它也将同一个块绑定到SERIES和CRITERIA这两个词,它将覆盖来自调用上下文的任何此类词的绑定,例如:

walk [some values][series: none probe value] ; results in error

答案 1 :(得分:2)

此版本避免绑定除VALUE之外的任何内容,并在Red 0.6.3和Rebol2中工作:

walk: func [series [block!] criteria [block!]][
    also none do bind compose/deep [
        while [not tail? series] [
            value: pick series 1
            either block? value [
                walk value criteria
            ] [
                (to paren! criteria)
            ]
            series: next series
        ]
    ]
    context [value: none]
]

(评论此实施与USE的不同之处将受到欢迎。)

是的,这对Rebol3 Alpha不起作用。但是USE也没有。我认为这是一个很小的问题。