summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-10-05 06:42:22 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-10-06 12:24:27 -0700
commit2d76229afdcdf356da469b6a81149553c1fd4952 (patch)
tree6e74d4748e6c05b9b1fb752f53855e3bf29f84c1
parent7f7379793f4732b09350798c22d9ed22dd2f11ba (diff)
downloadtxr-2d76229afdcdf356da469b6a81149553c1fd4952.tar.gz
txr-2d76229afdcdf356da469b6a81149553c1fd4952.tar.bz2
txr-2d76229afdcdf356da469b6a81149553c1fd4952.zip
New function: ginterate.
* eval.c (ginterate_func): New static function. (ginterate): New function. (eval_init): Registered ginterate as intrinsic. * txr.1: Documented.
-rw-r--r--eval.c31
-rw-r--r--txr.118
2 files changed, 48 insertions, 1 deletions
diff --git a/eval.c b/eval.c
index f9a51fed..68e4869b 100644
--- a/eval.c
+++ b/eval.c
@@ -3604,6 +3604,36 @@ static val giterate(val while_pred, val gen_fun, val init_val)
}
}
+static val ginterate_func(val env, val lcons)
+{
+ cons_bind (while_pred, gen_fun, env);
+ val next_item = funcall1(gen_fun, lcons->lc.car);
+
+ if (funcall1(while_pred, next_item)) {
+ val lcons_next = make_lazy_cons(lcons_fun(lcons));
+ rplacd(lcons, lcons_next);
+ rplaca(lcons_next, next_item);
+ } else {
+ rplacd(lcons, cons(next_item, nil));
+ }
+ return nil;
+}
+
+static val ginterate(val while_pred, val gen_fun, val init_val)
+{
+ init_val = default_bool_arg(init_val);
+
+ if (!funcall1(while_pred, init_val)) {
+ return cons(init_val, nil);
+ } else {
+ val lc = make_lazy_cons(func_f1(cons(while_pred, gen_fun),
+ ginterate_func));
+ rplaca(lc, init_val);
+ return lc;
+ }
+}
+
+
static val repeat_infinite_func(val env, val lcons)
{
if (!car(env))
@@ -4628,6 +4658,7 @@ void eval_init(void)
reg_fun(intern(lit("range*"), user_package), func_n3o(range_star, 0));
reg_fun(generate_s, func_n2(generate));
reg_fun(intern(lit("giterate"), user_package), func_n3o(giterate, 2));
+ reg_fun(intern(lit("ginterate"), user_package), func_n3o(ginterate, 2));
reg_fun(intern(lit("repeat"), user_package), func_n2o(repeat, 1));
reg_fun(intern(lit("pad"), user_package), func_n3o(pad, 1));
reg_fun(intern(lit("weave"), user_package), func_n0v(weavev));
diff --git a/txr.1 b/txr.1
index 4f496ec3..58c07039 100644
--- a/txr.1
+++ b/txr.1
@@ -15728,10 +15728,11 @@ argument is accessed. By that time, the variable is initialized
and holds the lazy cons itself, which creates the circular reference,
and a circular list.
-.coNP Functions @ generate and @ giterate
+.coNP Functions @ generate @, giterate and @ ginterate
.synb
.mets (generate < while-fun << gen-fun )
.mets (giterate < while-fun < gen-fun <> [ value ])
+.mets (ginterate < while-fun < gen-fun <> [ value ])
.syne
.desc
The
@@ -15815,10 +15816,25 @@ like this:
(lambda () (prog1 v (set v [g v])))))
.cble
+The
+.code ginterate
+function is a variant of
+.code giterate
+which includes the test-failing item in the generated sequence.
+That is to say
+.code ginterate
+generates the next value and adds it to the lazy list.
+The value is then tested using
+.metn while-fun .
+If that function returns
+.codn nil ,
+then the list is terminated, and no more items are produced.
+
.TP* Example:
.cblk
(giterate (op > 5) (op + 1) 0) -> (0 1 2 3 4)
+ (ginterate (op > 5) (op + 1) 0) -> (0 1 2 3 4 5)
.cble
.coNP Function @ repeat