案例陈述和模式匹配

时间:2011-10-17 09:37:22

标签: functional-programming pattern-matching case sml

我正在使用SML编写作业并且我已经做了一些练习问题而且我觉得我错过了一些东西 - 我觉得我使用了太多的{​​{1}}语句。这就是我正在做的事情以及我遇到问题的问题陈述。:

  1. 编写一个函数all_except_option,它接受一个字符串和一个字符串列表。如果字符串不在列表中,则返回NONE,否则返回SOME lst,其中lst与参数列表类似,但字符串不在其中。

    case
  2. 编写一个函数get_substitutions1,它接受一个字符串列表列表(字符串列表,替换列表)和一个字符串s并返回一个字符串列表。结果具有某些列表中的所有字符串,这些字符串也包含s,但s本身不应该在结果中。

    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)  
    
  3. - 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

3 个答案:

答案 0 :(得分:9)

首先,我将开始在函数定义中使用模式匹配 而不是有一个“顶级”案例陈述。它基本上归结为 脱糖后同样的事情。除非严格需要,否则我会删除显式类型注释:

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)

如果速度不重要,那么您可以在第一个函数中合并这两种情况:

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)

但是因为你在第二个函数中使用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)

但这只是我的首选方式,如果我真的需要添加类型注释。

顺便说一下,为什么你有same_string功能呢?您可以直接进行比较。除非你打算在某些时候用一些特殊的逻辑来交换它,否则使用辅助功能是很奇怪的。但是,你的函数名称并没有消化它。

答案 1 :(得分:1)

除了Jesper.Reenberg提到的内容之外,我还想提一下,booltrue的{​​{1}}匹配可以替换为false - if - then。但是,有些人认为if-then-else比案例陈述更丑陋

答案 2 :(得分:0)

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