From 857dda93d112fdd5e776f5dce2bbfc8a51704b2a Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 27 Jan 2014 00:47:43 -0800 Subject: * 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. --- lib.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'lib.c') diff --git a/lib.c b/lib.c index ecabd77f..c83dde14 100644 --- a/lib.c +++ b/lib.c @@ -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)); -- cgit v1.2.3