diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-06-05 20:18:58 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-06-05 20:18:58 -0700 |
commit | eb2d229637284ac6b8822357ce59c007742c825c (patch) | |
tree | f98faa041513dacb9cbec438a86a686486c086fc /lib.c | |
parent | f64eaa8c6839247c4e3023d244fdc328fd455e8d (diff) | |
download | txr-eb2d229637284ac6b8822357ce59c007742c825c.tar.gz txr-eb2d229637284ac6b8822357ce59c007742c825c.tar.bz2 txr-eb2d229637284ac6b8822357ce59c007742c825c.zip |
nullify and empty: convert to seq_info.
Issues: (nullify 1..1) doesn't return nil as it
should, and (empty 1) fails.
* lib.c (seq_info): Since we would like nullify to use
seq_info, seq_info cannot call nullify. Transplant the probing
of the nullify method out of nullify and into here.
(nullify): Obtain a seq_info_t on the object. If it's not a
sequence and is not range, then just return the object.
Otherwise obtain a seq_iter_t sequence and peek whether it has
a next item.
(empty): Similarly, obtain an iterator and peek.
Definition of empty is relocated to be next to nullify.
* lib.h: Relocate declaration of empty, also.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 95 |
1 files changed, 28 insertions, 67 deletions
@@ -299,7 +299,13 @@ seq_info_t seq_info(val obj) } else if (cls == carray_s) { ret.kind = SEQ_VECLIKE; } else if (obj_struct_p(obj)) { - val sub = nullify(obj); + val sub = obj; + + if (obj_struct_p(obj)) { + val nullify_meth = get_special_slot(obj, nullify_m); + if (nullify_meth) + sub = funcall1(nullify_meth, obj); + } if (!sub) { ret.kind = SEQ_NIL; @@ -1418,39 +1424,31 @@ val tolist(val seq) } } -val nullify(val seq) +val nullify(val obj) { - switch (type(seq)) { - case NIL: - return nil; - case CONS: - case LCONS: - return seq; - case LIT: - case STR: - return c_str(seq)[0] ? seq : nil; - case LSTR: - return if3(length_str_gt(seq, zero), seq, nil); - case VEC: - return if3(length_vec(seq) != zero, seq, nil); - case BUF: - return if3(length_buf(seq) != zero, seq, nil); - case COBJ: - if (seq->co.cls == carray_s) - return if3(length_carray(seq) != zero, seq, nil); - if (seq->co.cls == hash_s) - return if3(hash_count(seq) != zero, seq, nil); - if (obj_struct_p(seq)) { - val nullify_meth = get_special_slot(seq, nullify_m); - if (nullify_meth) - return funcall1(nullify_meth, seq); - } - /* fallthrough */ - default: - return seq; + val self = lit("nullify"); + val elem; + seq_info_t si = seq_info(obj); + + if (si.kind == SEQ_NOTSEQ && si.type != RNG) { + return obj; + } else { + seq_iter_t iter; + seq_iter_init_with_info(self, &iter, si, 0); + return if2(seq_peek(&iter, &elem), obj); } } +val empty(val seq) +{ + val self = lit("empty"); + val elem; + seq_iter_t iter; + seq_iter_init(self, &iter, seq); + + return tnil(!seq_peek(&iter, &elem)); +} + val seqp(val obj) { seq_info_t si = seq_info(obj); @@ -10875,43 +10873,6 @@ val length(val seq) } } -val empty(val seq) -{ - switch (type(seq)) { - case NIL: - return t; - case CONS: - case LCONS: - return nil; - case LIT: - case STR: - return if2(c_str(seq)[0] == 0, t); - case LSTR: - return length_str_le(seq, zero); - case VEC: - return eq(length_vec(seq), zero); - case RNG: - return eql(from(seq), to(seq)); - case BUF: - return eq(length_buf(seq), zero); - case COBJ: - if (seq->co.cls == hash_s) - return eq(hash_count(seq), zero); - if (seq->co.cls == carray_s) - return eq(length_carray(seq), zero); - if (obj_struct_p(seq)) { - val length_meth = get_special_slot(seq, length_m); - val nullify_meth = if2(nilp(length_meth), get_special_slot(seq, nullify_m)); - if (length_meth) - return eq(funcall1(length_meth, seq), zero); - return if3(nullify_meth && funcall1(nullify_meth, seq), nil, seq); - } - /* fallthrough */ - default: - type_mismatch(lit("empty: ~s is not a sequence"), seq, nao); - } -} - val sub(val seq, val from, val to) { switch (type(seq)) { |