I'm trying to implement last in ML. last can return the last element of a list.
For example, L=[1, 2, 3, 4], last(L) = 4. Here is my implementation.
fun last [] = last((h::nil)) = h | last((h::tail)) = last(tail);
It give me "unbound variable or constructor: h". In my understanding, h is a variable declared by me, representing the head of the list, why error would occur on variable h?
You definition can be laid out as
fun last [] = last((h::nil)) = h
| last((h::tail)) = last(tail);
SML interprets the first clause as an attempt to assign to last []
the Boolean value which is the result of the comparison last((h::nil)) = h
. Since the pattern that you are matching in that clause is []
and []
doesn't involve h
, the h
in the comparison last((h::nil)) = h
is unbound, hence the error. In any event such a comparison would make very little sense and is clearly not your intention.
Note that last []
can't be sensibly defined. You alternatives is to either simply ignore it or to address it by raising an error (either Empty
or a custom error). The real basis clause of the function last
is that of a 1-element list. You seem to know how to handle it. Your code actually works when you stop trying to use your first clause to simultaneously give a value to both last []
and last (h::nil)
and instead just do the latter:
fun last (h::nil) = h
| last (h::tail) = last tail;
Here I removed 3 pairs of superfluous parentheses around h::nil
, h::tail
, and tail
. In SML function invocation requires no parentheses. You only need parentheses when you need to insure proper grouping. Note that the first pattern can also be written more succintly as [h]
.
You get a nonexahaustive match warning since you haven't given a definition for last []
. You could just ignore the warning (since it is rather common with functions only defined for nonempty lists), or write it as
fun last [] = raise Empty
| last (h::nil) = h
| last (h::tail) = last tail;