C-style for loops in REBOL

2019-07-07 08:23发布

问题:

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

回答1:

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.



回答2:

There is an optimized Cfor by Ladislav Mecir

cfor: func [
  {General loop}
  [throw]
  init [block!]
  test [block!]
  inc [block!]
  body [block!]
] [
  use set-words init reduce [
    :do init
    :while test head insert tail copy body inc
  ]
]


回答3:

The other control structure that most people would use in this particular case is repeat

repeat i 10 [print i]

which results in:

>> repeat i 10 [print i]
1
2
3
4
5
6
7
8
9
10

I generally do no use loop very often, but it can be used to a similar extent:

>> i: 1 
>> loop 10 [print ++ i]
1
2
3
4
5
6
7
8
9
10

Those are some useful control structures. Not sure if you were looking for cfor but you got that answer from others.



回答4:

I have implemented a function that works in the same way as a C for loop.

cfor: func [init condition update action] [
    do init
    while condition [
        do action
        do update
    ]
]

Here's an example usage of this function:

cfor [i: 0] [i < 10] [i: i + 1] [
    print i
]


回答5:

For simple initial value, upper limit and step, following works:

for i 0 10 2 
    [print i] 

This is very close to C for loop.



标签: rebol rebol3