Короткий ответ: это не из-за fsi
, это потому, что mutable является глобальным.
Длинный ответ:
Для нормального (не изменяемый) захвата, реализация мудр захваченное значение копируется в объект функции, так, что если вернуть эту функцию и использовать его за пределами области, в которой он был определен, все работает нормально.
let pureAddOne() =
let x = 1
let f y = x + y // the value 1 is copied into the function object
f
let g = pureAddOne()
g 3 // x is now out of scope, but its value has been copied and can be used
С другой стороны, для того, чтобы захватить изменяемые, захват должно быть сделано по ссылке, иначе вы не сможете изменить его. Но это невозможно, поскольку в ранее упомянутом случае, когда замыкание возвращается и используется вне его области определения, изменчивый также выходит за рамки и потенциально освобождается. Это является причиной первоначального ограничения.
let mutableAddOne() =
let mutable x = 1
let f y = x <- x + y // x would be referenced, not copied
f
let g = mutableAddOne()
g 3 // x is now out of scope, so the reference is invalid!
// mutableAddOne doesn't compile, because if it did, then this would fail.
Однако, если изменяемые является глобальным, то не существует такого масштаба проблема, и компилятор принимает его. Это не только fsi
; если вы пытаетесь собрать следующую программу с fsc
, он работает:
module Working
let mutable x = 1 // x is global, so it never goes out of scope
let mutableAddOne() =
let f y = x <- x + y // referencing a global. No problem!
f
let g = mutableAddOne()
g 3 // works as expected!
В заключении, как сказал kwingho, если вы хотите иметь замыкание, которое захватывает локальные изменяемые значения используйте ref
. Они распределены по кучам (в отличие от локального измененного стека), поэтому, если замыкание содержит ссылку на него, оно не будет освобождено.
Привет, он не генерирует замыкание, когда вы просто запускаете код body.use: пусть x = ref 0; пусть incrementX() = x: =! x + 1; см. Закрытие: http: //msdn.microsoft.com/en-us/library/dd233186.aspx – kwingho
Обратите внимание, что компилятор также не возражает против тела функция сама по себе. –