diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2017-06-16 06:42:00 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2017-06-16 06:42:00 -0700 |
commit | 6ef95aee02b53e3bba0778ef2a94291c33c21cfb (patch) | |
tree | d08952fab9f44a7653333f2aaca3cce0f8dfefc7 | |
parent | d212fc6284a6b7858da4570ef4d22cb88eec747a (diff) | |
download | txr-6ef95aee02b53e3bba0778ef2a94291c33c21cfb.tar.gz txr-6ef95aee02b53e3bba0778ef2a94291c33c21cfb.tar.bz2 txr-6ef95aee02b53e3bba0778ef2a94291c33c21cfb.zip |
New length method on structures.
With this change, nreverse is possible on a struct,
if it has lambda, lambda-set and length methods.
* lib.c (length_s): New symbol variable.
(length): Check for length method and call it,
in preference to checking for car method and falling
back on cdr-based length.
(empty): If object has a length method, call it and
compare result to zero.
(obj_init): Initialize length_s.
* txr.1: Documented. We now have the concepts of structs
being vector-like sequences or list-like sequences.
-rw-r--r-- | lib.c | 21 | ||||
-rw-r--r-- | txr.1 | 50 |
2 files changed, 65 insertions, 6 deletions
@@ -107,7 +107,7 @@ val numeric_error_s, range_error_s; val query_error_s, file_error_s, process_error_s, syntax_error_s; val timeout_error_s, system_error_s; val warning_s, defr_warning_s, restart_s, continue_s; -val gensym_counter_s, nullify_s, from_list_s, lambda_set_s; +val gensym_counter_s, nullify_s, from_list_s, lambda_set_s, length_s; val nothrow_k, args_k, colon_k, auto_k, fun_k; val wrap_k, reflect_k; @@ -9175,8 +9175,17 @@ val length(val seq) return hash_count(seq); if (seq->co.cls == carray_s) return length_carray(seq); - if (structp(seq) && maybe_slot(seq, car_s)) - return length_proper_list(nullify(seq)); + if (structp(seq)) { + val length_meth = maybe_slot(seq, length_s); + + if (length_meth) + return funcall1(length_meth, seq); + + if (maybe_slot(seq, car_s)) + return length_proper_list(nullify(seq)); + + type_mismatch(lit("length: ~s has no length or car method"), seq, nao); + } /* fallthrough */ default: type_mismatch(lit("length: ~s is not a sequence"), seq, nao); @@ -9204,7 +9213,10 @@ val empty(val seq) if (seq->co.cls == hash_s) return eq(hash_count(seq), zero); if (structp(seq)) { - val nullify_meth = maybe_slot(seq, nullify_s); + val length_meth = maybe_slot(seq, length_s); + val nullify_meth = if2(nilp(length_meth), maybe_slot(seq, nullify_s)); + if (length_meth) + return eq(funcall1(length_meth, seq), zero); return if3(nullify_meth && funcall1(nullify_meth, seq), nil, seq); } default: @@ -9946,6 +9958,7 @@ static void obj_init(void) nullify_s = intern(lit("nullify"), user_package); from_list_s = intern(lit("from-list"), user_package); lambda_set_s = intern(lit("lambda-set"), user_package); + length_s = intern(lit("length"), user_package); args_k = intern(lit("args"), keyword_package); nothrow_k = intern(lit("nothrow"), keyword_package); @@ -24675,6 +24675,51 @@ An instance of this structure can now be used as follows: [s "apple"]) -> 3 .cble +.coNP Method @ length +.synb +.mets << object .(length) +.syne +.desc +If a structure has +.code length +method, then it can be used as an argument to the +.code length +function. + +Structures which implement the methods +.codn lambda , +.code lambda-ref +and +.code length +can be treated as abstract vector-like sequences, because such +structures support the +.codn ref , +.code refset +and +.code length +functions. + +For instance, the +.code nreverse +function will operate on such objects. + +Note: a structure which supports the +.code car +method also supports the +.code length +function, in a different way. Such a structure is treated by +.code length +as a list-like sequence, and its length is measured by walking the +sequence with +.code cdr +operations. If a structure supports both +.code length +and +.codn car , +preference is given to +.codn length , +which is likely to be much more efficient. + .coNP Methods @, car @ cdr and @ nullify .synb .mets << object .(car) @@ -24698,8 +24743,9 @@ by the functions and various other sequence manipulating functions derived from them, when those functions are applied to that object. -An object which implements these three methods can be considered to denote -an abstract sequence. +An object which implements these three methods can be considered to represent a +.I list-like +abstract sequence. The object's .code car |