diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2025-03-07 00:11:37 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2025-03-07 00:11:37 -0800 |
commit | 07e40c025d65beeced5ac83485eb13dab9b7d2ae (patch) | |
tree | 8a6569af89018d5d9ff2622c8f7ad40fd236fd0e | |
parent | a68a67376127cb9accf26c4ed43438f188eb24c8 (diff) | |
download | txr-07e40c025d65beeced5ac83485eb13dab9b7d2ae.tar.gz txr-07e40c025d65beeced5ac83485eb13dab9b7d2ae.tar.bz2 txr-07e40c025d65beeced5ac83485eb13dab9b7d2ae.zip |
New function: iterp.
* eval.c (eval_init): Register iterp intrinsic.
* lib.[ch] (iterp): New function.
* tests/012/iter.tl: New tests.
* txr.1: Document iterp. Update documentation for iter-more,
iter-item and iter-step to more precisely identify which
objects are valid arguments in terms of iterp and additional
conditions, and that other objects throw a type-error
exception. Fix wrong references to iter-more under
documentation for iter-item. Removed obsolete text specifying
that iter-step uses car on list-like sequences, a dubious
behavior removed in the previous commit.
-rw-r--r-- | eval.c | 1 | ||||
-rw-r--r-- | lib.c | 22 | ||||
-rw-r--r-- | lib.h | 1 | ||||
-rw-r--r-- | tests/012/iter.tl | 20 | ||||
-rw-r--r-- | txr.1 | 126 |
5 files changed, 139 insertions, 31 deletions
@@ -7854,6 +7854,7 @@ void eval_init(void) reg_fun(intern(lit("iter-item"), user_package), func_n1(iter_item)); reg_fun(intern(lit("iter-step"), user_package), func_n1(iter_step)); reg_fun(intern(lit("iter-reset"), user_package), func_n2(iter_reset)); + reg_fun(intern(lit("iterp"), user_package), func_n1(iterp)); reg_fun(intern(lit("iter-cat"), user_package), func_n0v(iter_catv)); reg_fun(intern(lit("copy-iter"), user_package), func_n1(copy_iter)); @@ -1440,6 +1440,28 @@ val iter_reset(val iter, val obj) } } +val iterp(val obj) +{ + switch (type(obj)) { + case NIL: + case CHR: + case NUM: + case BGNUM: + case FLNUM: + case CONS: + case LCONS: + return t; + case COBJ: + if (obj->co.cls == seq_iter_cls) + return t; + if (obj_struct_p(obj) && get_special_slot(obj, iter_step_m)) + return t; + /* fallthrough */ + default: + return nil; + } +} + val iter_catv(varg iters) { cnum index = 0; @@ -775,6 +775,7 @@ val iter_more(val iter); val iter_item(val iter); val iter_step(val iter); val iter_reset(val iter, val obj); +val iterp(val obj); val iter_catv(varg iters); val copy_iter(val iter); void seq_build_init(val self, seq_build_t *bu, val likeobj); diff --git a/tests/012/iter.tl b/tests/012/iter.tl index 94a50f34..cebbca55 100644 --- a/tests/012/iter.tl +++ b/tests/012/iter.tl @@ -154,3 +154,23 @@ (iter-item #()) :error (iter-item #(1)) :error (iter-item #(1 2 3)) :error) + +(defstruct iter () + (:method iter-step (self))) + +(defstruct not-iter ()) + +(mtest + (iterp nil) t + (iterp '(a . b)) t + (iterp (lcons 3 4)) t + (iterp #\a) t + (iterp 42) t + (iterp (expt 2 512)) t + (iterp 3.14) t + (iterp (new iter)) t + (iterp (new not-iter)) nil + (iterp "abc") nil + (iterp (fun list)) nil + (iterp #/regex/) nil + (iterp #(vec)) nil) @@ -34399,6 +34399,10 @@ Additional objects that are not sequences are also iterable: numeric or character ranges, and numbers. Future revisions of the language may specify additional iterable objects. +Iterable objects are suitable arguments to the +.code iter-begin +function. + .coNP Functions @ make-like and @ seq-like .synb .mets (make-like < seq << object ) @@ -40086,6 +40090,53 @@ If .code seq is not an iterable object, an error exception is thrown. +.coNP Function @ iterp +.synb +.mets (iterp << obj ) +.syne +.desc +The +.code iterp +function returns +.code t +if +.meta obj +is an iterator object, otherwise +.codn nil . + +Note that this test is different from the +.code iterable +function, which tests whether it is possible to invoke +.code iter-begin +on an object to obtain an iterator. + +It is possible for an object to satisfy both +.code iterp +and +.codn iterable . + +The +.code iterp +function returns +.code t +for the following objects or types: +the empty list +.codn nil ; +conses, including lazy conses; +characters; and numbers both integer and floating-point. + +In addition, +.code iterp +returns +.code t +for struct objects which have an +.code iter-step +method. Note that such objects must satisfy additional +requirements to usefully behave as iterators. + +For all other objects, the function returns +.codn nil . + .coNP Function @ iter-more .synb .mets (iter-more << iter ) @@ -40101,11 +40152,19 @@ Otherwise it returns The .meta iter -argument must be a valid iterator returned by a call to -.metn iter-begin , -.meta iter-step -or -.metn iter-reset . +argument must be a valid iterator object, for which the +.code iterp +function returns +.codn t , +or else it must be a struct. As a special behavior in support +of the fast iteration protocol, if +.meta iter +is a struct which does not support the +.code iter-more +method, the +.code iter-more +function unconditionally returns +.codn t . The .code iter-more @@ -40189,6 +40248,11 @@ method, then .code t is returned. +For any other object, the +.code iter-more +throws an exception of type +.codn type-error . + .coNP Function @ iter-item .synb .mets (iter-item << iter ) @@ -40200,21 +40264,25 @@ function indicates that more items remain to be visited, then the next item can be retrieved using .codn iter-item . -The +Except if it is a struct, the .meta iter -argument must be a valid iterator returned by a call to -.metn iter-begin , -.meta iter-step -or -.metn iter-reset . +argument must be a valid iterator object, for which the +.code iterp +function returns +.codn t . +If +.meta iter +is a struct, it must implement the +.code iter-item +method. The -.code iter-more +.code iter-item function doesn't change the state of .metn iter . If -.code iter-more +.code iter-item is invoked on an iterator which indicates that no more items remain to be visited, the return value is .codn nil . @@ -40281,6 +40349,11 @@ is a structure which supports the .code iter-item method, then that method is called and its return value is returned. +For all other objects, +.code iter-item +throws an exception of type +.codn type-error . + .coNP Function @ iter-step .synb .mets (iter-step << iter ) @@ -40297,11 +40370,10 @@ remaining items in the sequence. The .meta iter -argument must be a valid iterator returned by a call to -.metn iter-begin , -.meta iter-step -or -.metn iter-reset . +argument must be a valid iterator object, for which the +.code iterp +function returns +.codn t . The .code iter-step @@ -40357,19 +40429,6 @@ and so on. If .meta iter -is a list-like sequence, then -.code cdr -is invoked on it and that value is returned. -The value must also be a list-like sequence, or else -.codn nil . -The reasoning for this is the same as for the similar -restriction imposed in the case when -.meta iter -is a -.codn cons . - -If -.meta iter is a character or number, then .code iter-step returns its successor, as if using the @@ -40382,6 +40441,11 @@ is a structure which supports the .code iter-step method, then that method is called and its return value is returned. +For all other objects, +.code iter-step +throws an exception of type +.codn type-error . + .coNP Function @ iter-reset .synb .mets (iter-reset < iter << seq ) |