diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2024-07-11 20:48:34 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2024-07-11 20:48:34 -0700 |
commit | b2bb2af765a550efd92adb25687cb76f955574e3 (patch) | |
tree | f1eaa8bf8750b3cba95a5d40f95e808d94fb60ca | |
parent | d9d8beefbf45eaea89d4174e55df37ed89690ec9 (diff) | |
download | txr-b2bb2af765a550efd92adb25687cb76f955574e3.tar.gz txr-b2bb2af765a550efd92adb25687cb76f955574e3.tar.bz2 txr-b2bb2af765a550efd92adb25687cb76f955574e3.zip |
New funtion related to where function.
* eval.c (eval_init): register intrinsics wheref, whereq,
whereql and wherequal.
* lib.c (wheref_fun): New static function.
(wheref, whereq, whereql, wherequal): New functions.
* lib.h (wheref, whereq, whereql, wherequal): Declared.
* tests/012/seq.tl: New tests.
* txr.1: Documented.
-rw-r--r-- | eval.c | 4 | ||||
-rw-r--r-- | lib.c | 40 | ||||
-rw-r--r-- | lib.h | 4 | ||||
-rw-r--r-- | tests/012/seq.tl | 39 | ||||
-rw-r--r-- | txr.1 | 89 |
5 files changed, 176 insertions, 0 deletions
@@ -7829,6 +7829,10 @@ void eval_init(void) reg_fun(intern(lit("contains"), user_package), func_n4o(contains, 2)); reg_fun(intern(lit("search-all"), user_package), func_n4o(search_all, 2)); reg_fun(intern(lit("where"), user_package), func_n2(where)); + reg_fun(intern(lit("wheref"), user_package), func_n1(wheref)); + reg_fun(intern(lit("whereq"), user_package), func_n1(whereq)); + reg_fun(intern(lit("whereql"), user_package), func_n1(whereql)); + reg_fun(intern(lit("wherequal"), user_package), func_n1(wherequal)); reg_fun(intern(lit("select"), user_package), func_n2(sel)); reg_fun(intern(lit("reject"), user_package), func_n2(reject)); reg_fun(intern(lit("relate"), user_package), func_n3o(relate, 2)); @@ -14053,6 +14053,46 @@ val where(val func, val seq) } } +static val wheref_fun(val func, val seq) +{ + val iter = iter_begin(seq); + val index = zero; + + for (;;) { + if (!iter_more(iter)) + return nil; + if (funcall1(func, iter_item(iter))) + break; + iter = iter_step(iter); + index = succ(index); + } + + iter = iter_step(iter); + return make_lazy_cons_car_cdr(func_f1(iter, lazy_where_func), + index, func); +} + +val wheref(val func) +{ + return func_f1(func, wheref_fun); +} + + +val whereq(val obj) +{ + return func_f1(pa_12_1(eq_f, obj), wheref_fun); +} + +val whereql(val obj) +{ + return func_f1(pa_12_1(eql_f, obj), wheref_fun); +} + +val wherequal(val obj) +{ + return func_f1(pa_12_1(equal_f, obj), wheref_fun); +} + val sel(val seq, val where_in) { val self = lit("select"); @@ -1453,6 +1453,10 @@ val contains(val key, val seq, val testfun, val keyfun); val rsearch(val seq, val key, val from, val to); val search_all(val seq, val key, val testfun, val keyfun); val where(val func, val seq); +val wheref(val func); +val whereq(val obj); +val whereql(val obj); +val wherequal(val obj); val sel(val seq, val where); val reject(val seq, val where); val relate(val domain_seq, val range_seq, val dfl_val); diff --git a/tests/012/seq.tl b/tests/012/seq.tl index 5746939b..45cf2b67 100644 --- a/tests/012/seq.tl +++ b/tests/012/seq.tl @@ -1537,3 +1537,42 @@ (mtest (partition "abcdef" '(4 -1)) ("abcd" "e" "f") (partition "abcdef" '(4 5)) ("abcd" "e" "f")) + +(mtest + (where (op eq #\z) "") nil + (where (op eq #\z) "abc") nil + (where (op eq 'z) #()) nil + (where (op eq 'z) #(a b c)) nil + (where (op eq 'z) '()) nil + (where (op eq 'z) '(a b c)) nil + (where (op eq 10) 1..4) nil + (where (op eq 10) 1..1) nil) + +(mtest + (where (op eq #\c) "abcabc") (2 5) + (where (op eq 'c) #(a b c a b c)) (2 5) + (where (op eq 'c) '(a b c a b c)) (2 5) + (where (op eq 3) 0..9) (3)) + +(mtest + [[wheref oddp] '()] nil + [[wheref oddp] '(1 2 3 4 5 6)] (0 2 4)) + +(mtest + [(whereq #\c) "abcabc"] (2 5) + [(whereq 'c) #(a b c a b c)] (2 5) + [(whereq 'c) '(a b c a b c)] (2 5) + [(whereq 3) 0..9] (3)) + +(mtest + [(whereql #\c) "abcabc"] (2 5) + [(whereq 'c) #(a b c a b c)] (2 5) + [(whereql 'c) '(a b c a b c)] (2 5) + [(whereql 3) 0..9] (3)) + +(mtest + [(wherequal #xFFFFFFFFFFFFFFFFFFFF) '(#xFFFFFFFFFFFFFFFFFFFF)] (0) + [(wherequal 'c) #(a b c a b c)] (2 5) + [(wherequal 'c) '(a b c a b c)] (2 5) + [(wherequal 3) '(3 3.0 b c a b c)] (0) + [(wherequal 3) 0..9] (3)) @@ -36777,6 +36777,95 @@ as an argument. If a value is returned, then the zero-based index of that element is added to a list. Finally, the list is returned. +.coNP Function @ wheref +.synb +.mets (wheref << function) +.syne +.desc +The +.code wheref +function is a combinator related to the +.code where +function. + +The +.code wheref +function returns a function that takes one argument. When a sequence is +passed to that function, it returns the index positions where +the sequence elements satisfy the given +.metn function , +which must be capable of taking one argument. + +Certain uses of +.code where +can be expressed more briefly using +.codn wheref , +according to the following equivalence: + +.verb + (where f s) <--> [(wheref f) s] +.brev + +.TP* Example: + +.verb + ;; partition list of integers by odd, using where: + + [partition 0..10 (op where oddp)] + --> ((0) (1 2) (3 4) (5 6) (7 8) (9)) + + ;; using wheref + [partition 0..10 [wheref oddp]] + --> ((0) (1 2) (3 4) (5 6) (7 8) (9)) +.brev + +.coNP Functions @, whereq @ whereql and @ wherequal +.synb +.mets (whereq << object ) +.mets (whereql << object ) +.mets (wherequal << object ) +.syne +.desc +The functions +.codn whereq , +.code whereql +and +.code wherequal +are combinators related to the +.code where +function. + +The +.code whereq +function returns a function that takes one argument. When a sequence is passed +to that function, it returns the index positions where the elements of +the sequence are +.code eq +to +.metn object . + +The +.code whereql +function differs only in that the test is +.code eql +rather than +.codn eq , +and the +.code wherequal +function uses +.code equal +equality. + +.TP* Example: + +.verb + ;; indices where the string has a 'c', using where: + (where (op eq #\c) "abcabc") -> (2 5) + + ;; same, using whereq: + [(whereq #\c) "abcabc"] -> (2 5) +.brev + .coNP Function @ rmismatch .synb .mets (rmismatch < left-seq < right-seq >> [ testfun <> [ keyfun ]]) |