Index arguments from 0 in with-copy

Indexing from zero is consistent with the rest of Carp's indexing
behavior, so this should make the function more predictable. I've also
added a note to the docs about this.
This commit is contained in:
Scott Olsen 2020-08-18 22:52:56 -04:00
parent 3a82e7d5c0
commit af1d0065e2
2 changed files with 9 additions and 6 deletions

View File

@ -129,8 +129,8 @@
(doc with-copy
"Returns a reference to an anonymous 'proxied' variant of `function` in
which the argument in position `arg` is *copied* from a reference before being
passed to `function`:
which the argument in position `arg` (indexed from 0) is *copied* from a
reference before being passed to `function`:
```
;; Array.reduce expects a function that takes a *ref* in its second argument:
@ -161,11 +161,14 @@
(defmacro with-copy [function arg]
;; The calls to `eval` around `function` are necessary to ensure we can execute arity.
(let [arg-arr (Dynamic.unreduce inc 0 (Introspect.arity (eval function)) (array))
;; increment arg by 1 to simulate indexing from 0--since the
;; functions we rely on here return counts
pos (+ arg 1)
local-names (list-to-array-internal (map gensym-local (map Symbol.from arg-arr)) [])
target (gensym-local (Symbol.from arg))
target (gensym-local (Symbol.from pos))
prox (list 'copy target)
call (cons function (map (fn [x] (if (= target x) prox x)) local-names))]
(if (> arg (Introspect.arity (eval function)))
(macro-error "proxy error: the specified argument position is greater than the given function's arity.")
(if (> pos (Introspect.arity (eval function)))
(macro-error "with-copy error: the specified argument position is greater than the given function's arity.")
(list 'ref (list 'fn local-names call)))))
)

View File

@ -55,6 +55,6 @@
"arity works as expected")
(assert-equal test
6
(Array.reduce (Introspect.with-copy add 2) 0 &[1 2 3])
(Array.reduce (Introspect.with-copy add 1) 0 &[1 2 3])
"with-copy works as expected")
)