summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--eval.c14
-rw-r--r--lib.c17
-rw-r--r--lib.h1
-rw-r--r--txr.124
5 files changed, 55 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index fbd077f4..e05820a9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
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.
+
+ * lib.c (tolist): New function.
+
+ * lib.h (tolist): Declared.
+
+ * txr.1: Document how apply and dot position in compound forms
+ supports strings as well as vectors.
+
+2014-02-02 Kaz Kylheku <kaz@kylheku.com>
+
* eval.c (do_eval_args): If the dotted position of the argument
list evaluates to a vector, then convert the vector to a list.
diff --git a/eval.c b/eval.c
index 94332315..888c7e49 100644
--- a/eval.c
+++ b/eval.c
@@ -312,8 +312,13 @@ val apply(val fun, val arglist, val ctx_form)
type_check (fun, FUN);
- type_assert (listp(arglist),
- (lit("~s: arglist ~s is not a list"), car(ctx_form), arglist, nao));
+ if (!listp(arglist)) {
+ val arglist_conv = tolist(arglist);
+ type_assert (listp(arglist_conv),
+ (lit("~s: arglist ~s is not a list"), car(ctx_form),
+ arglist, nao));
+ arglist = arglist_conv;
+ }
variadic = fun->f.variadic;
fixparam = fun->f.fixparam;
@@ -430,9 +435,8 @@ static val do_eval_args(val form, val env, val ctx_form,
ptail = list_collect(ptail, do_eval(car(form), env, ctx_form, lookup));
if (form) {
val dotpos = do_eval(form, env, ctx_form, lookup);
- ptail = list_collect_append(ptail, if3(vectorp(dotpos),
- list_vector(dotpos),
- dotpos));
+ ptail = list_collect_append(ptail, if3(listp(dotpos),
+ dotpos, tolist(dotpos)));
}
return values;
}
diff --git a/lib.c b/lib.c
index d490a2c1..d2fa0147 100644
--- a/lib.c
+++ b/lib.c
@@ -470,6 +470,23 @@ val to_seq(val seq)
}
}
+val tolist(val seq)
+{
+ switch (type(seq)) {
+ case VEC:
+ return list_vector(seq);
+ case STR:
+ case LIT:
+ case LSTR:
+ return list_str(seq);
+ case NIL:
+ case CONS:
+ case LCONS:
+ default:
+ return seq;
+ }
+}
+
val *list_collect(val *ptail, val obj)
{
switch (type(*ptail)) {
diff --git a/lib.h b/lib.h
index 6a12cf36..451fe234 100644
--- a/lib.h
+++ b/lib.h
@@ -377,6 +377,7 @@ val push(val v, val *plist);
val copy_list(val list);
val make_like(val list, val thatobj);
val to_seq(val obj);
+val tolist(val seq);
val nreverse(val in);
val reverse(val in);
val append2(val list1, val list2);
diff --git a/txr.1 b/txr.1
index 33f9d267..e2e4a383 100644
--- a/txr.1
+++ b/txr.1
@@ -5022,10 +5022,11 @@ If the form is a function call then the arguments are evaluated. If any of the
arugments are symbols, they are treated according to Lisp-2 namespacing rules.
Additionally, if there is an expression in the dotted position, it is also
-evaluated. It should evaluate to a list or vector. The elements of the list
-or vector generate additional arguments for the function call.
-In some other Lisp dialects, a function called apply (or similar) must be
-used to do the same thing.
+evaluated. It should evaluate to a sequence: a list, vector or string. The
+elements of the sequence generate additional arguments for the function
+call. In some other Lisp dialects, a function called apply (or similar) must
+be used to do the same thing, and applying sequences other than lists is not
+supported.
The DWIM brackets are similar, except that the first position is an arbitrary
expression which is evaluated according to the same rules as the remaining
@@ -5041,9 +5042,11 @@ Examples:
;; a contains 3
;; b contains 4
;; c contains #(5 6 7)
+ ;; s contains "xyz"
(foo a b . c) ;; calls (foo 3 4 5 6 7)
(foo a) ;; calls (foo 3)
+ (foo . s) ;; calls (foo #\ex #\ey #\ez)
[foo a b . c] ;; calls (foo 3 4 5 6 7)
@@ -7130,14 +7133,16 @@ can be expressed as:
.TP
Syntax:
- (apply <function> <arglist>)
+ (apply <function> <argsequence>)
.TP
Description:
-The apply function converts a list of values <arglist> into individual arguments
-which are passed to <function>. The return value of the apply invocation is
-that of <function>.
+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>.
+
+<argsequence> must be list, vector or string.
.TP
Examples:
@@ -7145,6 +7150,9 @@ Examples:
;; '(1 2 3) becomes arguments to list, thus (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: