summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--eval.c1
-rw-r--r--lib.c15
-rw-r--r--lib.h1
-rw-r--r--tl.vim14
-rw-r--r--txr.169
-rw-r--r--txr.vim14
7 files changed, 109 insertions, 18 deletions
diff --git a/ChangeLog b/ChangeLog
index e2a651c3..000173c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
2014-12-23 Kaz Kylheku <kaz@kylheku.com>
+ * eval.c (eval_init): Registered intrinsic function unique.
+
+ * lib.c (unique): New function.
+ (uniq): Becomes wrapper around unique.
+
+ * lib.h (unique): Declared.
+
+ * txr.1: Documented unique, and equivalence between uniq and unique.
+
+ * tl.vim, txr.vim: Regenerated.
+
+2014-12-23 Kaz Kylheku <kaz@kylheku.com>
+
* lib.c (func_n1ov, func_n2ov, func_n3ov): New functions.
* lib.h (func_n1ov, func_n2ov, func_n3ov): Declared.
diff --git a/eval.c b/eval.c
index fd78afb5..1c020c83 100644
--- a/eval.c
+++ b/eval.c
@@ -3776,6 +3776,7 @@ void eval_init(void)
reg_fun(intern(lit("hash-isec"), user_package), func_n3o(hash_isec, 2));
reg_fun(intern(lit("group-by"), user_package), func_n2v(group_by));
reg_fun(intern(lit("sort-group"), user_package), func_n3o(sort_group, 1));
+ reg_fun(intern(lit("unique"), user_package), func_n2ov(unique, 1));
reg_fun(intern(lit("uniq"), user_package), func_n1(uniq));
reg_fun(intern(lit("hash-update"), user_package), func_n2(hash_update));
reg_fun(intern(lit("hash-update-1"), user_package),
diff --git a/lib.c b/lib.c
index 4261ec08..11cf2f83 100644
--- a/lib.c
+++ b/lib.c
@@ -5787,9 +5787,11 @@ val sort_group(val seq, val keyfun, val lessfun)
return partition_by(kf, sorted);
}
-val uniq(val seq)
+val unique(val seq, val keyfun, val hashargs)
{
- val hash = make_hash(nil, nil, t);
+ val hash = hashv(default_bool_arg(hashargs));
+ val kf = default_arg(keyfun, identity_f);
+
list_collect_decl (out, ptail);
if (vectorp(seq) || stringp(seq)) {
@@ -5799,7 +5801,7 @@ val uniq(val seq)
val new_p;
val v = ref(seq, num_fast(i));
- (void) gethash_c(hash, v, mkcloc(new_p));
+ (void) gethash_c(hash, funcall1(kf, v), mkcloc(new_p));
if (new_p)
ptail = list_collect(ptail, v);
@@ -5809,7 +5811,7 @@ val uniq(val seq)
val new_p;
val v = car(seq);
- (void) gethash_c(hash, v, mkcloc(new_p));
+ (void) gethash_c(hash, funcall1(kf, v), mkcloc(new_p));
if (new_p)
ptail = list_collect(ptail, v);
@@ -5819,6 +5821,11 @@ val uniq(val seq)
return make_like(out, seq);
}
+val uniq(val seq)
+{
+ return unique(seq, identity_f, cons(equal_based_k, nil));
+}
+
val find(val item, val list, val testfun, val keyfun)
{
testfun = default_arg(testfun, equal_f);
diff --git a/lib.h b/lib.h
index 0d20cd7a..a95c2e3f 100644
--- a/lib.h
+++ b/lib.h
@@ -805,6 +805,7 @@ val merge(val list1, val list2, val lessfun, val keyfun);
val sort(val seq, val lessfun, val keyfun);
val multi_sort(val lists, val funcs, val key_funcs);
val sort_group(val seq, val keyfun, val lessfun);
+val unique(val seq, val keyfun, val hashargs);
val uniq(val seq);
val find(val list, val key, val testfun, val keyfun);
val find_if(val pred, val list, val key);
diff --git a/tl.vim b/tl.vim
index d514afe7..eec18127 100644
--- a/tl.vim
+++ b/tl.vim
@@ -177,13 +177,13 @@ syn keyword txl_keyword contained tree-find trie-add trie-compress trie-lookup-b
syn keyword txl_keyword contained trie-lookup-feed-char trie-value-at trim-str true
syn keyword txl_keyword contained trunc tuples txr-case txr-if
syn keyword txl_keyword contained txr-when typeof unget-byte unget-char
-syn keyword txl_keyword contained uniq unless unquote until
-syn keyword txl_keyword contained upcase-str update url-decode url-encode
-syn keyword txl_keyword contained usleep uw-protect vec vec-push
-syn keyword txl_keyword contained vec-set-length vecref vector vector-list
-syn keyword txl_keyword contained vectorp when where while
-syn keyword txl_keyword contained with-saved-vars wrap wrap* zerop
-syn keyword txl_keyword contained zip
+syn keyword txl_keyword contained uniq unique unless unquote
+syn keyword txl_keyword contained until upcase-str update url-decode
+syn keyword txl_keyword contained url-encode usleep uw-protect vec
+syn keyword txl_keyword contained vec-push vec-set-length vecref vector
+syn keyword txl_keyword contained vector-list vectorp when where
+syn keyword txl_keyword contained while with-saved-vars wrap wrap*
+syn keyword txl_keyword contained zerop zip
syn match txr_metanum "@[0-9]\+"
syn match txr_nested_error "[^\t `]\+" contained
diff --git a/txr.1 b/txr.1
index 8151de77..70db9229 100644
--- a/txr.1
+++ b/txr.1
@@ -17841,6 +17841,75 @@ function. The first occurrence of each element is retained,
and the subsequent duplicates of that element, of any, are suppressed,
such that the order of the elements is otherwise preserved.
+The following equivalence holds between
+.code uniq
+and
+.codn unique :
+
+.cblk
+ (uniq s) <--> [unique s : :equal-based]
+.cble
+
+That is,
+.code uniq
+is like
+.code unique
+with the default
+.meta keyfun
+argument (the
+.code identity
+function) and an
+.codn equal -based
+hash table.
+
+.coNP Function @ unique
+.synb
+.mets (uniq < sequence >> [ keyfun <> { hash-arg }* ])
+.syne
+.desc
+The
+.code unique
+function is a generalization of
+.codn uniq .
+It returns a sequence of the same kind as
+.metn sequence ,
+but with duplicates removed.
+
+If neither
+.meta keyfun
+nor
+.metn hash-arg -s
+are specified, then elements of sequence are considered equal under the
+.code eql
+function. The first occurrence of each element is retained,
+and the subsequent duplicates of that element, of any, are suppressed,
+such that the order of the elements is otherwise preserved.
+
+If
+.meta keyfun
+is specified, then that function is applied to each element,
+and the resulting values are compared for equality.
+In other words, the behavior is as if
+.meta keyfun
+were the
+.code identity
+function.
+
+If one or more
+.meta hash-arg -s
+are present, these specify the arguments for the construction of
+the internal hash table used by
+.codn unique .
+The arguments are like those of the
+.code hash
+function. In particular, the argument
+.code :equal-based
+causes
+.code unique
+to use
+.code equal
+equality.
+
.coNP Function @ tuples
.synb
.mets (tuples < length < sequence <> [ fill-value ])
diff --git a/txr.vim b/txr.vim
index 1ec2846d..49d90a41 100644
--- a/txr.vim
+++ b/txr.vim
@@ -177,13 +177,13 @@ syn keyword txl_keyword contained tree-find trie-add trie-compress trie-lookup-b
syn keyword txl_keyword contained trie-lookup-feed-char trie-value-at trim-str true
syn keyword txl_keyword contained trunc tuples txr-case txr-if
syn keyword txl_keyword contained txr-when typeof unget-byte unget-char
-syn keyword txl_keyword contained uniq unless unquote until
-syn keyword txl_keyword contained upcase-str update url-decode url-encode
-syn keyword txl_keyword contained usleep uw-protect vec vec-push
-syn keyword txl_keyword contained vec-set-length vecref vector vector-list
-syn keyword txl_keyword contained vectorp when where while
-syn keyword txl_keyword contained with-saved-vars wrap wrap* zerop
-syn keyword txl_keyword contained zip
+syn keyword txl_keyword contained uniq unique unless unquote
+syn keyword txl_keyword contained until upcase-str update url-decode
+syn keyword txl_keyword contained url-encode usleep uw-protect vec
+syn keyword txl_keyword contained vec-push vec-set-length vecref vector
+syn keyword txl_keyword contained vector-list vectorp when where
+syn keyword txl_keyword contained while with-saved-vars wrap wrap*
+syn keyword txl_keyword contained zerop zip
syn keyword txr_keyword contained accept all and assert
syn keyword txr_keyword contained bind block cases cat