diff options
-rw-r--r-- | eval.c | 6 | ||||
-rw-r--r-- | lib.c | 42 | ||||
-rw-r--r-- | lib.h | 6 | ||||
-rw-r--r-- | tests/012/seq.tl | 4 | ||||
-rw-r--r-- | txr.1 | 84 |
5 files changed, 90 insertions, 52 deletions
@@ -7428,12 +7428,12 @@ void eval_init(void) reg_fun(intern(lit("remq"), user_package), func_n3o(remq, 2)); reg_fun(intern(lit("remql"), user_package), func_n3o(remql, 2)); reg_fun(intern(lit("remqual"), user_package), func_n3o(remqual, 2)); - reg_fun(intern(lit("remove-if"), user_package), func_n3o(remove_if, 2)); + reg_fun(intern(lit("remove-if"), user_package), func_n4o(remove_if, 2)); reg_fun(intern(lit("keepq"), user_package), func_n3o(keepq, 2)); reg_fun(intern(lit("keepql"), user_package), func_n3o(keepql, 2)); reg_fun(intern(lit("keepqual"), user_package), func_n3o(keepqual, 2)); - reg_fun(intern(lit("keep-if"), user_package), func_n3o(keep_if, 2)); - reg_fun(intern(lit("keep-keys-if"), user_package), func_n3o(keep_keys_if, 2)); + reg_fun(intern(lit("keep-if"), user_package), func_n4o(keep_if, 2)); + reg_fun(intern(lit("keep-keys-if"), user_package), func_n4o(keep_keys_if, 2)); reg_fun(intern(lit("separate"), user_package), func_n3o(separate, 2)); reg_fun(intern(lit("separate-keys"), user_package), func_n3o(separate_keys, 2)); reg_fun(intern(lit("remq*"), user_package), func_n2(remq_lazy)); @@ -3418,9 +3418,11 @@ static val rem_impl(val (*eqfun)(val, val), val self, return seq_finish(&bu); } -static val rem_if_impl(val pred, val seq, val keyfun_in, val self) +static val rem_if_impl(val pred, val seq, val keyfun_in, val mapfun_in, + val self) { val keyfun = default_null_arg(keyfun_in); + val mapfun = default_null_arg(mapfun_in); seq_iter_t it; seq_build_t bu; val elem; @@ -3430,8 +3432,15 @@ static val rem_if_impl(val pred, val seq, val keyfun_in, val self) while (seq_get(&it, &elem)) { val key = keyfun ? funcall1(keyfun, elem) : elem; - if (!funcall1(pred, key)) + if (!funcall1(pred, key)) { + if (mapfun) { + if (mapfun == keyfun) + elem = key; + else + elem = funcall1(mapfun, elem); + } seq_add(&bu, elem); + } } return seq_finish(&bu); @@ -3467,35 +3476,20 @@ val keepqual(val obj, val seq, val keyfun) return rem_impl(nequal, lit("keepqual"), obj, seq, keyfun); } -val remove_if(val pred, val seq, val keyfun) +val remove_if(val pred, val seq, val keyfun, val mapfun) { - return rem_if_impl(pred, seq, keyfun, lit("remove-if")); + return rem_if_impl(pred, seq, keyfun, mapfun, lit("remove-if")); } -val keep_if(val pred, val seq, val keyfun) +val keep_if(val pred, val seq, val keyfun, val mapfun) { - return rem_if_impl(notf(pred), seq, keyfun, lit("keep-if")); + return rem_if_impl(notf(pred), seq, keyfun, mapfun, lit("keep-if")); } -val keep_keys_if(val pred, val seq, val keyfun_in) +val keep_keys_if(val pred, val seq, val keyfun_in, val mapfun_in) { - val self = lit("keep-keys-if"); - val keyfun = default_null_arg(keyfun_in); - seq_iter_t it; - seq_build_t bu; - val elem; - - seq_iter_init(self, &it, seq); - seq_build_init(self, &bu, seq); - - while (seq_get(&it, &elem)) { - val key = keyfun ? funcall1(keyfun, elem) : elem; - - if (funcall1(pred, key)) - seq_add(&bu, key); - } - - return seq_finish(&bu); + val mapfun = default_arg(mapfun_in, keyfun_in); + return rem_if_impl(notf(pred), seq, keyfun_in, mapfun, lit("keep-keys-if")); } val separate(val pred, val seq, val keyfun_in) @@ -889,12 +889,12 @@ val rmember_if(val pred, val list, val key); val remq(val obj, val seq, val keyfun); val remql(val obj, val seq, val keyfun); val remqual(val obj, val seq, val keyfun); -val remove_if(val pred, val seq, val keyfun); +val remove_if(val pred, val seq, val keyfun_in, val mapfun_in); val keepq(val obj, val seq, val keyfun); val keepql(val obj, val seq, val keyfun); val keepqual(val obj, val seq, val keyfun); -val keep_if(val pred, val seq, val keyfun); -val keep_keys_if(val pred, val seq_in, val keyfun_in); +val keep_if(val pred, val seq, val keyfun_in, val mapfun_in); +val keep_keys_if(val pred, val seq_in, val keyfun_in, val mapfun_in); val separate(val pred, val seq, val keyfun); val separate_keys(val pred, val seq_in, val keyfun_in); val remq_lazy(val obj, val list); diff --git a/tests/012/seq.tl b/tests/012/seq.tl index 148f1899..5d63fbf5 100644 --- a/tests/012/seq.tl +++ b/tests/012/seq.tl @@ -1617,3 +1617,7 @@ (seq-like "" #\a #\b 3) (#\a #\b 3) (seq-like #() 1 2 3) #(1 2 3) (seq-like #b'' 1 2 3) #b'010203') + +(mtest + [keep-if (lop find "aiueo") "vertebrate" : chr-toupper] "EEAE" + [remove-if (lop find "aiueo") "vertebrate" : chr-toupper] "VRTBRT") @@ -36224,11 +36224,11 @@ is compared to .coNP Functions @, remove-if @, keep-if @, separate @ remove-if* and @ keep-if* .synb -.mets (remove-if < predicate-function < sequence <> [ key-function ]) -.mets (keep-if < predicate-function < sequence <> [ key-function ]) -.mets (separate < predicate-function < sequence <> [ key-function ]) -.mets (remove-if* < predicate-function < sequence <> [ key-function ]) -.mets (keep-if* < predicate-function < sequence <> [ key-function ]) +.mets (remove-if < predfun < sequence >> [ keyfun <> [ mapfun ]]) +.mets (keep-if < predfun < sequence >> [ keyfun <> [ mapfun ]]) +.mets (separate < predfun < sequence >> [ keyfun <> [ mapfun ]]) +.mets (remove-if* < predfun < sequence >> [ keyfun <> [ mapfun ]]) +.mets (keep-if* < predfun < sequence >> [ keyfun <> [ mapfun ]]) .syne .desc The @@ -36236,24 +36236,42 @@ The function produces a sequence whose contents are those of .meta sequence but with those elements removed which satisfy -.metn predicate-function . +.metn predfun . Those elements which are not removed appear in the same order. The result sequence may share substructure with the input sequence, and may even be the same sequence object if no items are removed. The optional -.meta key-function +.meta keyfun specifies how each element from the .meta sequence is transformed to an argument to -.metn predicate-function . +.metn predfun . If this argument is omitted then the predicate function is applied to the elements directly, a behavior which is identical to -.meta key-function +.meta keyfun being .codn "(fun identity)" . +The optional +.meta mapfun +argument specifies a function which is applied to the elements of +.meta sequence +that are identified for retention, mapping them to the actual values that are +accumulated into the output. In the absence of this argument, the behavior is +to accumulate the elements themselves. + +If +.meta keyfun +and +.meta mapfun +are the same object, it is unspecified whether +.meta mapfun +is called, or whether the result of +.meta keyfun +is used. + The .code keep-if function is exactly like @@ -36287,9 +36305,9 @@ respectively, on .meta sequence (with the -.meta predicate-function +.meta predfun and -.meta key-function +.meta keyfun arguments passed through). One of the two elements may share substructure with the input sequence, and may even be the same sequence object if all items are either kept or @@ -36336,8 +36354,8 @@ but produce lazy lists. .coNP Functions @ keep-keys-if and @ separate-keys .synb -.mets (keep-keys-if < predicate-fun < sequence <> [ key-fun ]) -.mets (separate-keys < predicate-fun < sequence <> [ key-fun ]) +.mets (keep-keys-if < predfun < sequence >> [ keyfun <> [ mapfun ]]) +.mets (separate-keys < predfun < sequence <> [[ keyfun ]) .syne .desc The functions @@ -36353,21 +36371,43 @@ rather than accumulating the elements of the input .codn sequence , they accumulate the transformed values of those elements, as projected through the -.metn key-fun . +.metn keyfun . -Thus when -.meta key-fun +If all arguments of +.code keep-keys-if +are specified, then it behaves exactly like +.code keep-if +for those same arguments. The same is true if both the +.meta keyfun +and +.meta mapfun +arguments are omitted, or if +.meta keyfun +is specified as +.codn identity . + +The difference between +.code keep-keys-if +and +.code keep-if +is the defaulting of the +.meta mapfun +argument. If +.meta mapfun +is omitted, then it defaults to being the same function as the +.meta keyfun +argument. + +In the case of +.codn separate-keys-if , +when +.meta keyfun is omitted, thus defaulting to .codn identity , or else explicitly specified as .code identity -or equivalent function, the behavior of these functions is the -almost the same as that of -.code keep-if -and +or equivalent function, the behavior is same as that of .codn separate . -However, there may be a difference in whether the output shares structure with -.metn sequence . .TP* Example: |