diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-05-13 18:43:02 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-05-13 18:43:02 -0700 |
commit | cdf79f2907cab5aa410ad47934f0374254386220 (patch) | |
tree | dc806ed600d1defd3eaf8ed1965a8987d8dfaaa9 /lib.c | |
parent | 0786f1422cf0a949fb0e0daf98852123ced19c9a (diff) | |
download | txr-cdf79f2907cab5aa410ad47934f0374254386220.tar.gz txr-cdf79f2907cab5aa410ad47934f0374254386220.tar.bz2 txr-cdf79f2907cab5aa410ad47934f0374254386220.zip |
lib: sort becomes non-destructive; nsort introduced.
I'm fixing a historic mistake copied from ANSI Lisp,
which trips up language newcomers and sometimes even
experienced users.
The function innocently named sort will now return newly
allocated structure. The function previously called sort will
be available as nsort (non-consing/allocating sort).
The shuffle function also becomes pure, and is accompanied by
nshuffle.
* eval (me_op): Continue to use destructive sort in this
legacy code that is only triggered in very old compat mode.
(eval_init): Registered nsort and nshuffle.
* lib.c (nsort, nshuffle): New functions introduced, closely
based on sort and shuffle.
(sort, shuffle): Rewritten to avoid destructive behavior: work
by copying the input and calling destructive counterparts.
(sort_group): Continue to use destructive sort, which is safe;
the structure is locally allocated. The sort_group function
has pure semantics.
(grade): Likewise.
* lib.h (nsort, nshuffle): Declared.
* share/txr/stdlib/getopts.tl (opthelp): Replace an instance
of the (sort (copy-list ...)) pattern with just (sort ...).
* tags.tl (toplevel): Continue to use destructive sort to sort
tags before writing the tag file; the lifetime of the tags
list ends when the file is written.
* tests/010/seq.txr: Switch some sort calls to nsort to keep
test case working.
* txr.1: Documented.
Diffstat (limited to 'lib.c')
-rw-r--r-- | lib.c | 44 |
1 files changed, 37 insertions, 7 deletions
@@ -8867,9 +8867,9 @@ static void sort_vec(val vec, val lessfun, val keyfun) quicksort(vec, lessfun, keyfun, 0, len); } -val sort(val seq, val lessfun, val keyfun) +val nsort(val seq, val lessfun, val keyfun) { - val self = lit("sort"); + val self = lit("nsort"); seq_info_t si = seq_info(seq); keyfun = default_arg(keyfun, identity_f); @@ -8891,7 +8891,31 @@ val sort(val seq, val lessfun, val keyfun) abort(); } -val shuffle(val seq) +val sort(val seq, val lessfun, val keyfun) +{ + val self = lit("sort"); + seq_info_t si = seq_info(seq); + + keyfun = default_arg(keyfun, identity_f); + lessfun = default_arg(lessfun, less_f); + + switch (si.kind) { + case SEQ_NIL: + return nil; + case SEQ_VECLIKE: + case SEQ_HASHLIKE: + sort_vec(copy(seq), lessfun, keyfun); + return seq; + case SEQ_LISTLIKE: + return sort_list(copy_list(seq), lessfun, keyfun); + case SEQ_NOTSEQ: + unsup_obj(self, seq); + } + + abort(); +} + +val nshuffle(val seq) { seq_info_t si = seq_info(seq); @@ -8928,12 +8952,19 @@ val shuffle(val seq) return seq; } case SEQ_NOTSEQ: - type_mismatch(lit("shuffle: ~s is not a sequence"), seq, nao); + type_mismatch(lit("nshuffle: ~s is not a sequence"), seq, nao); } abort(); } +val shuffle(val seq) +{ + if (seqp(seq)) + return nshuffle(copy(seq)); + type_mismatch(lit("nshuffle: ~s is not a sequence"), seq, nao); +} + static val multi_sort_less(val funcs_cons, val llist, val rlist) { cons_bind (funcs, key_funcs, funcs_cons); @@ -8976,8 +9007,7 @@ val sort_group(val seq, val keyfun, val lessfun) { val kf = default_arg(keyfun, identity_f); val lf = default_arg(lessfun, less_f); - val seq_copy = copy(seq); - val sorted = sort(seq_copy, lf, kf); + val sorted = sort(seq, lf, kf); return partition_by(kf, sorted); } @@ -9054,7 +9084,7 @@ val grade(val seq, val lessfun, val keyfun_in) { list_collect_decl (out, ptail); - sort(v, lessfun, keyfun); + nsort(v, lessfun, keyfun); for (i = 0; i < len; i++) ptail = list_collect(ptail, cdr(v->v.vec[i])); |