diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-10-05 06:42:22 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-10-06 12:24:27 -0700 |
commit | 2d76229afdcdf356da469b6a81149553c1fd4952 (patch) | |
tree | 6e74d4748e6c05b9b1fb752f53855e3bf29f84c1 | |
parent | 7f7379793f4732b09350798c22d9ed22dd2f11ba (diff) | |
download | txr-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.c | 31 | ||||
-rw-r--r-- | txr.1 | 18 |
2 files changed, 48 insertions, 1 deletions
@@ -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)); @@ -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 |