How to keep elements in list through out the program in SML?

647 views Asked by At

Suppose I have to update a list with each call to a function, such that, the previous element of the list are preserved.

Here is my attempt:

local 
    val all_list = [];
in
    fun insert (x:int) : string  = int2string (list_len( ((all_list@[x])) ) )
end;

The problem is that each time I call to insert, I get the output "1", which indicates that the list is initiated to [] again.

However I was expecting output of "1" for the first call to insert, and "2" for the second call,...etc.

I am not able to come with a workaround. How should it be done?

2

There are 2 answers

0
Anton Trunov On BEST ANSWER

You need to use side-effects. Most of the time functional programmers prefer to use pure functions, which don't have side effects. Your implementation is a pure function, so it will always return the same value for the same input (and in your case it returns the same value for any input).

You can deal with that by using a reference.

A crash course on references in Standard ML:

  • use ref to create a new reference, ref has type 'a -> 'a ref, so it packs an arbitrary value into a reference cell, which you can modify later;
  • ! is for unpacking a reference: (!) : 'a ref -> 'a, in most imperative languages this operation is implicit, but not in SML or OCaml;
  • (:=) : 'a ref * 'a -> unit is an infix operator used for modifying references, here is how you increment the contents of an integer reference: r := !r + 1.

The above gives us the following code (I prepend xs onto the list, instead of appending them):

local
    val rxs = ref []
in
    fun insert (x:int) : string =
      (rxs := x :: !rxs;
       Int.toString (length (!rxs)))
end
0
John Coleman On

Values are immutable in SML. insert is defined in a context in which the value of all_list is [] and nothing about your code changes that value.

all_list@[x] 

doesn't mutate the value all_list -- it returns a brand new list, one which your code promptly discards (after taking its length).

Using reference types (one of SML's impure features) it is possible to do what you seem to be trying to do, but the resulting code wouldn't be idiomatic SML. It would break referential transparency (the desirable feature of functional programming languages where a function called with identical inputs yields identical outputs).