use*_*876 7 functional-programming case sml pattern-matching
我正在用SML编写一个作业,我已经做了一些练习问题,我觉得我错过了一些东西 - 我觉得我使用了太多的case陈述.这就是我正在做的事情以及我遇到问题的问题陈述:
编写一个函数all_except_option,它接受一个字符串和一个字符串列表.如果字符串不在列表中,则返回NONE,否则返回SOME lst,其中lst与参数列表类似,但字符串不在其中.
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)
Run Code Online (Sandbox Code Playgroud)编写一个函数get_substitutions1,它接受一个字符串列表列表(字符串列表,替换列表)和一个字符串s并返回一个字符串列表.结果具有某些列表中的所有字符串,这些字符串也具有s,但s本身不应该在结果中.
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)
Run Code Online (Sandbox Code Playgroud)-
same_string是提供的功能,
fun same_string(s1 : string, s2 : string) = s1 = s2
首先,我将开始在函数定义中使用模式匹配,而不是使用"顶级"case语句.去糖后它基本上归结为同样的东西.除非严格要求,否则我会删除显式类型注释:
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)
Run Code Online (Sandbox Code Playgroud)
如果速度不重要,那么您可以在第一个函数中合并这两种情况:
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)
Run Code Online (Sandbox Code Playgroud)
但是因为你在第二个函数中使用append(@),并且因为它不是尾递归的,所以我不认为它是你的主要关注点.请记住,追加是潜在的"邪恶",你应该几乎总是使用连接(然后在返回时反转你的结果)和尽可能的尾递归(它总是).
如果你真的喜欢显式类型注释,那么你可以这样做:
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)
Run Code Online (Sandbox Code Playgroud)
但这只是我的首选方式,如果我真的需要添加类型注释.
顺便说一下,为什么你有这个same_string功能呢?您可以直接进行比较.除非你打算在某些时候用一些特殊的逻辑来交换它,否则使用辅助功能是很奇怪的.但是,您的函数名称不会消耗它.