fun count_wcs p =
let
val count = 0
in
g (fn () => count + 1) (fn y => 1) p
end
我正在做作业,我们不应该使用突变,这不会将价值重新分配给任何东西,但它感觉不对。请不要说这是怎样的正确方法,因为我应该弄明白这一点。
datatype pattern = Wildcard
| Variable of string
| UnitP
| ConstP of int
| TupleP of pattern list
| ConstructorP of string * pattern
fun g f1 f2 p =
let
val r = g f1 f2
in
case p of
Wildcard => f1 ()
| Variable x => f2 x
| TupleP ps => List.foldl (fn (p,i) => (r p) + i) 0 ps
| ConstructorP(_,p) => r p
| _ => 0
end
这个函数g必须接收一个类型unit - > int函数作为第一个参数。我调用函数后检查了计数并得到0,所以可以这样写,对吧?但是,它确实感到邋..
添加了上下文(函数g和使用的数据类型)。函数count_wcs应该计算通配符模式在模式中出现的数量。
这不算作突变,但它确实类似于你拥有它们时可能会做的事情,并且可能不会起作用,这取决于你正在做什么。突变需要参考,它们是用ref
制作的,并且用!
取消引用。所以只要远离那些。 :-)
你正在做一些没有什么好处的事情:
let
val count = 0
in
...
end
将count
绑定为0,但绝不会导致count
具有任何其他值;我认为你想最终让count
增加。如果它是一个引用,val count = ref 0
,你可以通过做count := !count + 1
来增加它,但是因为它不是,你必须使count
成为某个函数的变量才能改变它。
例如:
fun count_4s ([], count) = count
| count_4s (x::xs, count) = count_4s (xs, if x = 4 then count + 1 else count)
在每次调用中,count
都是常量,但在每个后续的递归调用中,它可能会递增。
这个函数g必须接收一个类型unit - > int函数作为第一个参数。
... g (fn () => count + 1) (fn y => 1) p ...
[...]但它确实感到草率。
假设g
的第一个参数没有副作用,并且不抛出异常并且不会永远循环,他们所能做的就是在每次调用时返回相同的内容。这使他们相当无聊。通常,作为输入或返回() : unit
的函数执行其他操作,例如从程序外部的源读取或写入。
我不会称之为草率。只是有点奇怪,不知道上下文。
在标准ML中识别突变非常容易 - 如果你不使用ref
变量并用:=
赋予它们新的值,那么它就不是突变。
你不这样做,所以你不会改变任何事情。
此外,您的功能可以简化为
fun count_wildcards p = g (fn () => 1) (fn _ => 1) p
这使得更清楚的是没有任何变异。 (它根本不清楚它应该完成什么,因此无法确定您的解决方案是否正确。)