I'm trying to understand pattern matching and recursion and how the program is executing.
In a simple case:
fun sum_list_num xs =
case xs of
[] => NONE
| x::xs' => case (sum_list_num xs') of
NONE => (print "x: "; print (Int.toString x);
print "\n"; SOME x)
| SOME y => (print "x: "; print (Int.toString x);
print " y: "; print (Int.toString y); print"\n";
SOME (x+y))
I can see that the y1
in SOME y
is basically acting as an accumulator as the above is returning in sum_list_num [1,2,3,4,5];
:
x: 5
x: 4 y: 5
x: 3 y: 9
x: 2 y: 12
x: 1 y: 14
val it = SOME 15 : int option
Am I right to be thinking that or have I missed the mark?.
Now for a more advanced example I'm trying to wrap my head around pattern matching and I've come across this post but I can't make heads or tails of how it works. I've modified the function to print out what's going on at each 'match':
fun smatch (str, in_stringlist) =
case in_stringlist of
[] => NONE
| x::x' => case(same_string(x, str), smatch (str, x')) of
(true, _) => (print "MATCH CASE x: "; print x;
print " x': "; print(gather(x'));
print "\n"; SOME x')
| (false, NONE) => (print "NONE CASE x: ";print x;
print "\n"; NONE)
| (false, SOME z) => (print "SOME Z CASE x: "; print x;
print " z: ";print(gather(z));
print " x': ";print(gather(x'));print "\n";
SOME (x :: z))
The output I was totally not expecting when called using smatch("this", ["1", "2", "this", "4", "5", "6"])
NONE CASE x: 6
NONE CASE x: 5
NONE CASE x: 4
MATCH CASE x: this x': 4 5 6
SOME Z CASE x: 2 z: 4 5 6 x': this 4 5 6
SOME Z CASE x: 1 z: 2 4 5 6 x': 2 this 4 5 6
val it = SOME ["1","2","4","5","6"] : string list option
Where I'm lost:
- Why am I returning
x'
in the match case? - Why is everything in the list after the string I'm looking for evaluate to the NONE case?
- I've been sitting here with a pad of paper and many edits and I'm having a tough time 'following' what exactly is happening in how the recursive calls are being stacked up and evaluated.
Any help would be appreciated. Reading SML guides on pattern matching all day have not made this any clearer!
note: the second example IS a homework question to a Coursera class (I answered it using a let function that used an accumulator to build up the list rather than a nested case statement, I came across the above while googling pattern matching SML and have been trying to wrap my head around it all day).
FYI gather is just a helper function so I can print out the contents of a list of strings:
fun gather xs =
foldl (fn (x,acc) =>
acc ^ " " ^ x) (hd xs) (tl xs)