SML - 列表替换函数的迭代翻译

时间:2011-03-07 06:40:36

标签: loops sml iteration

我相信我正在将我的第一个函数转换为仅使用赋值和循环。我知道这是针对函数式编程的,但这是教授想要的。

递归函数:

fun sub (x, y, []) = []
  | sub (x, y, z::zz) = if x = z then y::sub(x, y, zz)
            else z::sub(x, y, zz);

迭代翻译:

fun sub2 (x, y, z) =
    let val ret = ref []; val temp = z;
    in
        while !temp <> []
        do (if x = hd(!temp) then ret := !ret::y; temp := tl(!temp)
            else ret := ret::hd(!temp); temp := tl(!temp));
        !ret;
    end;

我在smlnj上运行以下错误。第一个是do,第二个是结束。

  

错误:语法错误:用EQUALOP替换END

     

错误:在EOF中找到语法错​​误

我很感激帮助调试或者更简洁的方法来完成这个迭代功能。

1 个答案:

答案 0 :(得分:4)

为什么哦,为什么他不会那样?没关系......

有很多问题。

  1. 你正在使用许多分号,不需要它们。然而,这不是语法错误。
  2. 您在if语句中忘记了序列(exp1; exp2)周围的括号。只允许在let..in..end表达式的“in”部分中排除括号。
  3. 您将temp作为ref类型引用(使用:=和!)。但是你没有把它作为参考。这意味着您的输入变量z必须作为参考。如果这是你想要的,那么它与原来的子功能不匹配。
  4. 原始子功能将自身限制为相等类型。但是,如果情况并非如此,那么您的!temp <> null将会受到限制。使用List.null函数代替“最佳实践”。
  5. 最后!ret;的分号不应该在您的序列停止时出现,否则end将成为失败的序列的一部分。
  6. 你忘了在你的其他部分条件中取消引用ret
  7. 你已经改变了cons(:)的参数。 Cons具有类型'a * 'a list,因此获取元素,然后是元素列表。解决这个问题并保持元素顺序的一种方法是使用append(@)函数,然后将元素放在单个列表中。然而,有更多的方法以更好的方式处理它,因为追加函数在大列表上的表现非常糟糕。
  8. 以下是一个有效的功能:

    fun sub2 (x, y, z) =
    let 
      val ret = ref []
      val temp = ref z
    in
      while not (null (!temp)) do 
        if x = hd(!temp) then 
          (ret := !ret @ [y]; 
           temp := tl(!temp))
        else 
          (ret := !ret @ [hd(!temp)]; 
           temp := tl (!temp));
      !ret
    end
    

    这里可以改进的一个显而易见的事情是你总是用相同的值更新temp。所以这可以被考虑在内。而且条件可以改为案例

    fun sub2 (x, y, z) =
        let 
          val ret = ref []
          val temp = ref z
        in
          while not (null (!temp)) do       
            (case x = hd(!temp) of
              true => ret := y :: !ret
            | false => ret := hd(!temp) :: !ret
           ;temp := tl (!temp));         
          rev (!ret)
        end
    

    特别注意元素不是如何附加到结果列表中,而是放在前面然后在结尾处反转生成的列表以获得正确的顺序。这将使您在大型列表上获得更好的性能。然而,当你在SML中使用命令式样式时,仍然有更好的方法。

    正如您已经看到的,它可以以功能的方式完成。但它也可以更简单。请考虑以下使用地图。

    fun sub3 (x, y, zs) = map (fn z => if z = x then y else z) zs