Search code examples
syntax-errorsml

Syntax errors in sml: Inserting LOCAL


The following method determines how many numbers can be added up starting from the beginning of the list without adding up to 4:

number_before_Reaching_sum (4, [1,2,3,4,6]);
should return : val it = 2 : int

fun number_before_reaching_sum (sum : int * int list) =
    let val len_orig_list = length (#2 sum)
    in fun num_bef_reach_sum (sum) =
           if #1 sum <= 0
           then len_orig_list - (length (#2 sum)) - 1
           else num_bef_reach_sum (#1 sum - hd (#2 sum), tl (#2 sum))
    end

syntax error: inserting LOCAL
syntax error found at EOF

I can't seem to find the errors in this code. I have some experience with Python, but just starting to learn sml. I'm loving it, but I don't understand all the error messages. I have really spent hours on this, but I think I don't know enough to solve my problem. I tried exchanging let with local, but i still got a syntax error (equalop). I think that the function between in and end is an expression and not a declaration. But I would appreciate any comments on this. If you come up with alternative code, it would be great if you did it without using more advanced features, since I'm just trying to get the basics down :-)


Solution

  • You probably meant this:

    fun number_before_reaching_sum (sum : int * int list) =
        let 
            val len_orig_list = length (#2 sum)
            fun num_bef_reach_sum (sum) =
               if #1 sum <= 0
               then len_orig_list - (length (#2 sum)) - 1
               else num_bef_reach_sum (#1 sum - hd (#2 sum), tl (#2 sum))
        in 
            num_bef_reach_sum (sum)
        end
    

    With let … in … end, the part between let and in is for the local definitions; the part between in and end is for the expression which will be the evaluation of the let … in … end expression (this construct is indeed an expression).

    Think of let … in … end as a possibly complex expression. You hoist parts of the expression as definitions, then rewrite the complex expression using references to these definitions. This help write shorter expressions by folding some of its sub‑expressions. This construct is also required when recursion is needed (a recursion requires a defining name).

    Another way to understand it, is as the application of an anonymous function whose arguments bindings are these definitions.

    Ex.

    let
       val x = 1
       val y = 2
    in
       x + y
    end
    

    is the same as writing

    (fn (x, y) => x + y) (1, 2)
    

    which is the same as writing

    1 + 2
    

    You erroneously put a definition at the place of the expression the whole evaluates to.

    (note I did not check the function's logic, as the question was about syntax)