2012-09-27 54 views
0

下面的代码只是一种原型。我想知道的是为什么它不能编译。ML代码错误的原因

fun test(list) = 
    let 
    fun inner(list) = 
    let 
     val from = #1(hd(list)) 
     in 
     if null(tl(list)) = false then innerinner(tl(list),from) 
     else false 
     end 
    fun innerinner(list,from) = 
     if #2(hd(list)) = from then true 
     else if null(list) = false then innerinner(tl(list),from) 
     else false 
    in 
    inner(list) 
    end; 

错误消息是:

test.txt:7.34-7.44 Error: unbound variable or constructor: innerinner 
test.txt:3.2-9.6 Error: unresolved flex record 
(can't tell what fields there are besides #1) 
test.txt:10.2-13.13 Error: unresolved flex record 
(can't tell what fields there are besides #2) 

uncaught exception Error 
raised at: ../compiler/Toplevel/interact/evalloop.sml:66.19-66.27 
.... 

我ML编程的一种初学者。任何人都可以教我什么是错的?

回答

2

你在这里有很多事情要做。如果我们先看看你遇到的错误。

  1. 绑定变量或构造函数:innerinner

    在SML你不能“用”已经申报前的东西了。通过 交换函数声明并在inner之前声明innerinner很容易在你的情况下被修复。

    如果你想要例如声明两个相互递归的 函数,那么这不是一个选项。在这种情况下,您将不得不使用关键字and

  2. 悬而未决的柔性记录

    这是一个比较复杂一点。这是一个类型错误,并且与事实 有关,即元组在内部被表示为记录(我建议你去阅读关于它的 它)。因此,当你不提供足够的信息时,类型系统会投诉。

    我认为this QA解释得相当不错。总之,你不能有无限元组 ,因此你需要向类型系统清楚它包含了多少元素。这个 可以通过显式地注释函数声明来完成。 然而,一般而言,您应该尽可能经常使用模式匹配。

一般来说,你应该总是使用模式匹配,而不是选择的元组(#1,#2,...),或列表选择器(HD或TL)。你刚刚看到了为什么元组选择器可能是“坏”的,但是使用列表选择器而不测试列表是否为空将首先给出运行时错误(例外)。

在你的代码中加入这样的测试用例会“炸毁”它,并使其阅读变得混乱。但是如果你使用模式匹配,你会在你的函数定义中有一些很好的清除案例。 也往往你会倾向于编写更少的代码(在我看来)。

顺便说一句,你不需要在函数的单个参数周围放置括号,比如你对test函数的主要定义。

总之你的函数可以是这个样子:

fun test list = 
let 
    fun innerinner ((x1, x2)::xs,from) = 
     if x1 = from then true 
     else innerinner(xs,from) 
    | innerinner ([], from) = false 

    fun inner ((x1, x2)::xs) = innerinner(xs,x1) 
    | inner [] = false 
in 
    inner(list) 
end 
+1

或许'X1 =从否则别指望innerinner(XS,来自)';)引起的 –

+0

,但尽量不惹到很多与原来的功能和冒着失去我的观点:) –

相关问题