summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-07-28 22:21:13 -0700
committerKaz Kylheku <kaz@kylheku.com>2014-07-28 22:21:13 -0700
commit2014daea4ca5a4f92afc07bbc08dfdcb6c095a12 (patch)
tree9842d17277a17295030902914a78c89bc8648610
parentb9e5782453ab8f89ac15219b4d20301f7c19545a (diff)
downloadtxr-2014daea4ca5a4f92afc07bbc08dfdcb6c095a12.tar.gz
txr-2014daea4ca5a4f92afc07bbc08dfdcb6c095a12.tar.bz2
txr-2014daea4ca5a4f92afc07bbc08dfdcb6c095a12.zip
* eval.c (eval_init): Register partition-by intrinsic.
* lib.c (partition_by_func): New static function. (partition_by): New function. * lib.h (partition_by): Declared. * txr.1: Documented partition-by.
-rw-r--r--ChangeLog11
-rw-r--r--eval.c1
-rw-r--r--lib.c46
-rw-r--r--lib.h1
-rw-r--r--txr.139
5 files changed, 98 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index a148c69c..c01eea05 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2014-07-28 Kaz Kylheku <kaz@kylheku.com>
+ * eval.c (eval_init): Register partition-by intrinsic.
+
+ * lib.c (partition_by_func): New static function.
+ (partition_by): New function.
+
+ * lib.h (partition_by): Declared.
+
+ * txr.1: Documented partition-by.
+
+2014-07-28 Kaz Kylheku <kaz@kylheku.com>
+
* arith.c (rising_product): Fix wrong m == n case,
which breaks the n_perm_k function for k == 1.
diff --git a/eval.c b/eval.c
index d2539817..e44d132f 100644
--- a/eval.c
+++ b/eval.c
@@ -3647,6 +3647,7 @@ void eval_init(void)
reg_fun(intern(lit("flatten"), user_package), func_n1(flatten));
reg_fun(intern(lit("flatten*"), user_package), func_n1(lazy_flatten));
reg_fun(intern(lit("tuples"), user_package), func_n3o(tuples, 2));
+ reg_fun(intern(lit("partition-by"), user_package), func_n2(partition_by));
reg_fun(memq_s, func_n2(memq));
reg_fun(memql_s, func_n2(memql));
reg_fun(memqual_s, func_n2(memqual));
diff --git a/lib.c b/lib.c
index 563da3a0..863be13b 100644
--- a/lib.c
+++ b/lib.c
@@ -1373,6 +1373,52 @@ val tuples(val n, val seq, val fill)
tuples_func));
}
+static val partition_by_func(val env, val lcons)
+{
+ list_collect_decl (out, ptail);
+ cons_bind (seq_func, func, env);
+ cons_bind (flast, seq_in, seq_func);
+ val seq = seq_in;
+ val last = pop(&seq);
+ val next, fnext = nil;
+
+ ptail = list_collect(ptail, last);
+
+ while (seq) {
+ fnext = funcall1(func, next = car(seq));
+
+ if (!equal(flast, fnext))
+ break;
+
+ ptail = list_collect(ptail, next);
+
+ seq = cdr(seq);
+ last = next;
+ flast = fnext;
+ }
+
+ rplaca(seq_func, fnext);
+ rplacd(seq_func, seq);
+
+ if (seq)
+ rplacd(lcons, make_lazy_cons(lcons_fun(lcons)));
+
+ rplaca(lcons, make_like(out, seq_in));
+ return nil;
+}
+
+val partition_by(val func, val seq)
+{
+ seq = nullify(seq);
+
+ if (!seq)
+ return nil;
+
+ return make_lazy_cons(func_f1(cons(cons(funcall1(func, car(seq)), seq),
+ func),
+ partition_by_func));
+}
+
cnum c_num(val num);
val eql(val left, val right)
diff --git a/lib.h b/lib.h
index f9bcb4e3..157a7994 100644
--- a/lib.h
+++ b/lib.h
@@ -443,6 +443,7 @@ val ldiff(val list1, val list2);
val flatten(val list);
val lazy_flatten(val list);
val tuples(val n, val seq, val fill);
+val partition_by(val func, val seq);
val memq(val obj, val list);
val memql(val obj, val list);
val memqual(val obj, val list);
diff --git a/txr.1 b/txr.1
index 230d17c3..560f359f 100644
--- a/txr.1
+++ b/txr.1
@@ -10770,6 +10770,45 @@ Examples:
(tuples 3 "abcd" #\z) -> ("abc" "dzz")
(tuples 3 (list 1 2) #\z) -> ((1 2 #\z))
+.SS Function partition-by
+
+.TP
+Syntax:
+
+ (partition-by <function> <sequence>)
+
+.TP
+Description:
+
+If <sequence> is empty, then partition-by returns an empty list,
+and <function> is never called.
+
+Otherwise, partition-by returns a lazy list of partitions of the sequence
+<sequence>. Partitions are consecutive, non-empty sub-strings of <sequence>,
+of the same kind as <sequence>.
+
+The partitioning begins with the first element of <sequence> being is placed
+into a partition.
+
+The subsequent partitioning is done according to <function>, which is applied
+to each element of <sequence>. Whenever, for the next element, the function
+returns the same value as it returned for the previous element, the
+element is placed into the same partition. Otherwise, the next element
+is placed into, and begins, a new partition.
+
+The return values of the calls to <function> are compared using the equal
+function.
+
+Note:
+
+.TP
+Examples:
+
+ [partition-by identity '(1 2 3 3 4 4 4 5)] -> ((1) (2) (3 3) (4 4 4) (5))
+
+ (partition-by (op = 3) #(1 2 3 4 5 6 7)) -> (#(1 2) #(3) #(4 5 6 7))
+
+
.SS Function make-like
.TP