请问这个“计数”是突变吗?

时间:2019-03-15 01:25:36

标签: sml

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必须接收类型单元-> int函数作为第一个参数。我在调用该函数并得到0之后检查了计数,所以可以这样编写它,对吗?但是,它确实有点草率。

添加了上下文(函数g和使用的数据类型)。该功能count_wcs应该计算一个模式中出现的通配符模式的数量。

2 个答案:

答案 0 :(得分:0)

这不算是突变,但确实与您拥有它们时可能执行的操作类似,并且可能无法正常工作,具体取决于您正在执行的操作。突变需要引用,它们是用ref进行的,并用!取消了引用。因此,请远离这些。 :-)

您正在做的事情将无济于事:

let
  val count = 0
in
  ...
end

count绑定为0,但不会导致count具有任何其他值;我假设您最终希望增加count。如果它是一个引用val count = ref 0,则可以通过执行count := !count + 1来对其进行递增,但是由于不是,因此必须更改count某个函数的变量才能对其进行更改。 / p>

例如:

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作为输入或返回的函数会执行其他操作,例如从程序外部的源进行读取或写入。

我不会称其为马虎。有点奇怪,不知道上下文。

答案 1 :(得分:0)

在标准ML中识别突变非常容易-如果您不使用ref变量,而用:=为其赋予新值,则不是突变。
而且您不需要,所以您没有任何变异。

此外,您的功能可以简化为

fun count_wildcards p = g (fn () => 1) (fn _ => 1) p

这使得没有任何变异变得更加清晰。
(完全不清楚应该完成什么,因此无法确定您的解决方案是否正确。)