Search code examples
rebolrebol3

C-style for loops in REBOL


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);
}

Solution

  • Because of the 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.