这个"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

这更清楚地表明没有任何变化。
(完全不清楚它应该完成什么,所以无法判断你的解决方案是否正确。)