summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-11-15 20:18:16 -0800
committerKaz Kylheku <kaz@kylheku.com>2023-11-15 20:18:16 -0800
commit2d9a3b40559d41b632eb230ea816076af52d4faf (patch)
treef54d3cd7d45c827c744d19f93230c8ee1e86e7a0
parent7d6caf9959e5bf92c6714ca19fb2f628d3c72bfb (diff)
downloadtxr-2d9a3b40559d41b632eb230ea816076af52d4faf.tar.gz
txr-2d9a3b40559d41b632eb230ea816076af52d4faf.tar.bz2
txr-2d9a3b40559d41b632eb230ea816076af52d4faf.zip
oop: allow del on struct sequences.
* lib.c (dwim_del): Remove check against structures from OBJ case; we just let this pass through to the logic that invokes replace. * tests/012/aseq.tl: New test cases. * txr.1: Document how del works on a [obj index] place.
-rw-r--r--lib.c3
-rw-r--r--tests/012/aseq.tl11
-rw-r--r--txr.153
3 files changed, 63 insertions, 4 deletions
diff --git a/lib.c b/lib.c
index 2e5cffef..0dc756ba 100644
--- a/lib.c
+++ b/lib.c
@@ -13453,9 +13453,6 @@ val dwim_del(val place_p, val seq, val ind_range)
(void) remhash(seq, ind_range);
return seq;
}
- if (obj_struct_p(seq))
- uw_throwf(error_s, lit("index/range delete: not supported for structs"),
- nao);
default:
break;
}
diff --git a/tests/012/aseq.tl b/tests/012/aseq.tl
index dfb20118..e1a55fb8 100644
--- a/tests/012/aseq.tl
+++ b/tests/012/aseq.tl
@@ -8,7 +8,11 @@
(:method lambda (me i)
(if (rangep i)
(mapcar (op + me.n) [me.list i])
- (+ me.n (ref me.list i)))))
+ (+ me.n (ref me.list i))))
+ (:method lambda-set (me i nv)
+ (if (rangep i)
+ (set [me.list i] (mapcar (lop - me.n) nv))
+ (set [me.list i] (- nv me.n)))))
(defvarl o (new (add 3 (range 10 100 10))))
@@ -16,3 +20,8 @@
(test (cadr o) 23)
(test [o 4] 53)
(test (cadr (last o)) nil)
+
+(test (set [o 0..3] '(1003 1103 1203)) (1003 1103 1203))
+(test o.list (1000 1100 1200 40 50 60 70 80 90 100))
+(test (del [o 1..4]) (1103 1203 43))
+(test o.list (1000 50 60 70 80 90 100))
diff --git a/txr.1 b/txr.1
index 5600bcd3..1e024a98 100644
--- a/txr.1
+++ b/txr.1
@@ -43611,6 +43611,59 @@ place denotes a value stored in a dynamic data set such as a hash table,
then deletion of that place implies deletion of the entry which holds
that value. If the entry is identified by a key, that key is also removed.
+If
+.code place
+is a DWIM bracket expression indexing into a structure, the structure
+is expected to implement the
+.code lambda
+and
+.code lambda-set
+methods. Moreover, the place form must have only two arguments:
+the object and an index argument. In other words, the
+.code del
+form must have this syntax:
+
+.mono
+.mets (del >> [ obj << index ])
+.onom
+
+The
+.code lambda
+method will be invoked with the unmodified
+.meta obj
+and
+.meta index
+arguments to determine the prior value to be returned.
+Then the
+.code lambda-set
+method will be invoked with three arguments:
+.metn obj ,
+a possibly modified
+.meta index
+value and the argument
+.code nil
+representing an empty replacement sequence.
+
+If
+.meta index
+is a sequence or range, it is passed to the
+.code lambda-set
+method unmodified. Otherwise it is expected to be an integer, and
+converted into a one-element range spanning the indicated element.
+For instance, if the
+.meta index
+value is
+.codn 3 ,
+it is converted to the range
+.codn "#R(3 4)" .
+In effect, the
+.code lambda-set
+method is thereby asked to replace the one-element subsequence starting at
+index
+.code 3
+with the empty sequence
+.codn nil .
+
.coNP Macro @ lset
.synb
.mets (lset <> { place }+ << sequence-expr )