red / REP

Red Enhancement Process
BSD 3-Clause "New" or "Revised" License
11 stars 4 forks source link

REP 101 - For Loop Function #6

Open PeterWAWood opened 6 years ago

PeterWAWood commented 6 years ago

I believe there are better options to provide equivalent functionality in an easier to use way. The alternatives include:

foreach range foreach [series comprehension] foreach [lazy series generator]

Rust has for x in 0..10 for ranges Python has for x in [x in range(100) if x % 2 == 0] for series comprehensions Python has for x in itertools.count() for lazy series generators.

I think it would be much more worthwhile to add ranges, series comprehensions and lazy series generators.

greggirwin commented 6 years ago

Link to REP: https://github.com/red/REP/blob/master/rep-0101.adoc

greggirwin commented 6 years ago

@PeterWAWood, could you mock up equivalents for the interface options from the REP, maybe starting with list comprehensions. I have some things on those, but more on ranges and generators that I could work up comparisons for. I'll also try to clear my mind and think of alternatives. Hard though, because, to me,

for [i = 1 to 100 step 2]

Seems much clearer than

for x in [x in range(100) if x % 2 == 0]

A bit late right now, so I'll try to give it a look with fresh eyes tomorrow.

PeterWAWood commented 6 years ago

Assuming that there is a range function which has a tuple! parameter. range 2.10.2 would return [ 2 4 6 8 10]. range 1.10.1 would return [1 2 3 4 5 6 7 8 9 10].

So we could have:

even-up-to-ten: range 2.10.2
foreach i even-up-to-ten [ ... ]

foreach i range 2.10.2 [ ... ]

Assuming series comprehension syntax to be `block-from [foreach x a-block [if x = 2 [x * x ]], we could have:

numbers: range 0.100.1
even-squared-numbers: block-from [foreach x numbers [if x = 2 [x *x]]
for i even-squared-numbers [ ... ]

(I'm sure it is possible to come up with better syntax with some deeper thought).

Assuming there is a yield function and that iterators signal stop by calling an iterator-end function. We could have something like:

infinite-ints: func [/local i] [
    i: [1]
    until [
        yield i
        i: i + 1
    ]
]

foreach i infinite-ints [ ... ]
PeterWAWood commented 6 years ago

I will mock up equivalents to the example given in the proposal when I have a little more time.

PeterWAWood commented 6 years ago

I guess we already have series comprehensions:

>> list: collect [foreach x [1 2 3 4 5 6 7 8] [if x % 2 = 0 [keep x * x]]]
== [4 16 36 64]
PeterWAWood commented 6 years ago

I've duplicated most of your examples for the proposal. The vast majority of them can be satisfied with a very simple range function that I wrote. It couldn't handle the scientific notation example but I guess it could be enhanced to do so.

There was only one case where I needed to use something other than the range function. I used collect as a block comprehension but it looks very clunky. There is probably some syntactic sugar that could make it look better.

My code is for-alternatives.red

JEROME-TICTEC commented 1 year ago

Hi guys, old REP, but never mind here is a simpler solution (with a refinment to call an internal loop func, in case of pointer value needing)

For: function [pnter step target cmd /Fn /local c][
    c:  target
    while [not (c = (pnter - 1))][
            either Fn [
                do rejoin [ cmd " " (pnter + (target - c ))]
                    ][
                    do cmd
                    ]
            c: c - step
    ]
]

ForFn: function [pnter] [
    print pnter
]

use cases:

>> For/Fn 1 1 3 "ForFn"
1
2
3
>> For 1 1 3 [print "hello"]
hello
hello
hello
>> For 1 -1 -3 [print "hello"]
hello
hello
hello