diff options
-rw-r--r-- | lib.c | 41 | ||||
-rw-r--r-- | tests/012/aseq.tl | 5 | ||||
-rw-r--r-- | txr.1 | 81 |
3 files changed, 121 insertions, 6 deletions
@@ -7235,6 +7235,29 @@ val replace_vec(val vec_in, val items, val from, val to) return vec_in; } +static val replace_obj(val obj, val items, val from, val to) +{ + val self = lit("replace"); + val lambda_set_meth = maybe_slot(obj, lambda_set_s); + + if (!lambda_set_meth) + uw_throwf(error_s, lit("~a: object ~s lacks ~s method"), + self, obj, lambda_set_s, nao); + + if (listp(from)) { + if (!missingp(to)) + uw_throwf(error_s, + lit("~a: to-arg not applicable when from-arg is a list"), + self, nao); + + (void) funcall3(slot(obj, lambda_set_s), obj, from, items); + } else { + (void) funcall3(slot(obj, lambda_set_s), obj, rcons(from, to), items); + } + + return obj; +} + val cat_vec(val list) { ucnum total = 0; @@ -9793,11 +9816,6 @@ val sub(val seq, val from, val to) switch (type(seq)) { case NIL: return nil; - case COBJ: - if (seq->co.cls == carray_s) - return carray_sub(seq, from, to); - seq = nullify(seq); - /* fallthrough */ case CONS: case LCONS: return sub_list(seq, from, to); @@ -9807,6 +9825,17 @@ val sub(val seq, val from, val to) return sub_str(seq, from, to); case VEC: return sub_vec(seq, from, to); + case COBJ: + if (seq->co.cls == carray_s) + return carray_sub(seq, from, to); + if (structp(seq)) { + val lambda_meth = maybe_slot(seq, lambda_s); + if (lambda_meth) + return funcall2(lambda_meth, seq, rcons(from, to)); + seq = nullify(seq); + return sub_list(seq, from, to); + } + /* fallthrough */ default: type_mismatch(lit("sub: ~s is not a sequence"), seq, nao); } @@ -9894,6 +9923,8 @@ val replace(val seq, val items, val from, val to) case COBJ: if (seq->co.cls == carray_s) return carray_replace(seq, items, from, to); + if (obj_struct_p(seq)) + return replace_obj(seq, items, from, to); /* fallthrough */ default: type_mismatch(lit("replace: ~s is not a sequence"), seq, nao); diff --git a/tests/012/aseq.tl b/tests/012/aseq.tl index fc6cf76b..dfb20118 100644 --- a/tests/012/aseq.tl +++ b/tests/012/aseq.tl @@ -5,7 +5,10 @@ (:method cdr (me) (if (cdr me.list) (new (add me.n (cdr me.list))))) (:method car (me) (+ me.n (car me.list))) (:method nullify (me) (if me.list me)) - (:method lambda (me i) (+ me.n (ref me.list i)))) + (:method lambda (me i) + (if (rangep i) + (mapcar (op + me.n) [me.list i]) + (+ me.n (ref me.list i))))) (defvarl o (new (add 3 (range 10 100 10)))) @@ -25961,6 +25961,32 @@ is a object, then the function behaves like .codn carray-sub . +If +.meta sequence +is a structure, it must support the +.code lambda +method. The +.code sub +operation is transformed into a call to the +.code lambda +method according to the following equivalence: + +.cblk + (sub o from to) <--> o.(lambda (rcons from to)) + (sub o : to) <--> o.(lambda (rcons : to)) + (sub o from) <--> o.(lambda (rcons from :)) + (sub o) <--> o.(lambda (rcons : :)) +.cble + +That is to say, the +.meta from +and +.code to +arguments are converted to range object. If either argument +is missing, the symbol +.code : +is used for the corresponding element of the range. + When a .code sub form is used as a syntactic place, that place denotes a slice of @@ -26107,6 +26133,61 @@ object, then behaves like .codn carray-replace . +If +.meta sequence +is a structure, then the structure must support the +.code lambda-set +method. The +.code replace +operation is translated into a call of the +.code lambda-set +method according to the following equivalences: + +.cblk + (replace o items from to) + <--> o.(lambda-set (rcons from to) items) + + (replace o items index-list) + <--> o.(lambda-set index-list items) +.cble + +Thus, the +.meta from +and +.meta to +arguments are converted to single range object, +whereas an +.meta index-list +is passed as-is. +It is an error if a +.code to +argument is given, and +.code from +is a list; the situation is diagnosed. If either +.code from +or +.code to +are omitted, the range object contains the +.code : +symbol in the corresponding place: + +.cblk + (replace o items from) + <--> o.(lambda-set (rcons from :) items) + + (replace o items : to) + <--> o.(lambda-set (rcons : to) items) + + (replace o items) + <--> o.(lambda-set (rcons : :) items) +.cble + +It is the responsibility of the object's +.code lambda-set +method to implement semantics consistent with the +description of +.codn replace . + .coNP Function @ take .synb .mets (take < count << sequence ) |