diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2014-02-02 15:22:49 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2014-02-02 15:22:49 -0800 |
commit | 1d6ad5892120dd0ce3f1947ee87fe343fc932f0d (patch) | |
tree | d45fbe1a2ac898d768b075f0cfd6a401ddaef27c | |
parent | fd2690b7b18d46ea970f1ec828d7a35e31d4942b (diff) | |
download | txr-1d6ad5892120dd0ce3f1947ee87fe343fc932f0d.tar.gz txr-1d6ad5892120dd0ce3f1947ee87fe343fc932f0d.tar.bz2 txr-1d6ad5892120dd0ce3f1947ee87fe343fc932f0d.zip |
append can now take additional leading arguments before the list.
* eval.c (apply_frob_args): New static function.
(apply_intrinsic): Process arguments with apply_frob_args.
(eval_init): apply_intrinsic registered differently, as a
variadic function with one mandatory arg.
* lib.c (lastcons): New function.
* lib.h (lastcons): Declared.
* txr.1: Updated append documentation.
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | eval.c | 15 | ||||
-rw-r--r-- | lib.c | 10 | ||||
-rw-r--r-- | lib.h | 1 | ||||
-rw-r--r-- | txr.1 | 44 |
5 files changed, 64 insertions, 21 deletions
@@ -1,5 +1,20 @@ 2014-02-02 Kaz Kylheku <kaz@kylheku.com> + append can now take additional leading arguments before the list. + + * eval.c (apply_frob_args): New static function. + (apply_intrinsic): Process arguments with apply_frob_args. + (eval_init): apply_intrinsic registered differently, as a + variadic function with one mandatory arg. + + * lib.c (lastcons): New function. + + * lib.h (lastcons): Declared. + + * txr.1: Updated append documentation. + +2014-02-02 Kaz Kylheku <kaz@kylheku.com> + * eval.c (apply): Support string and vector arglist. (do_eval_args): Support string or vector in dot position. @@ -419,9 +419,20 @@ val apply(val fun, val arglist, val ctx_form) internal_error("corrupt function type field"); } +static val apply_frob_args(val args) +{ + val *plast = lastcons(args); + if (plast) { + *plast = car(*plast); + return args; + } else { + return car(args); + } +} + static val apply_intrinsic(val fun, val args) { - return apply(fun, args, cons(apply_s, nil)); + return apply(fun, apply_frob_args(args), cons(apply_s, nil)); } static val do_eval(val form, val env, val ctx_form, @@ -2384,7 +2395,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(apply_s, func_n2(apply_intrinsic)); + reg_fun(apply_s, func_n1v(apply_intrinsic)); reg_fun(intern(lit("reduce-left"), user_package), func_n4o(reduce_left, 2)); reg_fun(intern(lit("reduce-right"), user_package), func_n4o(reduce_right, 2)); @@ -400,6 +400,16 @@ val *tail(val cons) return cdr_l(cons); } +val *lastcons(val list) +{ + val *ret = 0; + while (consp(cdr(list))) { + ret = cdr_l(list); + list = cdr(list); + } + return ret; +} + val *ltail(val *cons) { while (cdr(*cons)) @@ -371,6 +371,7 @@ val lazy_conses(val list); val listref(val list, val ind); val *listref_l(val list, val ind); val *tail(val cons); +val *lastcons(val list); val *ltail(val *cons); val pop(val *plist); val push(val v, val *plist); @@ -7141,16 +7141,27 @@ can be expressed as: .TP Syntax: - (apply <function> <argsequence>) + (apply <function> [ {<arg>}* <trailing-args> ]) .TP Description: -The apply function converts a sequence of values <argsequence> into individual -arguments which are passed to <function>. The return value of the apply -invocation is that of <function>. +The apply function invokes <function>, optionally passing to it an argument +list. The return value of the apply call is that of <function>. -<argsequence> must be list, vector or string. +If no arguments are present after <function>, then <function> is invoked +without arguments. + +If one argument is present after <function>, then it is interpreted as +<trailing-args>. If this is a sequence (a list, vector or string), +then the elements of the sequence are passed as individual arguments to +<function>. If <trailing-args> is not a sequence, then the function is invoked +with an improper argument list, terminated by the <trailing-args> atom. + +If two or more arguments are present after <function>, then the last of +these arguments is interpreted as <trailing-args>. The previous arguments +represent leading arguments which are applied to <function>, prior to the +arguments taken from <trailing-args>. .TP Examples: @@ -7158,11 +7169,17 @@ Examples: ;; '(1 2 3) becomes arguments to list, thus (list 1 2 3). (apply (fun list) '(1 2 3)) -> (1 2 3) + ;; this effectively invokes (list 1 2 3 4) + (apply (fun list) 1 2 '(3 4)) -> (1 2 3) + + ;; this effectively invokes (list 1 2 . 3) + (apply (fun list) 1 2 3)) -> (1 2 . 3) + ;; "abc" is separated into characters which become arguments of list (apply (fun list) "abc") -> (#\ea #\eb #\ec) .TP -Dialect Note 1: +Dialect Note: Note that some uses of this function that are necessary in other Lisp dialects are not necessary in TXR Lisp. The reason is that in TXR Lisp, improper list @@ -7173,19 +7190,8 @@ syntax is accepted as a compound form, and performs application: Here, the variables a and b supply the first two arguments for foo. In the dotted position, x must evaluate to a list or vector. The list or vector's elements are pulled out and treated as additional arguments for foo. - -.TP -Dialect Note 2: - -TXR Lisp apply does not take additional arguments before the list. -In Common Lisp we can write (apply #'list 1 2 (list 3 4 5)) which -yields (1 2 3 4 5). -In TXR Lisp, - -In TXR Lisp, this usage can be simulated using the approach in the -previous Dialect Note 1, or by using code such as: -(apply (fun list) (list 1 2 (list 3 4 5))) or -(apply (fun list) '(,1 ,2 ,*(list 3 4 5))) . +Of course, this syntax can only be used if x is a symbolic form or an atom. It +cannot be a compound form. .SS Functions reduce-left and reduce-right |