Brian pointed me to the goal directed programming (Anrew, you
beast!...), and I started to think about its feasibility in Rebol.
The first sign of the goal directed programming is Rebol Any
function.
To make something similar I tried to write a Break-transparent
while function. The task is easy to accomplish with recursion, I
tried to use another approach (modify existing Rebol While).
Here's the result:
inblock: func [
{returns a block containing a value}
value [any-type!]
] [
head insert/only copy [] get/any 'value
]
transp-break: func [
{a transparent break function}
/return value [any-type!]
] [
throw either return [
append/only copy [
bt-while break/return first
] inblock get/any 'value
] [
[bt-while break]
]
]
bt-while: func [
{a break-transparent While}
[catch throw]
cond-block [block!]
body-block [block!]
/local orig-break blk
] [
; change Break to Transparent-break and save the original
set [break orig-break] reduce [:transp-break :break]
; do cycle and save the result
error? set/any 'blk try [
catch [
append/only copy [
bt-while first
] inblock while cond-block body-block
]
]
; restore Break
break: :orig-break
; error or foreign throw?
either any [
error? get/any 'blk
not block? get/any 'blk
'bt-while <> pick :blk 1
] [
if error? blk: try [throw get/any 'blk] [
throw :blk
]
] [do next blk]
]
{
Example
repeat i 4 [
j: 0
bt-while [j: j + 1 j <= 4] [
print ["i: " i "j: " j]
if j = 2 [break]
]
]
}
Known issues:
1) the Try doesn't catch all errors (throw errors not catched -
feedback #3484).
2) Catch cannot resume named Throw - a Rebol design flaw?