summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-06-16 06:42:00 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-06-16 06:42:00 -0700
commit6ef95aee02b53e3bba0778ef2a94291c33c21cfb (patch)
treed08952fab9f44a7653333f2aaca3cce0f8dfefc7
parentd212fc6284a6b7858da4570ef4d22cb88eec747a (diff)
downloadtxr-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.c21
-rw-r--r--txr.150
2 files changed, 65 insertions, 6 deletions
diff --git a/lib.c b/lib.c
index bb5e7e51..e71a9a73 100644
--- a/lib.c
+++ b/lib.c
@@ -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);
diff --git a/txr.1 b/txr.1
index 3251c3f6..c37a620c 100644
--- a/txr.1
+++ b/txr.1
@@ -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