Conclusions and pattern matching

I am coding in SML for the job, and I have made some practice problems, and it seems to me that I am missing something - it seems to me that I am using too many case . Here's what I do, and statements about the problems I'm having problems with:

  • Write an all_except_option function that takes a string and a list of strings. Return NONE if the string is not in the list, else returns SOME lst, where lst is similar to the argument list, except that it does not have a string.

     fun all_except_option(str : string, lst : string list) = case lst of [] => NONE | x::xs => case same_string(x, str) of true => SOME xs | false => case all_except_option(str, xs) of NONE => NONE | SOME y=> SOME (x::y) 
  • Write a function get_substitutions1, which takes a list of a list of strings (a list of a list of strings, substitutions) and a string s and returns a list of strings. The result has all the lines that are in some list in permutations, which also have s, but s itself should not be the result.

     fun get_substitutions1(lst : string list list, s : string) = case lst of [] => [] | x::xs => case all_except_option(s, x) of NONE => get_substitutions1(xs, s) | SOME y => y @ get_substitutions1(xs, s) 

- same_string - given function, fun same_string(s1 : string, s2 : string) = s1 = s2

+8
pattern-matching functional-programming case sml
source share
3 answers

First of all, I would start using pattern matching in a function definition instead of having a top-level operator. It basically comes down to the same item after degreasing. I would also get rid of explicit type annotations, unless this is required:

 fun all_except_option (str, []) = NONE | all_except_option (str, x :: xs) = case same_string(x, str) of true => SOME xs | false => case all_except_option(str, xs) of NONE => NONE | SOME y => SOME (x::y) fun get_substitutions1 ([], s) = [] | get_substitutions1 (x :: xs, s) = case all_except_option(s, x) of NONE => get_substitutions1(xs, s) | SOME y => y @ get_substitutions1(xs, s) 

If speed doesn't matter, you can combine two cases in the first function:

 fun all_except_option (str, []) = NONE | all_except_option (str, x :: xs) = case (same_string(x, str), all_except_option(str, xs)) of (true, _) => SOME xs | (false, NONE) => NONE | (false, SOME y) => SOME (x::y) 

But since you are using append (@) in the second function, and since it is not tail recursive, I do not consider this to be your main concern. Keep in mind that append is a potential “evil” and you should almost always use concatenation (and then reverse your result when it returns) and tail recursion whenever possible (it always is).

If you really like explicit type annotations, you can do it like this:

 val rec all_except_option : string * string list -> string list option = fn (str, []) => NONE | (str, x :: xs) => case (same_string(x, str), all_except_option(str, xs)) of (true, _) => SOME xs | (false, NONE) => NONE | (false, SOME y) => SOME (x::y) val rec get_substitutions1 : string list list * string -> string list = fn ([], s) => [] | (x :: xs, s) => case all_except_option(s, x) of NONE => get_substitutions1(xs, s) | SOME y => y @ get_substitutions1(xs, s) 

But this is only my preferred way if I really need to add type annotations.

By the way, why do you have the same_string function? Instead, you can simply compare it. Using an auxiliary function is simply monstrous if you do not plan to exchange it at some point with some special logic. However, the names of your functions are not so important that.
+9
source share

In addition to what Jesper.Reenberg mentioned, I just wanted to mention that a match on bool for true and false can be replaced with if - then - else . However, some people find if-then-else more ugly than the case argument

+1
source share
 fun same_string( s1: string, s2: string ) = if String.compare( s1, s2 ) = EQUAL then true else false fun contains( [], s: string ) = false | contains( h::t, s: string ) = if same_string( s, h ) then true else contains( t, s ) fun all_except_option_successfully( s: string, [] ) = [] | all_except_option_successfully( s: string, h::t ) = if same_string( s, h ) then t else ( h :: all_except_option_successfully( s, t ) ) fun all_except_option( s: string, [] ) = NONE | all_except_option( s: string, h::t ) = if same_string( s, h ) then SOME t else if contains( t, s ) then SOME ( h :: all_except_option_successfully( s, t ) ) else NONE 
0
source share

All Articles