From e68f3828d79d16d2afc929c83d499e8e2e0dd38a Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 23 Dec 2014 09:13:13 -0800 Subject: * 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. --- ChangeLog | 13 ++++++++++++ eval.c | 1 + lib.c | 15 ++++++++++---- lib.h | 1 + tl.vim | 14 ++++++------- txr.1 | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ txr.vim | 14 ++++++------- 7 files changed, 109 insertions(+), 18 deletions(-) diff --git a/ChangeLog b/ChangeLog index e2a651c3..000173c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2014-12-23 Kaz Kylheku + + * 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 * lib.c (func_n1ov, func_n2ov, func_n3ov): New functions. 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 -- cgit v1.2.3