summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-01-14 06:57:43 -0800
committerKaz Kylheku <kaz@kylheku.com>2014-01-14 06:57:43 -0800
commit28bd257494d8a0a6337d6fdd06b820412a2f1c55 (patch)
treea7db5acbae930222af2fad3b6df20461725666d8
parent48c8cec1c83d70e23dc1359b85cfd9e36fdaa60f (diff)
downloadtxr-28bd257494d8a0a6337d6fdd06b820412a2f1c55.tar.gz
txr-28bd257494d8a0a6337d6fdd06b820412a2f1c55.tar.bz2
txr-28bd257494d8a0a6337d6fdd06b820412a2f1c55.zip
* eval.c (bind_args): Implemented default values for optional
arguments. (op_defun): Permit the syntax. * txr.1: Documented.
-rw-r--r--ChangeLog8
-rw-r--r--eval.c18
-rw-r--r--txr.16
3 files changed, 29 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index f7a0f4ac..46ff1909 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2014-01-14 Kaz Kylheku <kaz@kylheku.com>
+
+ * eval.c (bind_args): Implemented default values for optional
+ arguments.
+ (op_defun): Permit the syntax.
+
+ * txr.1: Documented.
+
2014-01-13 Kaz Kylheku <kaz@kylheku.com>
Support for pushing back bytes and characters into streams.
diff --git a/eval.c b/eval.c
index f9a68f95..ce610dd1 100644
--- a/eval.c
+++ b/eval.c
@@ -235,8 +235,11 @@ static val bind_args(val env, val params, val args, val ctx_form)
param = car(params);
}
+ if (optargs && consp(param))
+ param = car(param);
+
if (!bindable(param))
- eval_error(ctx_form, lit("~a: ~s is not a bindable sybol"),
+ eval_error(ctx_form, lit("~a: ~s is not a bindable symbol"),
car(ctx_form), param, nao);
new_bindings = acons(param, car(args), new_bindings);
@@ -254,9 +257,16 @@ static val bind_args(val env, val params, val args, val ctx_form)
if (!optargs)
eval_error(ctx_form, lit("~s: too few arguments"), car(ctx_form), nao);
while (consp(params)) {
- if (car(params) == colon_k)
+ val param = car(params);
+ val val = nil;
+ if (param == colon_k)
goto twocol;
- new_bindings = acons(car(params), nil, new_bindings);
+ if (consp(param)) {
+ val = car(cdr(param));
+ param = car(param);
+ }
+ new_bindings = acons(param, eval(val, env, ctx_form),
+ new_bindings);
params = cdr(params);
}
if (bindable(params))
@@ -758,6 +768,8 @@ static val op_defun(val form, val env)
colon = t;
continue;
}
+ if (colon && consp(param))
+ continue;
if (!bindable(param))
eval_error(form, lit("defun: parameter ~s is not a bindable symbol"), param, nao);
}
diff --git a/txr.1 b/txr.1
index a6760076..888d4cbc 100644
--- a/txr.1
+++ b/txr.1
@@ -5821,6 +5821,12 @@ but a separator between required parameters and optional parameters.
When the function is called, optional parameter for which arguments
are not supplied take on the value nil.
+An optional parameter can also be written in the form (<name> <expr>).
+In this situation, if the call does not specify a value for the parameter,
+then the parameter takes on the value of the expression <expr>.
+The expression is evaluated in the environment in which the lambda
+was constructed.
+
Functions created by lambda capture the surrounding variable bindings.