fsharp: step 3: Consolidated vector and list let* binding logic.
[jackhill/mal.git] / fsharp / core.fs
CommitLineData
6c47cf67
PS
1module Core
2
3 open Types
4
5 let errArity () = EvalError("arity: wrong number of arguments")
6 let errArgMismatch () = EvalError("argument mismatch")
7
8 let inline toNumber node =
9 match node with
10 | Number(n) -> n
11 | _ -> raise <| errArgMismatch ()
12
13 let inline makeNumFolder op =
14 (fun state node -> op state (node |> toNumber))
15
16 let add nodes =
17 let addNode = makeNumFolder (+)
18 nodes |> Seq.fold addNode 0L |> Number
19
20 let subtract nodes =
21 let subtractNode = makeNumFolder (-)
22 match nodes with
23 | [] -> raise <| errArity ()
24 | Number(first)::[] -> Number(-first)
25 | Number(first)::rest -> rest |> Seq.fold subtractNode first |> Number
26 | _ -> raise <| errArgMismatch ()
27
28 let multiply nodes =
29 let multiplyNode = makeNumFolder ( * )
30 nodes |> Seq.fold multiplyNode 1L |> Number
31
32 let divide nodes =
33 let divideNode = makeNumFolder (/)
34 match nodes with
35 | [] -> raise <| errArity ()
36 | Number(first)::[] -> 1L / first |> Number
37 | Number(first)::rest -> rest |> Seq.fold divideNode first |> Number
38 | _ -> raise <| errArgMismatch ()