summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-02-14 06:46:45 -0800
committerKaz Kylheku <kaz@kylheku.com>2019-02-14 06:46:45 -0800
commit4477112731119ebc28d5e4a9dce858d8d008af36 (patch)
tree7ac7093b4b934dc4304f7f3984aebbea542506d8 /lib.c
parent014c61e860fce07cceee60efecd949a17e53f2ae (diff)
downloadtxr-4477112731119ebc28d5e4a9dce858d8d008af36.tar.gz
txr-4477112731119ebc28d5e4a9dce858d8d008af36.tar.bz2
txr-4477112731119ebc28d5e4a9dce858d8d008af36.zip
symdiff: new function.
* eval.c (eval_init): Register symdiff intrinsic. * lib.c (symdiff): New function. * lib.h (us_car_p, us_cdr_p): New inline functions. (symdiff): Declared. * txr.1: Documented, also fixing issues not related to symdiff doc.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/lib.c b/lib.c
index f5a3d920..b56a4a5b 100644
--- a/lib.c
+++ b/lib.c
@@ -9994,6 +9994,49 @@ val set_diff(val list1, val list2, val testfun, val keyfun)
return make_like(out, list_orig);
}
+val symdiff(val seq1, val seq2, val testfun, val keyfun)
+{
+ val self = lit("symdiff");
+ list_collect_decl (out, ptail);
+ seq_iter_t si1, si2;
+ val el1, el2;
+
+ testfun = default_arg(testfun, equal_f);
+ keyfun = default_arg(keyfun, identity_f);
+
+ seq_iter_init(self, &si1, seq1);
+ seq_iter_init(self, &si2, seq2);
+
+ while (seq_get(&si1, &el1))
+ ptail = list_collect(ptail, el1);
+
+ while (seq_get(&si2, &el2)) {
+ val el2_key = funcall1(keyfun, el2);
+ val *iter;
+ int found = 0;
+
+ for (iter = &out; *iter; ) {
+ val elo = us_car(*iter);
+ val elo_key = funcall1(keyfun, elo);
+ if (funcall2(testfun, elo_key, el2_key)) {
+ val del = us_cdr(*iter);
+ if (deref(ptail) == del)
+ ptail = mkcloc(*iter);
+ *iter = del;
+ found = 1;
+ break;
+ } else {
+ iter = us_cdr_p(*iter);
+ }
+ }
+
+ if (!found)
+ ptail = list_collect(ptail, el2);
+ }
+
+ return make_like(out, seq1);
+}
+
val isec(val seq1, val seq2, val testfun, val keyfun)
{
val self = lit("isec");