Task

Select certain elements from an Array into a new Array in a generic way.



To demonstrate, select all even numbers from an Array.

As an option, give a second solution which filters destructively,
by modifying the original Array rather than creating a new Array.




get "libhdr"
 
// Copy every value for which p(x) is true from in to out
// This will also work in place by setting out = in
let filter(p, in, ilen, out, olen) be
$(  !olen := 0
    for i = 0 to ilen-1 do
        if p(in!i) do
        $(  out!!olen := in!i
            !olen := !olen + 1
        $)
$)
 
// Write N elements from vector
let writevec(v, n) be
    for i = 0 to n-1 do writef("%N ", v!i)
 
let start() be
$(  // Predicates 
    let even(n) = (n&1) = 0
    let mul3(n) = n rem 3 = 0
 
    let nums = table 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
    let arr = vec 20
    let len = ?
 
    writes("Numbers: ")
    writevec(nums, 15)
 
    // Filter 'nums' into 'arr'
    filter(even, nums, 15, arr, @len)
    writes("*NEven numbers: ")
    writevec(arr, len)
 
    // Filter 'arr' in place for multiples of 3
    filter(mul3, arr, len, arr, @len)
    writes("*NEven multiples of 3: ")
    writevec(arr, len)
    wrch('*N')
$)