Q:

Breaking out of a recursive function

I'm walking through a set of nested blocks and want to stop the walk when I've found the value I'm looking for.
For reasons that are beyond the scope of this question, I can't use PARSE for this particular problem, nor use FOREACH as the 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
        ]
    ]
]

I'd like to break out if I find this specific value.
walk [a [b c [d e] f] g] [if value = 'e [return value]]
; returns 'e

However, I'd also like to do operations that don't break out:
walk [a [b c [d e] f] g] [
    collect [if find [c e] value [keep value]]
]
; returns [c e]

Would like to try and solve this for any of the Rebol flavours including Red. Any thoughts as to efficiency (reason I use a block instead of a function), etc. would be welcome too.

A:

The function combo I was looking for is CATCH/THROW. Once again, using the given function:
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
        ]
    ]
]

I can simply wrap it as follows:
catch [walk [a [b c [d e] f] g] [if value = 'e [throw value]]]
; returns 'e

Some Notes

I want the function to return NONE if there are no matches

I'll just have WALK return NONE (am using ALSO just so as not to leave an awkward trailing 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
          ]
      ]
  ]

red does not have a USE function

This introduces a complication as I only want to bind the block to the word VALUE. If I were to rewrite the function as follows:
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
]

Then it also binds that same block to the words SERIES and CRITERIA which would override the binding of any such words from the calling context, e.g.:
walk [some values][series: none probe value] ; results in error

