summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-09-01 06:40:36 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-09-01 06:40:36 -0700
commit286bb507a316acefcecc87865f3a152c403ea8b3 (patch)
tree9f1df698308ae963da85ac31847a9197582f3450
parent2c773cc08d1945df2b410863512305140ac9d9da (diff)
downloadtxr-286bb507a316acefcecc87865f3a152c403ea8b3.tar.gz
txr-286bb507a316acefcecc87865f3a152c403ea8b3.tar.bz2
txr-286bb507a316acefcecc87865f3a152c403ea8b3.zip
New function: reject.
* eval.c (eva_init): Register reject intrinsic. * lib.c (appendl): New static function. (reject): New function. * lib.h (reject): Declared. * txr.1: Documented.
-rw-r--r--eval.c1
-rw-r--r--lib.c45
-rw-r--r--lib.h1
-rw-r--r--txr.170
4 files changed, 117 insertions, 0 deletions
diff --git a/eval.c b/eval.c
index 1091432d..de2acf92 100644
--- a/eval.c
+++ b/eval.c
@@ -6963,6 +6963,7 @@ void eval_init(void)
reg_fun(intern(lit("contains"), user_package), func_n4o(contains, 2));
reg_fun(intern(lit("where"), user_package), func_n2(where));
reg_fun(intern(lit("select"), user_package), func_n2(sel));
+ reg_fun(intern(lit("reject"), user_package), func_n2(reject));
reg_fun(intern(lit("relate"), user_package), func_n3o(relate, 2));
reg_fun(intern(lit("seq-begin"), user_package), func_n1(seq_begin));
reg_fun(intern(lit("seq-next"), user_package), func_n2(seq_next));
diff --git a/lib.c b/lib.c
index cbf9cc2a..0f7595c4 100644
--- a/lib.c
+++ b/lib.c
@@ -2071,6 +2071,12 @@ val appendv(struct args *lists)
return out;
}
+static val appendl(val lists)
+{
+ args_decl_list(args, ARGS_MIN, lists);
+ return appendv(args);
+}
+
val nappend2(val list1, val list2)
{
list_collect_decl (out, ptail);
@@ -11717,6 +11723,45 @@ val sel(val seq, val where_in)
return make_like(out, seq);
}
+val reject(val seq, val where_in)
+{
+ val self = lit("reject");
+ seq_info_t si = seq_info(seq);
+ val (*appendfn)(val) = lazy_appendl;
+
+ switch (si.kind) {
+ case SEQ_NIL:
+ return nil;
+ case SEQ_HASHLIKE:
+ {
+ seq_iter_t wh_iter;
+ val wh;
+ val newhash = copy_hash(si.obj);
+ val where = if3(functionp(where_in),
+ funcall1(where_in, seq),
+ where_in);
+ seq_iter_init(self, &wh_iter, where);
+
+ while (seq_get(&wh_iter, &wh))
+ remhash(newhash, wh);
+
+ return newhash;
+ }
+ case SEQ_VECLIKE:
+ appendfn = appendl;
+ /* fallthrough */
+ case SEQ_LISTLIKE:
+ {
+ val list = appendfn(split_star(seq, where_in));
+ return make_like(list, seq);
+ }
+ break;
+ case SEQ_NOTSEQ:
+ default:
+ type_mismatch(lit("~a: ~s is not a sequence"), self, seq, nao);
+ }
+}
+
static val do_relate(val env, val arg)
{
cons_bind (dom, rng, env);
diff --git a/lib.h b/lib.h
index e74ed15f..c6f90a58 100644
--- a/lib.h
+++ b/lib.h
@@ -1185,6 +1185,7 @@ val contains(val key, val seq, val testfun, val keyfun);
val rsearch(val seq, val key, val from, val to);
val where(val func, val seq);
val sel(val seq, val where);
+val reject(val seq, val where);
val relate(val domain_seq, val range_seq, val dfl_val);
val rcons(val from, val to);
val rangep(val obj);
diff --git a/txr.1 b/txr.1
index 84d2512f..a44fb8c5 100644
--- a/txr.1
+++ b/txr.1
@@ -31826,6 +31826,76 @@ from the input sequence, and a new
is returned whose storage is initialized by converting the extracted
values back to the foreign representation.
+.coNP Function @ reject
+.synb
+.mets (reject < sequence >> { index-list | << function })
+.syne
+.desc
+The
+.code reject
+function returns a sequence, of the same kind as
+.metn sequence ,
+which consists of all those elements of
+.meta sequence
+which are not identified by the indices in
+.metn index-list ,
+which may be a list or a vector.
+
+If
+.meta function
+is given instead of
+.metn index-list ,
+then
+.meta function
+is invoked with
+.meta sequence
+as its argument. The return value is then taken as
+if it were the
+.meta index-list
+argument .
+
+If
+.code sequence
+is a hash, then
+.meta index-list
+represents a list of keys. The
+.code reject
+function returns a duplicate of the hash, in which
+the keys specified in
+.meta index-list
+do not appear.
+
+Otherwise if
+.meta sequence
+is a vector-like sequence, then the behavior of
+.code reject
+may be understood by the following equivalence:
+
+.verb
+ (reject seq idx) --> (make-like
+ [apply append (split* seq idx)]
+ seq)
+.brev
+
+where it is to be understood that
+.meta seq
+is evaluated only once.
+
+If
+.meta sequence
+is a list, then, similarly, the following equivalence applies:
+
+.verb
+ (reject seq idx) --> (make-like
+ [apply append* (split* seq idx)]
+ seq)
+.brev
+
+The input sequence is split into pieces at the indicated indices, such that
+the elements at the indices are removed and do not appear in the pieces. The
+pieces are then appended together in order, and the resulting list is coerced
+into the same type of sequence as the input sequence.
+
.coNP Function @ relate
.synb
.mets (relate < domain-seq < range-seq <> [ default-val ])