Python and JavaScript both give us generators, and the keyword yield, allowing us to draw an arbitrary number of values from an infinite stream.
Haskell, similarly, allows us to draw values from infinite lists, without knowing in advance how many we will need, by writing things like:
take 10 (iterate (2*) 1) --> [1,2,4,8,16,32,64,128,256,512]
or
take 10 (iterate (\x -> (x+3)*2) 1) --> [1,8,22,50,106,218,442,890,1786,3578]
(see iterate either here, with examples or on Hoogle)
Applescript, not to be outdone, also lets us write things like:
take(10, iterate(dbl, 1)) --> {1, 2, 4, 8, 16, 32, 64, 128, 256, 512}
by recruiting a script object as a generator:
on run
take(10, iterate(succ, 0)) --> {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
take(10, iterate(dbl, 1)) --> {1, 2, 4, 8, 16, 32, 64, 128, 256, 512}
take(10, iterate(etc, 1)) --> {1, 8, 22, 50, 106, 218, 442, 890, 1786, 3578}
end run
-- SAMPLE TEST FUNCTIONS
-- succ :: Int -> Int
on succ(x)
1 + x
end succ
-- dbl :: Num -> Num
on dbl(x)
2 * x
end dbl
-- etc :: Num -> Num
on etc(x)
(x + 3) * 2
end etc
-- ITERATE AND TAKE --------------------------------------
-- https://github.com/RobTrew/prelude-applescript
-- iterate :: (a -> a) -> a -> Generator [a]
on iterate(f, x)
script
property v : missing value
property g : mReturn(f)'s |λ|
on |λ|()
if v is missing value then
set v to x
else
set v to g(v)
end if
return v
end |λ|
end script
end iterate
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: First-class m => (a -> b) -> m (a -> b)
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn
-- min :: Ord a => a -> a -> a
on min(x, y)
if y < x then
y
else
x
end if
end min
-- take :: Int -> [a] -> [a]
-- take :: Int -> String -> String
on take(n, xs)
set c to class of xs
if c is list then
if 0 < n then
items 1 thru min(n, length of xs) of xs
else
{}
end if
else if c is string then
if 0 < n then
text 1 thru min(n, length of xs) of xs
else
""
end if
else if c is script then
set ys to {}
repeat with i from 1 to n
set end of ys to xs's |λ|()
end repeat
return ys
else
missing value
end if
end take