0
votes

I am back again with a basic question.! ;)

I have learned some of the List functions. "List.nth" is one of them. When I use this function in SML command window, It is working fine. But when used inside Let..in..end; block , It is not working.

I hope, Somebody would be able to help out.

let
  val actualDays = 0;

in
  actualDays = List.nth([10,20,31,50,45], 2);
  actualDays
end;

Expected output:

 val it = 31 : int

Actual output:

 val it = 0 : int

Thanks in Advance!

2

2 Answers

2
votes

The reason that this does not work as you intend has nothing to do with the List.nth function or the fact that you're inside a let expression. The reason that this does not work as you intend is that = is the equality operator, not an assignment operator, in SML.

The only assignment operator in SML is the := operator and its left operand needs to be a ref, not a plain integer. So one way to fix your code would be to change actualDays to be an int ref rather than just an int and to use := instead of =. However mutating variables isn't very idiomatic in SML. A better solution would be to adjust your logic to not need any mutation - probably by using recursive functions or, depending on what exactly you're trying to do, higher order functions.

1
votes

You need to let go of your "imperative thinking", and open your mind for the "functional thinking" instead. For example

As stated you can't reassign a variable unless it is a reference. And if you ever need to use references, then you are probably doing it "wrong" anyways. In functional programming you are actually doing name binding (sometimes also called single assignment), instead of variable assignment. Think of them as "immutable objects".

Lets first look at your code

let
  val actualDays = 0;    
in
  actualDays = List.nth([10,20,31,50,45], 2);
  actualDays
end;

When u put a sequence of expressions inside the in ... end part, it is actually the same as having in ( expr_1; ... ; expr_n) end, note the parenthesis which denote a sequence of expressions. A sequence of expressions evaluates each expression from left to right, ignoring all but the last expressions result. Thus it is mainly used for evaluating expressions with side effects

- (print "foo\n"; print "bar\n"; 3);
foo
bar
val it = 3 : int

In your case, as the equal sign is not an assignment operator, but an comparison operator, your first expression will evaluate to a boolean expression, which is "ignored" as it has no side effects, and then the value of actualDays is returned as it is the last expression.

One way to fix your example would be to declare actualDays to be the result of List.nth. Then your function could take two arguments, one argument would be the element that you expect to get, and the other argument could be the index where you wan't to look it up.

fun foo x i =
    let
      val actualDays = List.nth([10,20,31,50,45], i)
    in
      x = actualDays
    end

- foo 20 1;
val it = true : bool
- foo 50 3;
val it = true : bool

However in this specific function, there is no need for the let-expression, and you could just as well write it like this

fun foo x i = x = List.nth([10,20,31,50,45], i)