diff --git a/builtin/core.wren b/builtin/core.wren index fe501afe..156f507f 100644 --- a/builtin/core.wren +++ b/builtin/core.wren @@ -16,6 +16,16 @@ class Sequence { return result } + count(f) { + var result = 0 + for (element in this) { + if (f.call(element)) { + result = result + 1 + } + } + return result + } + map(f) { var result = new List for (element in this) { diff --git a/doc/site/core/list.markdown b/doc/site/core/list.markdown index 4e08007e..498f754c 100644 --- a/doc/site/core/list.markdown +++ b/doc/site/core/list.markdown @@ -11,11 +11,11 @@ Appends `item` to the end of the list. ### **clear**() -Removes all items from the list. +Removes all elements from the list. ### **count** -The number of items in the list. +The number of elements in the list. ### **insert**(index, item) diff --git a/doc/site/core/sequence.markdown b/doc/site/core/sequence.markdown index a7bac5e9..75ab4f14 100644 --- a/doc/site/core/sequence.markdown +++ b/doc/site/core/sequence.markdown @@ -34,6 +34,24 @@ Otherwise, returns `false`. Returns whether the sequence contains any element equal to the given element. +### **count** + +The number of elements in the sequence. + +Unless a more efficient override is available, this will iterate over the +sequence in order to determine how many elements it contains. + +### **count**(predicate) + +Returns the number of elements in the sequence that pass the `predicate`. + +Iterates over the sequence, passing each element to the function `predicate` +and counting the number of times the returned value evaluates to `true`. + + :::dart + [1, 2, 3].count {|n| n > 2} // 1. + [1, 2, 3].count {|n| n < 4} // 3. + ### **join**(sep) Returns a string representation of the list. The string representations of the diff --git a/src/vm/wren_core.c b/src/vm/wren_core.c index 5de7fd82..f34b2cbb 100644 --- a/src/vm/wren_core.c +++ b/src/vm/wren_core.c @@ -62,6 +62,16 @@ static const char* libSource = " return result\n" " }\n" "\n" +" count(f) {\n" +" var result = 0\n" +" for (element in this) {\n" +" if (f.call(element)) {\n" +" result = result + 1\n" +" }\n" +" }\n" +" return result\n" +" }\n" +"\n" " map(f) {\n" " var result = new List\n" " for (element in this) {\n" diff --git a/test/core/list/count_predicate.wren b/test/core/list/count_predicate.wren new file mode 100644 index 00000000..349cf976 --- /dev/null +++ b/test/core/list/count_predicate.wren @@ -0,0 +1,6 @@ +var a = [1, 2, 3] + +IO.print(a.count {|x| x > 3 }) // expect: 0 +IO.print(a.count {|x| x > 1 }) // expect: 2 + +IO.print([].count {|x| true }) // expect: 0 diff --git a/test/core/list/count_predicate_non_bool_returning_fn.wren b/test/core/list/count_predicate_non_bool_returning_fn.wren new file mode 100644 index 00000000..35feb0b6 --- /dev/null +++ b/test/core/list/count_predicate_non_bool_returning_fn.wren @@ -0,0 +1,3 @@ +var a = [1, 2, 3] + +IO.print(a.count {|x| "truthy" }) // expect: 3 diff --git a/test/core/list/count_predicate_non_function_arg.wren b/test/core/list/count_predicate_non_function_arg.wren new file mode 100644 index 00000000..884fa557 --- /dev/null +++ b/test/core/list/count_predicate_non_function_arg.wren @@ -0,0 +1,3 @@ +var a = [1, 2, 3] + +a.count("string") // expect runtime error: String does not implement 'call(_)'.