Skip to content

Instantly share code, notes, and snippets.

@hinjolicious
Forked from toomasv/lazy-range.red
Created May 29, 2026 06:56
Show Gist options
  • Select an option

  • Save hinjolicious/89c392e1eb7af47852ebf19a6f5c9216 to your computer and use it in GitHub Desktop.

Select an option

Save hinjolicious/89c392e1eb7af47852ebf19a6f5c9216 to your computer and use it in GitHub Desktop.
Range for on-demand evaluation
Red [
Author: "Toomas Vooglaid"
Date: 27-11-2017
]
lazy-range: function [
"Returns function that generates next value in (possibly infinite) range"
val [scalar!] "Initial value"
/step stp [scalar! block!] "By which to increment each next value"
/limit lim [integer!] "How many new values to generate"
/stop stopval [scalar! block!] "On which value to stop generation of new values; if block, then also after how may matches"
/circle crcl [scalar!] "To generate (possibly infinite) new values in limited range"
][
cx: context compose/deep [
limit: lim
stop: (either all [stop block? stopval][stopval/1][stopval])
step: (either step [([stp])][if percent? val [1%][1]])
val: (val)
count: 0
val2: none
cval: none
inc: if block? step [get step/2] ;either block? step [get step/2][:+]
circle: crcl
stop-count: (if all [stop block? stopval][stopval/2])
count-stop: 0
count-circle: 0
bstep: if block? step [either '- = step/2 [0 - step/3][step/3]]
b2stp: 0
next-val: does [
if any [limit circle][count: count + 1]
either any [
all [limit limit < count]
all [
stop
either circle [
if all [stop-count stop = val2][count-stop: count-stop + 1]
and~ stop = val2 either stop-count [stop-count = count-stop][true]
][
pick reduce [stop > val stop < val] either any [
all [number? step negative? step]
all [block? step '- = step/2]
][true][false]
]
]
][none][
either circle [
cval: either block? step [
either number? circle [
val2: val
b2stp: count - 1 * bstep % circle
val2/(step/1): val2/(step/1) + b2stp
val2
][cause-error 'user 'message ["Only integer! type supported for circle in case of block step!"]]
][
val + case [
or~ number? circle time? circle [count - 1 * step % circle]
true [cause-error 'user 'message ["Only numeric and time types supported for circle!"]]
]
]
][
also val val: either block? step [
val2: val
val2/(step/1): val2/(step/1) inc step/3
val2
][
val + step
]
]
]
]
]
:cx/next-val
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment