这个"count"是突变吗?
Does this "count" is a mutation?
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 函数作为第一个参数。我调用函数后查看了count,得到0,所以这样写是可以的吧?不过,还是觉得有点草率。
添加了上下文(函数 g 和使用的数据类型)。函数 count_wcs 应该计算通配符模式在模式中出现的次数。
这不算是突变,但它确实类似于如果你有它们可能会做的事情并且可能不会起作用,这取决于你在做什么。突变需要 references,它们是用 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
是常量,但在随后的每次递归调用中,它可能会递增。
This function g has to receive a type unit -> int function as first argument.
...
g (fn () => count + 1) (fn y => 1) p
...
[...] But still it does feel sloppy.
假设 g
的第一个参数没有副作用,不会抛出异常,也不会永远循环,它们所能做的就是 return 每次调用都做同样的事情。这让他们相当无聊。通常将函数作为输入或 return () : unit
执行其他操作,例如从程序外部的源读取或写入。
我不会说它马虎。有点奇怪,不知道上下文。
在标准 ML 中识别突变非常容易 - 如果您不使用 ref
变量并使用 :=
为它们分配新值,则它不是突变。
而你没有,所以你没有改变任何东西。
另外,你的函数可以简化为
fun count_wildcards p = g (fn () => 1) (fn _ => 1) p
这更清楚地表明没有任何变化。
(完全不清楚它应该完成什么,所以无法判断你的解决方案是否正确。)
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 函数作为第一个参数。我调用函数后查看了count,得到0,所以这样写是可以的吧?不过,还是觉得有点草率。
添加了上下文(函数 g 和使用的数据类型)。函数 count_wcs 应该计算通配符模式在模式中出现的次数。
这不算是突变,但它确实类似于如果你有它们可能会做的事情并且可能不会起作用,这取决于你在做什么。突变需要 references,它们是用 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
是常量,但在随后的每次递归调用中,它可能会递增。
This function g has to receive a type unit -> int function as first argument.
... g (fn () => count + 1) (fn y => 1) p ...
[...] But still it does feel sloppy.
假设 g
的第一个参数没有副作用,不会抛出异常,也不会永远循环,它们所能做的就是 return 每次调用都做同样的事情。这让他们相当无聊。通常将函数作为输入或 return () : unit
执行其他操作,例如从程序外部的源读取或写入。
我不会说它马虎。有点奇怪,不知道上下文。
在标准 ML 中识别突变非常容易 - 如果您不使用 ref
变量并使用 :=
为它们分配新值,则它不是突变。
而你没有,所以你没有改变任何东西。
另外,你的函数可以简化为
fun count_wildcards p = g (fn () => 1) (fn _ => 1) p
这更清楚地表明没有任何变化。
(完全不清楚它应该完成什么,所以无法判断你的解决方案是否正确。)