我是SML的新手。我编写了一个函数,它将2个int和一个元组列表作为输入。
fun move(x,y,mylist:(int * int)list): NOxNO =
let
val counter = ref y-1
in
if y=1 then (x,y)
else (
while !counter > 0 do (
if List.exists (fn s => s = (x,!counter)) mylist
then counter := !counter - 1
else break
);
if !counter = 0 then (x,y) else (x,y-1)
)
end
我可能有语法错误,因为我是初学者。该函数试图做的是:它将检查列表以找到其第一个元素为x且第二个元素从1到y-1变化的所有元组(这样的元组:(x,1)(x,2)。 ..(x,y-1))如果所有这些都存在于列表中,它将返回(x,y)else(x,y-1)。我用了一个while循环和一个计数器。计数器首先设置为y-1,而在while循环中如果找到(x,counter),计数器的值将减小。最后,如果counter = 0,则意味着我们找到了所有元组。运行程序后,我遇到了这个错误:
Caught Error ../compiler/TopLevel/interact/evalloop.sml:296.17-296.20
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
出了什么问题?
答案 0 :(得分:1)
ML中没有break
。你可能只想在那里写()
。此外,您需要在第3行ref
的参数周围找到问题。
答案 1 :(得分:1)
以下是一些反馈:
(错误)正如Andreas Rossberg所说,break
并不存在。但是如果使用()
,则循环在y > 1
时终止并且谓词的计算结果为false。你可能想要打破"打破"设置counter := 0
或counter := -1
,具体取决于您希望后续if !counter = 0 ...
做什么。
(错误)正如Andreas Rossberg所说,ref y-1
给出了以下类型错误:
! Toplevel input:
! val r = ref y-1;
! ^
! Type clash: expression of type
! int
! cannot have type
! int ref
这是因为函数应用程序(ref y
)比中缀运算符(y-1
)更紧密。您的意思是ref (y-1)
,因为您无法从参考中减去1.
这不是很容易理解或很强大。我试着以我能想到的最简单的方式运行它,
val test1 = move (1,1,[])
但这是一个奇怪的基本情况,不是由循环处理的。如果我稍微改变数字,
val test2 = move (5,6,[])
然后返回(5,6)
或(5,5)
,具体取决于您将break
更改为的内容。
根据您在代码下方的说明,这是一个建议的实现,虽然我还不完全确定我理解这个功能的使用:
(* verticalPointsExist (x, y, ps) checks that
* (x,1), (x,2), ..., (x,y-1) are all in ps. *)
fun verticalPointsExist (_, 0, _) = true
| verticalPointsExist (x, y, ps) = List.exists (fn p => (x,y) = p) ps
andalso verticalPointsExist (x, y - 1, ps)
fun move (x, y, ps) =
if verticalPointsExist (x, y, ps) then (x,y) else (x,y-1)
我做的考虑:
使用递归而不是迭代。
将检查部分拆分为辅助函数,因此move
不做两件事。
为函数提供良好的名称,以便代码更容易阅读。由于我不了解域名,并且我真的在猜测y
是否是某种垂直维度,因此可能还有更好的名称。 (verticalLineExists
?verticalPathClear
?)也许更通用的功能会有更好的名称,例如一个拿了两分,看到他们之间的界线清晰。