Search code examples
functionif-statementstandardssmlml

Multiple if statemens in one Function in SML


I want to write a function in SML that checks if the parameters a, b, c are true and, if they are, increases the value x with 1.0, 2.0 or 3.0. For Example:

fun calc(a:bool, b:bool, c:bool, d:int) = 
let
    val x = 0.0
in
    if a then x+1.0 else x+0.0
    ;if b then x+2.0 else x+0.0
    ;if c then x+3.0 else x+0.0
    ;if d<120 then x+4.0 else x+0.0
end

If I run this code with a, b and c true and d < 120, then I get the output:

val it = 0.0 : real

but I want to get as output x.


Solution

  • First of all, there is no problem with having multiple if expressions in a single function definition. For example, the following is unproblematic:

    fun sign x = if x < 0  then ~1
                else if x = 0 then 0
                else 1;
    

    Note that if ... then ... else is an expression which yields a value, not a control structure. You have several independent if expressions in that in block, separated by semicolons. When you have several expressions in such an in block, they are evaluated sequentially, with the result of the last expression being the overall value of that block. This only makes sense when the earlier expressions have side effects (e.g. printing something to the terminal or modifying the store using a ref variable). In your cases, your expressions have no side effects and you are simply discarding the values (except the very last one).

    You seem to want to have a series of val bindings, where the later ones depend on the earlier ones. This can be done, but it would need to be in the let part of the construct rather than in the in part. Something like:

    fun calc(a:bool, b:bool, c:bool, d:int) = 
    let
        val x = 0.0
        val x = if a then x+1.0 else x
        val x = if b then x+2.0 else x
        val x = if c then x+3.0 else x
    in
        if d<120 then x+4.0 else x
    end
    

    For example:

    - calc(false,false,true,119);
    val it = 7.0 : real
    

    You can do this more directly by writing a helper function:

    fun f(a,x) = if a then x else 0.0;
    

    And then:

    fun calc(a,b,c,d) =  
    let
       val x = f(a,1.0) + f(b,2.0) + f(c,3.0)
    in
       if d < 120 then x + 4.0 else x
    end