Является ли этот «счет» мутацией? - PullRequest
0 голосов
/ 15 марта 2019
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 должна получить функцию type -> int в качестве первого аргумента. Я проверил счетчик после того, как вызвал функцию и получил 0, так что можно написать это так, верно? Но, тем не менее, он чувствует себя небрежно.

Добавлен контекст (функция g и используемый тип данных). Предполагается, что функция count_wcs подсчитывает число шаблонов с подстановочными знаками в шаблоне.

Ответы [ 2 ]

0 голосов
/ 15 марта 2019

Очень просто идентифицировать мутацию в стандартном ML - если вы не используете ref переменные и присваиваете им новые значения с помощью :=, это не мутация.
А ты нет, поэтому ты ничего не мутируешь.

Кроме того, ваша функция может быть упрощена до

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

, что делает еще более ясным, что ничего не мутировало.
(Не совсем понятно, чего он должен достичь, поэтому невозможно сказать, правильно ли ваше решение.)

0 голосов
/ 15 марта 2019

Это не считается мутацией, но похоже на то, что вы могли бы сделать, если бы они у вас были, и, вероятно, не будет работать, в зависимости от того, что вы делаете.Мутации требуют ссылок , они сделаны с 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, делают что-то еще, например, читают или пишут из внешнего по отношению к программе источника.

Я бы не назвал это небрежным.Просто немного странно, не зная контекста.

...