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?

Reply via email to