Chadtech / elm-imperative-porting / Imperative

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


type Termination a b
    = Break b
    | Continue a

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 }