Reduce is a function or method that is used to take the values in an array or a list and apply a function to successive members of the list to produce (or reduce them to), a single value.



Task

Show how reduce (or foldl or foldr etc), work (or would be implemented) in your language.



See also

 Wikipedia article:   Fold
 Wikipedia article:   Catamorphism


---------------------- CATAMORPHISMS ---------------------
 
-- the arguments available to the called function f(a, x, i, l) are
-- a: current accumulator value
-- x: current item in list
-- i: [ 1-based index in list ] optional
-- l: [ a reference to the list itself ] optional
 
-- foldl :: (a -> b -> a) -> a -> [b] -> a
on foldl(f, startValue, xs)
    tell mReturn(f)
        set v to startValue
        set lng to length of xs
        repeat with i from 1 to lng
            set v to |λ|(v, item i of xs, i, xs)
        end repeat
        return v
    end tell
end foldl
 
-- the arguments available to the called function f(a, x, i, l) are
-- a: current accumulator value
-- x: current item in list
-- i: [ 1-based index in list ] optional
-- l: [ a reference to the list itself ] optional
 
-- foldr :: (a -> b -> a) -> a -> [b] -> a
on foldr(f, startValue, xs)
    tell mReturn(f)
        set v to startValue
        set lng to length of xs
        repeat with i from lng to 1 by -1
            set v to |λ|(v, item i of xs, i, xs)
        end repeat
        return v
    end tell
end foldr
 
 
--- OTHER FUNCTIONS DEFINED IN TERMS OF FOLDL AND FOLDR --
 
-- concat :: [String] -> string
on concat(xs)
    foldl(my append, "", xs)
end concat
 
 
-- product :: Num a => [a] -> a
on product(xs)
    script
        on |λ|(a, b)
            a * b
        end |λ|
    end script
 
    foldr(result, 1, xs)
end product
 
 
-- str :: a -> String
on str(x)
    x as string
end str
 
 
-- sum :: Num a => [a] -> a
on sum(xs)
    script
        on |λ|(a, b)
            a + b
        end |λ|
    end script
 
    foldl(result, 0, xs)
end sum
 
 
--------------------------- TEST -------------------------
on run
    set xs to {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
 
    {sum(xs), product(xs), concat(map(str, xs))}
 
    --> {55, 3628800, "10987654321"}
end run
 
 
-------------------- GENERIC FUNCTIONS -------------------
 
-- append :: String -> String -> String
on append(a, b)
    a & b
end append
 
 
-- map :: (a -> b) -> [a] -> [b]
on map(f, xs)
    -- The list obtained by applying f
    -- to each element of xs.
    tell mReturn(f)
        set lng to length of xs
        set lst to {}
        repeat with i from 1 to lng
            set end of lst to |λ|(item i of xs, i, xs)
        end repeat
        return lst
    end tell
end map
 
 
-- Lift 2nd class handler function into 1st class script wrapper 
-- mReturn :: Handler -> Script
on mReturn(f)
    if class of f is script then
        f
    else
        script
            property |λ| : f
        end script
    end if
end mReturn