【问题标题】:SML/NJ function errorSML/NJ 功能错误
【发布时间】:2014-07-15 17:12:09
【问题描述】:

我想要一个函数,它接受一个整数列表并返回排序后的列表(从左到右递增)。这必须通过使用这两个函数来完成:

datatype tree=Empty
        | Node of int*tree*tree;
fun treeinsert(Empty,k) = Node(k,Empty,Empty)
  | treeinsert(T as Node(y,left,right),k) =
       if k=y then T
       else if k<y then Node(y,treeinsert(left,k),right)
       else Node(y,left,treeinsert(right,k));

fun inOrder(Empty) = nil
  | inOrder(Node(a,left,right)) =
     inOrder(left)@[a]@inOrder(right) ;

所以我做了这个函数,它的问题是总是返回一个空列表。

val y=Empty;
fun treesort(x::xs)=let val y=treeinsert(Empty,x)
                    in treesort(xs)
                    end
  |treesort []=inOrder(y);

我做错了什么?提前谢谢你..

【问题讨论】:

    标签: smlnj


    【解决方案1】:

    在这部分:

    let val y=treeinsert(Empty,x)
    in treesort(xs)
    end
    

    你从函数返回的是treesort(xs),但你没有用xy做任何事情,所以你将继续用xs递归直到xs[]点你会退货的。

    【讨论】:

      【解决方案2】:

      您在第 2 行定义的变量 y 在第 3 行的 in 到第 4 行的 end 的范围内。您从不在该代码块中使用它,因此该变量未使用,并且因此不会影响程序的行为(除了在您定义它时会调用treeInsert 的事实)。当您在第 5 行使用 y 时,这指的是您在第 1 行定义的变量 y,因为另一个不在范围内。

      重要的是要理解第 1 行定义的变量和第 2 行定义的变量是完全独立的,只是碰巧有相同的名称(这意味着第 1 行中的变量不能被访问,而另一个是在适用范围)。你的程序相当于这样:

      val y1 = Empty;
      fun treesort(x::xs)=let val y2=treeinsert(Empty,x)
                          in treesort(xs)
                          end
        |treesort []=inOrder(y1);
      

      这应该清楚为什么它不能按您的意愿工作。

      【讨论】:

      • 那么我应该如何在两个“let..in..end”之间使用相同的变量,或者至少从函数内部访问一个“全局”?
      • @user2879198 您可以通过写入全局名称来访问全局变量,而不是在其他任何地方定义另一个具有相同名称的变量。我认为您真正要问的是如何更改变量的值。答案是:你不能。您可以通过使用refs(它为您提供可变值)来解决此问题,但在绝大多数情况下,您最好重新处理程序逻辑,这样您就不必这样做(通常意味着通过通过附加参数获取信息)。
      • 你能给我一个有趣的树排序的“适当逻辑”的例子吗?
      • @user2879198 定义一个递归辅助函数,它接受两个参数:列表 (xs) 和树 (y)。当该函数重复出现时,将 y 的新值作为参数传递。然后,您的 treesort 函数将只是 fun treeseort xs = treesortHelper(xs, Empty)
      • 好的,感谢您的建议,我找到了解决方案。非常感谢您的宝贵时间!
      猜你喜欢
      • 2013-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-18
      • 2013-12-17
      • 2017-01-03
      • 2017-01-27
      • 2011-11-24
      相关资源
      最近更新 更多