diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | eval.c | 25 | ||||
-rw-r--r-- | lib.c | 10 | ||||
-rw-r--r-- | lib.h | 1 | ||||
-rw-r--r-- | txr.1 | 38 |
5 files changed, 81 insertions, 5 deletions
@@ -1,5 +1,17 @@ 2014-07-19 Kaz Kylheku <kaz@kylheku.com> + * eval.c (mapdov): New function. + (eval_init): Register mapdo intrinsic. + + * lib.c (mapdo): New function. + + * lib.h (mapdo): Declared. + + * txr.1: Documented mapdo. Documented zero-argument case + for mapcar, mapcar*, mappend and mappend*. + +2014-07-19 Kaz Kylheku <kaz@kylheku.com> + * stream.c (put_strings, put_lines): New functions. (stream_init): Registered new functions as intrinsics. @@ -2958,6 +2958,30 @@ static val lazy_mappendv(val fun, val list_of_lists) return lazy_appendv(lazy_mapcarv(fun, list_of_lists)); } +static val mapdov(val fun, val list_of_lists) +{ + if (!cdr(list_of_lists)) { + return mapdo(fun, car(list_of_lists)); + } else { + val lofl = mapcar_listout(func_n1(nullify), list_of_lists); + + for (;;) { + val iter; + list_collect_decl (args, atail); + + for (iter = lofl; iter; iter = cdr(iter)) { + val list = car(iter); + if (!list) + return nil; + atail = list_collect(atail, car(list)); + deref(car_l(iter)) = cdr(list); + } + + apply(fun, args, nil); + } + } +} + static val symbol_value(val sym) { return cdr(lookup_var(nil, sym)); @@ -3506,6 +3530,7 @@ void eval_init(void) reg_fun(intern(lit("mapcar*"), user_package), func_n1v(lazy_mapcarv)); reg_fun(intern(lit("mappend"), user_package), func_n1v(mappendv)); reg_fun(intern(lit("mappend*"), user_package), func_n1v(lazy_mappendv)); + reg_fun(intern(lit("mapdo"), user_package), func_n1v(mapdov)); reg_fun(apply_s, func_n1v(apply_intrinsic)); reg_fun(iapply_s, func_n1v(iapply)); reg_fun(call_s, func_n1v(call)); @@ -4979,6 +4979,16 @@ val mappend(val fun, val list) return make_like(out, list_orig); } +val mapdo(val fun, val list) +{ + list = nullify(list); + + for (; list; list = cdr(list)) + funcall1(fun, car(list)); + + return nil; +} + static val lazy_interpose_func(val env, val lcons) { cons_bind (sep, list, env); @@ -743,6 +743,7 @@ val mapcar_listout(val fun, val list); val mapcar(val fun, val list); val mapcon(val fun, val list); val mappend(val fun, val list); +val mapdo(val fun, val list); val interpose(val sep, val seq); val merge(val list1, val list2, val lessfun, val keyfun); val sort(val seq, val lessfun, val keyfun); @@ -8058,15 +8058,18 @@ preserved. .TP Syntax: - (mapcar <function> <list> <list>*) - (mappend <function> <list> <list>*) - (mapcar* <function> <list> <list>*) - (mappend* <function> <list> <list>*) + (mapcar <function> <list>*) + (mappend <function> <list>*) + (mapcar* <function> <list>*) + (mappend* <function> <list>*) .TP Description: -When given three arguments, the mapcar function applies <function> to +When given only one argument, the mapcar function returns nil. +The <function> is never called. + +When given two arguments, the mapcar function applies <function> to the elements of <list> and returns a list of the resulting values. Essentially, the list is filtered through the function. @@ -8124,6 +8127,31 @@ Examples: (mappend (lambda (item) (if (evenp x) (list x))) '(1 2 3 4 5)) -> (2 4) +.SS Function mapdo + +.TP +Syntax: + + (mapdo <function> <sequence>*) + +.TP +Description: + +The mapdo function is similar to mapcar, but always returns nil. It is useful +when <function> performs some kind of side effect, hence the "do" in the name, +which is a mnemonic for the execution of imperative actions. + +When only the <function> argument is given, the function is never called, +and nil is returned. + +If a single <sequence> argument is given, then mapdo iterates over +<sequence>, invoking <function> on each element. + +If two or more <sequence> arguments are given, then mapdo iterates over +the sequences in parallel, extracting parallel tuples of items. These +tuples are passed as arguments to <function>, which must accept as many +arguments as there are sequences. + .SS Functions transpose and zip .TP |