Search code examples
functional-programmingsml

Standard ML : Check conditions when iterating a list


i'm studying the programming language Standard ML and i am wondering how i can iterate a list with a check condition.

In other languages we have for loops like :

var input;
for(var i = 0; i < arr.length; i++) {
   if(arr[i] == input) {
      //you have arrived at your condition...
   } else {
     //other case
   }
}

f.ex

i want to iterate through a list and check if the input variable matches a existing element in the list.

i = 5  
xs = [1,5,2,3,6] --> the element matches after one iteration.

fun check i nil = []
| check i (x::xs) = if i=x 
                    then //dowork 
                    else //iterate;

I've gone through many documentations on how to implement this without success.

It would be really helpful if someone could give me some explaining regarding how i can use let val A in B end; inside or outside of if conditions for this kind of work.


Solution

  • how i can iterate a list with a check condition

    fun check i nil = []
    | check i (x::xs) = if i=x 
                        then //dowork 
                        else //iterate;
    

    i want to iterate through a list and check if the input variable matches a existing element in the list.

    I would call this a predicate combinator. It already exists in the standard library and is called List.exists. But you can also make it yourself:

    fun exists p [] = false
      | exists p (x::xs) = p x orelse exists p xs
    

    This is a simplification of the if-then-else you're attempting, which would look like:

    fun exists p [] = false
      | exists p (x::xs) = if p x then true else exists p xs
    

    If-then-else isn't really necessary when the result type is a boolean, since orelse, andalso and not are short-circuiting (will not evaluate their second operand if the result can be determined with the first).

    Using this List.exists function to check if a list contains a specific element, you have to construct a p that compares the list element with some given value, e.g.:

    fun check y xs = List.exists (fn x => ...) xs
    

    This may seem a bit more complicated than simply writing check recursively from scratch,

    fun check y [] = false
      | check y (x::xs) = ... orelse check y xs
    

    but a solution using higher-order functions is preferred for several reasons.

    One is that a seasoned reader will quickly detect what you're doing when seeing List.exists: Ah, you're scanning a list for an element given a predicate. Whereas if your function is explicitly recursive, the reader will have to read the entire recursion scheme: OK, the function doesn't do anything funky, which I'd have known if I'd seen e.g. List.exists.