TL; DR; let
не является назначением :=
. Пусть создает лексическую привязку, она не меняет никаких значений.
Прежде всего, вы путаете назначение с затенением.
Когда вы делаете
let x = 42
let x = 52
Вы не изменяете значение x
, вы привязываете переменную x
к новому значению 52
. В OCaml переменные являются чисто математическими, в том смысле, что они не действуют как ячейка памяти и не хранят ничего внутри себя. Это просто имена, которые используются программистом для ссылки на результат выражения.
Более того, вы даже можете привязать значения разных типов к одному и тому же идентификатору, например,
let x = 42
let x = "hello"
Теперь для создания ссылочной ячейки, в которой в качестве объекта, в котором вы можете сохранить значение, вы можете использовать функцию ref
. Он вернет коробку с местом, готовым для хранения
ваши ценности.
let x = ref 42
и для изменения значения, хранящегося в этой ячейке, необходимо использовать функцию (:=)
, например,
x := 56
Теперь значение, хранящееся в ячейке, на которую мы ссылаемся под именем x
, равно 56
, и для получения этого значения необходимо использовать функцию (!)
. Например, следующее удвоит значение, хранящееся в ячейке:
x := !x * !x
И вы можете сделать это в цикле,
for i = 0 to 9 do
x := !x * !x
done
Теперь давайте посмотрим, что вы делали :)
let primeFactors = ref Factorize.empty;;
Вы создаете ячейку с пустой картой и привязываете ее к имени primeFactors
. Значение, связанное с переменной primeFactors
, имеет тип Factorize.t ref
, то есть ссылку на Factorize.t
. Пока все хорошо!
let primeFactors = Factorize.add 1 (PF.add 1 3 PF.empty) primeFactors;;
Прежде всего, он не будет компилироваться, поскольку Factorize.add
ожидает Factorize.t
, но вы присваиваете ему значение типа Factorize.t ref
. Хотя это синтаксически правильно, это не действительная программа. Однако, даже если мы сделаем его типизированным, путем разыменования ячейки до ее значения с помощью функции (!)
let primeFactors = Factorize.add 1 (PF.add 1 3 PF.empty) !primeFactors
Это все равно будет неправильной программой (не все программы, которые правильно напечатаны, верны!).
Что мы здесь сделали, мы отскочили переменную primeFactors
до нового значения, которое представляет собой карту от значения 1
до (PF.add 1 3 PF.empty)
. Таким образом, мы изменили значение, связанное с переменной primeFactors
, а также ее тип. Что мы должны сделать, это
primeFactors := Factorize.add 1 (PF.add 1 3 PF.empty) !primeFactors