Skip to content

Commit c082953

Browse files
committed
Pass indexes to ARRAY/initial function
When calling ARRAY/initial with a function used to generate the values, pass the current index at the position the function is being called for, with each index in a block of sizes provided to create a multidimensional array being provided as a separate parameter to the function in the order specified in the sizes block. Uses APPLY so the function can optionally not take the parameters. Uses an internal function option for efficiency. See http://issue.cc/r3/2193 for details.
1 parent 25033f8 commit c082953

File tree

1 file changed

+23
-8
lines changed

1 file changed

+23
-8
lines changed

src/mezz/mezz-series.r

+23-8
Original file line numberDiff line numberDiff line change
@@ -85,24 +85,39 @@ array: func [
8585
size [integer! block!] "Size or block of sizes for each dimension"
8686
/initial "Specify an initial value for all elements"
8787
value "Initial value (will be called each time if a function)"
88-
/local block rest
88+
/local block rest word
89+
/with tag indexes ; Token to ensure internal use, and block of index expressions
8990
][
91+
unless same? :tag 'tag [with: tag: indexes: none] ; Enforced internal option
9092
if block? size [
93+
if all [not with any-function? :value] [ ; Make indexes to pass to function
94+
indexes: append/dup make block! 2 * length? size [index? block] length? size
95+
]
9196
if tail? rest: next size [rest: none]
9297
unless integer? set/any 'size first size [
9398
cause-error 'script 'expect-arg reduce ['array 'size type? :size]
9499
]
95100
]
96101
block: make block! size
97102
case [
98-
block? rest [
99-
loop size [block: insert/only block array/initial rest :value]
103+
block? :rest [
104+
either any-function? :value [ ; Must construct params to pass to function
105+
word: in make object! copy [x: block] 'x ; Make a persistent word for this level
106+
indexes: change next indexes word ; Put that word in the params block
107+
loop size [ ; Pass indexes block to recursive call, at that level's position
108+
set word insert/only get word array/initial/with rest :value 'tag indexes
109+
]
110+
block: get word
111+
] [ ; Regular value, no parameter handling needed
112+
loop size [block: insert/only block array/initial rest :value]
113+
]
100114
]
101115
series? :value [
102116
loop size [block: insert/only block copy/deep value]
103117
]
104-
any-function? :value [ ; So value can be a thunk :)
105-
loop size [block: insert/only block value] ; Called every time
118+
any-function? :value [
119+
unless indexes [indexes: [index? block]] ; Single dimension, single index
120+
loop size [block: insert/only block apply :value head indexes]
106121
]
107122
insert/dup block value size
108123
]
@@ -421,7 +436,7 @@ printf: func [
421436
split: func [
422437
"Split a series into pieces; fixed or variable size, fixed number, or at delimiters"
423438
series [series!] "The series to split"
424-
dlm [block! integer! char! bitset! any-string!] "Split size, delimiter(s), or rule(s)."
439+
dlm [block! integer! char! bitset! any-string!] "Split size, delimiter(s), or rule(s)."
425440
/into "If dlm is an integer, split into n pieces, rather than pieces of length n."
426441
/local size piece-size count mk1 mk2 res fill-val add-fill-val
427442
][
@@ -480,7 +495,7 @@ split: func [
480495
; implied empty field after it, which we add here.
481496
case [
482497
bitset? dlm [
483-
; ATTEMPT is here because LAST will return NONE for an
498+
; ATTEMPT is here because LAST will return NONE for an
484499
; empty series, and finding none in a bitest is not allowed.
485500
if attempt [find dlm last series] [add-fill-val]
486501
]
@@ -496,7 +511,7 @@ split: func [
496511
]
497512
]
498513
]
499-
514+
500515
res
501516
]
502517
]

0 commit comments

Comments
 (0)