diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2024-06-17 16:40:31 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2024-06-17 16:49:05 -0700 |
commit | 881c87fa8856e0d66d1d13dda36c461dc95da0b7 (patch) | |
tree | 6a5fab43924d66514e223628f946f5e6ce2ea053 | |
parent | 775e10c4007c024981d0b27f5f2e54c8ac54c73d (diff) | |
download | txr-881c87fa8856e0d66d1d13dda36c461dc95da0b7.tar.gz txr-881c87fa8856e0d66d1d13dda36c461dc95da0b7.tar.bz2 txr-881c87fa8856e0d66d1d13dda36c461dc95da0b7.zip |
More work on copy-iter.
* lib.c (copy_iter): Use the copy method for arguments which
are structures, or else return just the objects if they
implement list-like sequences. Error out otherwise.
For an argument that is not an iterators or structure, error
out if it is not a number, nil, or a list-like sequence.
* txr.1: Documented.
-rw-r--r-- | lib.c | 45 | ||||
-rw-r--r-- | txr.1 | 53 |
2 files changed, 88 insertions, 10 deletions
@@ -1496,17 +1496,42 @@ val iter_catv(varg iters) val copy_iter(val iter) { - if (type(iter) == COBJ && iter->co.cls == seq_iter_cls) { - val iter_copy; - const struct seq_iter *sit = coerce(struct seq_iter *, iter->co.handle); - struct seq_iter *dit = coerce(struct seq_iter *, - chk_calloc(1, sizeof *dit)); - seq_iter_clone(dit, sit); - iter_copy = cobj(coerce(mem_t *, dit), seq_iter_cls, &seq_iter_cobj_ops); - gc_hint(iter); - return iter_copy; - } else { + val self = lit("copy-iter"); + + switch (type(iter)) { + case CHR: + case NUM: + case BGNUM: return iter; + case COBJ: + if (iter->co.cls == seq_iter_cls) { + val iter_copy; + const struct seq_iter *sit = coerce(struct seq_iter *, iter->co.handle); + struct seq_iter *dit = coerce(struct seq_iter *, + chk_calloc(1, sizeof *dit)); + seq_iter_clone(dit, sit); + iter_copy = cobj(coerce(mem_t *, dit), seq_iter_cls, &seq_iter_cobj_ops); + gc_hint(iter); + return iter_copy; + } + if (obj_struct_p(iter)) { + val copy_meth = get_special_slot(iter, copy_m); + if (copy_meth) + return funcall1(copy_meth, iter); + } + unsup_obj(self, iter); + /* fallthrough */ + default: + { + seq_info_t sinf = seq_info(iter); + switch (sinf.kind) { + case SEQ_NIL: + case SEQ_LISTLIKE: + return sinf.obj; + default: + unsup_obj(self, iter); + } + } } } @@ -21565,6 +21565,10 @@ as if by: .mono .meti (copy-cptr << object ) .onom +.coIP seq-iter +.mono +.meti (copy-iter << object ) +.onom .RE .IP @@ -40081,6 +40085,55 @@ is invoked on .meta seq and the result is returned. +.coNP Function @ copy-iter +.synb +.mets (copy-iter << iter ) +.syne +.desc +The +.code copy-iter +produces a duplicate +.meta iter +such that the duplicate iterator will traverse +the same sequence of items as +.meta iter +starting at the current point in the sequence indicated by iter. + +For some kinds of iterators, such as integers and conses, +.code copy-iter +just returns +.metn iter . + +If +.meta iter +is a structure object, then if it supports the +.code copy +method, that method is invoked and its return value is taken +as the iterator copy. Otherwise, +.meta iter +must implement a list-like sequence, in which case the object +is just returned. If +.code iter +is a structure which neither supports a +.code copy +method nor implements a list-like sequence by supporting the +.code car +method, an error exception is thrown. + +Note: iterators of type +.code seq-iter +can be copied with the +.code copy +function (which for those objects is defined in terms of +.codn copy-iter ). +However, the +.code copy +function has the wrong semantics for other kinds of iterator +objects. It refuses to copy certain atoms such as numbers, +and in the case of conses it behaves like +.codn copy-list , +which is unnecessary. + .coNP Function @ iter-cat .synb .mets (iter-cat << seq *) |