Functions that resemble imperative syntax
while : (a -> Basics.Bool) -> a -> (a -> a) -> a
The classic while loop.
count : Int
count =
Loop.while ((>) 100) 0 ((+) 1)
-- is basically analagous to..
--
-- var i = 0;
-- while ( i < 100) {
-- i++;
-- }
until : (a -> Basics.Bool) -> a -> (a -> a) -> a
A twist on the classic while loop. It loops while the condition is NOT met.
countJustForFun : Int -> Int
countJustForFun to =
Loop.until
((==) to)
0
((+) 1)
doWhile : (a -> Basics.Bool) -> a -> (a -> a) -> a
Much like while
, however this function applies its a -> a
before it continues, ensuring that f
is applied to the output at least once.
while ((>) 0) 0 ((+) 1) == 0
doWhile ((>) 0) 0 ((+) 1) == 1
A way that a loop can end
explicitLoop : (a -> Termination a b) -> a -> b
A loop in imperative code might have break and continue cases that are clearly marketed out with words like break;
and return ...;
. With this explicitLoop
function you can map the break points in imperative code directly to Break
and Continue
points in a function.
clipSegment x0 y0 x1 y1 c0 c1 ({ xmax, xmin, ymax, ymin } as viewport) =
Imperative.explicitLoop
(\{ x0, y0, x1, y1, c0, c1 } ->
if c0 == 0 && c1 == 0 then
Imperative.Break <| Just ( x0, y0, x1, y1 )
else if Bitwise.and c0 c1 /= 0 then
Imperative.Break Nothing
else
let
c =
if c0 == 0 then
c1
else
c0
( x, y ) =
if Bitwise.and c 8 /= 0 then
( x0 + (x1 - x0) * (ymax - y0) / (y1 - y0), ymax )
else if Bitwise.and c 4 /= 0 then
( x0 + (x1 - x0) * (ymin - y0) / (y1 - y0), ymin )
else if Bitwise.and c 2 /= 0 then
( xmax, y0 + (y1 - y0) * (xmax - x0) / (x1 - x0) )
else
( xmin, y0 + (y1 - y0) * (xmin - x0) / (x1 - x0) )
in
if c0 /= 0 then
Imperative.Continue { x0 = x, y0 = y, x1 = x1, y1 = y1, c0 = regionCode x y viewport, c1 = c1 }
else
Imperative.Continue { x0 = x0, y0 = y0, x1 = x, y1 = y, c1 = regionCode x y viewport, c0 = c0 }
)
{ x0 = x0, y0 = y0, x1 = x1, y1 = y1, c1 = c1, c0 = c0 }