diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-01-27 00:47:43 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-01-27 00:47:43 -0800 |
commit | 857dda93d112fdd5e776f5dce2bbfc8a51704b2a (patch) | |
tree | a0f2d19df381ecc4d7bf5c1bf144fc70e643309b /lib.c | |
parent | bcc1770bf64c62dc5c6404596017cf73a6c9e25e (diff) | |
download | txr-857dda93d112fdd5e776f5dce2bbfc8a51704b2a.tar.gz txr-857dda93d112fdd5e776f5dce2bbfc8a51704b2a.tar.bz2 txr-857dda93d112fdd5e776f5dce2bbfc8a51704b2a.zip |
* lib.c (reduce_left, reduce_right): changing the behavior so that
the initial value is optional. this creates the possibility that
the effective list of operands is empty, in which case the function
must support a call with no arguments, just like in the common lisp
reduce.
* txr.1: rewrote reduce-left and reduce-right documentation.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 25 |
1 files changed, 24 insertions, 1 deletions
@@ -3542,6 +3542,12 @@ val reduce_left(val fun, val list, val init, val key) if (!key) key = identity_f; + if (!init && list) + init = pop(&list); + + if (!init && !list) + return funcall(fun); + for (; list; list = cdr(list)) init = funcall2(fun, init, funcall1(key, car(list))); @@ -3553,8 +3559,25 @@ val reduce_right(val fun, val list, val init, val key) if (!key) key = identity_f; - if (nullp(list)) + if (list) { + if (!init) { + if (!rest(list)) + return funcall1(key, first(list)); + if (!rest(rest(list))) + return funcall2(fun, funcall1(key, first(list)), + funcall1(key, second(list))); + /* fall through: no init, three or more items in list */ + } else { + if (!rest(list)) + return funcall2(fun, funcall1(key, first(list)), init); + /* fall through: init, and two or more items in list */ + } + } else if (init) { return init; + } else { + return funcall(fun); + } + return funcall2(fun, funcall1(key, car(list)), if3(cdr(list), reduce_right(fun, cdr(list), init, key), init)); |