C-style for loops in REBOL

rebol, rebol3

Solution

Because of the rebol3 tag, I'll assume this question pertains to Rebol 3.

Proposed "CFOR" for Rebol 3

For Rebol 3, there is a proposal (which got quite a bit of support) for a "general loop" very much along the lines of a C-style `for` and therefore currently going under the name of `cfor` as well: see CureCode issue #884 for all the gory details.

This includes a much refined version of Ladislav's original implementation, the current (as of 2014-05-17) version I'll reproduce here (without the extensive inline comments discussing implementation aspects) for the sake of easy reference:

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]
]

General problems with user-level control structure implementations in Rebol 3

One important general remark for all user-level implementation of control constructs in Rebol 3: there is no analogue to Rebol 2's `[throw]` attribute in R3 yet (see CureCode issue #539), so such user-written ("mezzanine", in Rebol lingo) control or loop functions have problems, in general.

In particular, this CFOR would incorrectly capture `return` and `exit`. To illustrate, consider the following function:

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

You'd (rightly) expect the `return` to actually return from `foo`. However, if you try the above, you'll find this expectation disappointed:

>> foo
before
1
2
3
after
== false

This remark of course applies to all the user-level implementation given as answers in this thread, until bug #539 is fixed.

Problem

I attempted to write a C-style for-loop in REBOL: ``` for [i: 0] [i < 10] [i: i + 1] [ print i ] ``` This syntax doesn't appear to be correct, though: ``` *** 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... ``` Does REBOL have any built-in function that is similar to a C-style for loop, or will I need to implement this function myself? The equivalent construct in a C-like language would look like this, but I'm not sure if it's possible to implement the same pattern in REBOL: ``` for(i = 0; i < 10; i++){ print(i); } ```

Original source