summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-02-10 05:12:14 -0800
committerKaz Kylheku <kaz@kylheku.com>2014-02-10 05:12:14 -0800
commit2fccb10283aae350ced4db70fcddcc95e59e503a (patch)
treea062189edc6051bcec7145857703dca6e9dfc9f6
parent13fa06edcfa454ec0f0bb5ae6fb51c968f5dcdfd (diff)
downloadtxr-2fccb10283aae350ced4db70fcddcc95e59e503a.tar.gz
txr-2fccb10283aae350ced4db70fcddcc95e59e503a.tar.bz2
txr-2fccb10283aae350ced4db70fcddcc95e59e503a.zip
Relaxed behavior: don't throw errors for impossible permutations,
but return an empty list. * eval.c (perm_init_common): Do not throw error; return a nil state if permutation length exceeds sequence length. (perm_vec, perm_list, perm_str): Check for null return from perm_init_common and return empty list. (k_conses): Do not throw error; return empty list. (comb_list_gen_fun): Check for nil value out of k_conses. (comb): For vectors and strings, check length against k and return nil if necessary. For lists, comb_list_gen_fun handles it. * txr.1: Section order rearranged, and updated.
-rw-r--r--ChangeLog16
-rw-r--r--eval.c46
-rw-r--r--txr.166
3 files changed, 78 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index 05de02c8..cee7df5a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
2014-02-10 Kaz Kylheku <kaz@kylheku.com>
+ Relaxed behavior: don't throw errors for impossible permutations,
+ but return an empty list.
+
+ * eval.c (perm_init_common): Do not throw error; return a nil
+ state if permutation length exceeds sequence length.
+ (perm_vec, perm_list, perm_str): Check for null return from
+ perm_init_common and return empty list.
+ (k_conses): Do not throw error; return empty list.
+ (comb_list_gen_fun): Check for nil value out of k_conses.
+ (comb): For vectors and strings, check length against k and
+ return nil if necessary. For lists, comb_list_gen_fun handles it.
+
+ * txr.1: Section order rearranged, and updated.
+
+2014-02-10 Kaz Kylheku <kaz@kylheku.com>
+
* eval.c (rcomb_while_fun, rcomb_gen_fun_common,
rcomb_list_gen_fun, rcomb_list, rcomb_vec_gen_fun, rcomb_vec,
rcomb_str_gen_fun, rcomb_str, rcomb): New static functions.
diff --git a/eval.c b/eval.c
index a0b0255b..c2a82994 100644
--- a/eval.c
+++ b/eval.c
@@ -2287,20 +2287,18 @@ static val perm_init_common(val p, val k_null)
uses_or2;
val n = length(p);
val k = or2(k_null, n);
- val state = vector(three, nil);
- val c = vector(k, zero);
- if (gt(k, n))
- uw_throwf(numeric_error_s,
- lit("perm: permutation length ~s exceeds sequence length ~s"),
- k, n, nao);
-
- *vecref_l(state, zero) = p;
- *vecref_l(state, one) = k;
- *vecref_l(state, two) = c;
- *vecref_l(c, negone) = negone;
-
- return state;
+ if (gt(k, n)) {
+ return nil;
+ } else {
+ val state = vector(three, nil);
+ val c = vector(k, zero);
+ *vecref_l(state, zero) = p;
+ *vecref_l(state, one) = k;
+ *vecref_l(state, two) = c;
+ *vecref_l(c, negone) = negone;
+ return state;
+ }
}
static void perm_vec_gen_fill(val out, cnum i, val v)
@@ -2324,6 +2322,8 @@ static val perm_vec(val p, val k)
return cons(vector(zero, nil), nil);
} else {
val state = perm_init_common(p, k);
+ if (!state)
+ return nil;
return generate(func_f0(state, perm_while_fun),
func_f0(state, perm_vec_gen_fun));
}
@@ -2353,6 +2353,8 @@ static val perm_list(val p, val k)
return cons(nil, nil);
} else {
val state = perm_init_common(vector_list(p), k);
+ if (!state)
+ return nil;
return generate(func_f0(state, perm_while_fun),
func_f0(state, perm_list_gen_fun));
}
@@ -2380,6 +2382,8 @@ static val perm_str(val p, val k)
return cons(string(L""), nil);
} else {
val state = perm_init_common(vector_list(list_str(p)), k);
+ if (!state)
+ return nil;
return generate(func_f0(state, perm_while_fun),
func_f0(state, perm_str_gen_fun));
}
@@ -2422,12 +2426,7 @@ static val k_conses(val list, val k)
for (; consp(iter) && gt(i, zero); iter = cdr(iter), i = minus(i, one))
ptail = list_collect(ptail, iter);
- if (i != zero)
- uw_throwf(numeric_error_s,
- lit("comb: permutation length ~s exceeds sequence length ~s"),
- k, length(list), nao);
-
- return out;
+ return (i != zero) ? nil : out;
}
static val comb_while_fun(val state)
@@ -2469,8 +2468,9 @@ static val comb_list_gen_fun(val state)
static val comb_list(val list, val k)
{
val state = nreverse(k_conses(list, k));
- return generate(func_f0(state, comb_while_fun),
- func_f0(state, comb_list_gen_fun));
+ return state ? generate(func_f0(state, comb_while_fun),
+ func_f0(state, comb_list_gen_fun))
+ : nil;
}
static val comb_vec_gen_fun(val state)
@@ -2534,12 +2534,16 @@ static val comb(val seq, val k)
case VEC:
if (k == zero)
return cons(vector(zero, nil), nil);
+ if (gt(k, length(seq)))
+ return nil;
return comb_vec(seq, k);
case STR:
case LSTR:
case LIT:
if (k == zero)
return cons(string(L""), nil);
+ if (gt(k, length(seq)))
+ return nil;
return comb_str(seq, k);
default:
type_mismatch(lit("comb: ~s is not a sequence"), seq, nao);
diff --git a/txr.1 b/txr.1
index 195dd441..f7b65d7d 100644
--- a/txr.1
+++ b/txr.1
@@ -7869,6 +7869,37 @@ cached inside <promise> and returned, becoming the return value of the
force function call. If the force function is invoked additional times on
the same promise, the cached value is retrieved.
+.SS Function perm
+
+.TP
+Syntax:
+
+ (perm <seq> [<len>])
+
+.TP
+Description:
+
+The rperm function returns a lazy list which consists of all
+length <len> permutations of formed by items taken from <seq>.
+The permutations do not use any element of <seq> more than once.
+
+Argument <len>, if present, must be a positive integer, and <seq> must be a
+sequence.
+
+If <len> is not present, then its value defaults to the length of <seq>:
+the list of the full permutations of the entire sequence is returned.
+
+The permutations in the returned list are sequences of the same kind as <seq>.
+
+If <len> is zero, then a list containing one permutation is returned, and that
+permutations is of zero length.
+
+If <len> exceeds the length of <seq>, then an empty list is returned,
+since it is impossible to make a single non-repeating permutation that
+requires more items than are available.
+
+The permutations are lexicographically ordered.
+
.SS Function rperm
.TP
@@ -7909,34 +7940,8 @@ Examples:
(rperm '(0 1 2) 2) -> ((0 0) (0 1) (0 2) (1 0) (1 1) (1 2) (2 0) (2 1) (2 2))
-.SS Function perm
-
-.TP
-Syntax:
-
- (perm <seq> [<len>])
-
-.TP
-Description:
-
-The rperm function returns a lazy list which consists of all
-length <len> permutations of formed by items taken from <seq>.
-The permutations do not use any element of <seq> more than once.
-Argument <len>, if present, must be a positive integer no greater
-than the length of <seq>, and <seq> must be a sequence.
-
-If <len> is not present, then its value defaults to the length of <seq>:
-the list of the full permutations of the entire sequence is returned.
-
-The permutations in the returned list are sequences of the same kind as <seq>.
-
-If <len> is zero, then a list containing one permutation is returned, and that
-permutations is of zero length.
-
-The permutations are lexicographically ordered.
-
-.SS Functions comb and rcomb
+.SS Function comb
.TP
Syntax:
@@ -7952,14 +7957,17 @@ length <len> non-repeating combinations formed by taking items taken from
element of <seq> more than once. If <seq> contains no duplicates, then
the combinations contain no duplicates.
-Argument <len> must be a nonnegative integer no greater than the length of
-<seq>, and <seq> must be a sequence.
+Argument <len> must be a nonnegative integer, and <seq> must be a sequence.
The combinations in the returned list are sequences of the same kind as <seq>.
If <len> is zero, then a list containing one combination is returned, and that
permutations is of zero length.
+If <len> exceeds the length of <seq>, then an empty list is returned,
+since it is impossible to make a single non-repeating combination that
+requires more items than are available.
+
The combinations are lexicographically ordered.
.SS Function rcomb