Вопрос по shadowing, f#, immutability – неизменный в F #

8

Я знаю, что переменные в F # являются неизменяемыми по умолчанию. Но, например, в F # интерактив:

  > let x = 4;;

val x : int = 4

> let x = 5;;

val x : int = 5

> x;;
val it : int = 5
> 

Итак, я назначаю 4 для x, затем 5 для x, и это меняется. Это правильно? Должно ли это дать какую-то ошибку или предупреждение? Или я просто не понимаю, как это работает?

Вопрос аналогичен, но не является дубликатом. Onorio Catenacci
@ Алекс: Вы можете найти ответы наthis question полезно. Daniel
Возможный дубликатstackoverflow.com/questions/2844047/… , Ответы там объясняют различие между привязкой переменной и назначением переменной. Heatsink

Ваш Ответ

4   ответа
3

иллюстрирующий идентификатор «затенение». (то есть скрывается) в F #:

let x = 0
do //introduce a new lexical scope
    let x = 1 //"shadow" (i.e. hide) the previous definition of x
    printfn "%i" x //prints 1
//return to outer lexical scope
printfn "%i" x //prints 0, proving that our outer definition of x was not mutated by our inner definition of x

Ваш пример на самом деле немного сложнее, потому что вы работаете в F # Interactive (FSI). FSI динамически испускает код, который выглядит примерно так в вашем примере:

module FSI_0001 =
    let x = 4;;

open FSI_0001 //x = 4 is now available in the top level scope
module FSI_0002 =
    let x = 5;;

open FSI_0002 //x = 5 is now available in the top level scope, hiding x = 4
module FSI_0003 =
    let it = x;;

open FSI_0003
//... subsequent interactions
4

xвы определяете новую переменную.

Следующий пример показывает, что есть две разные переменные. (Это также показывает, что вы можете «получить доступ» к старому x, если он находится в замыкании, используемом другой функцией):

let x = 5;;
let f y = y+x;;
f 10;;
let x = 0;;
f 10;;

доходность

>
val x : int = 5

>
val f : int -> int
> val it : int = 15
>
val x : int = 0

> val it : int = 15

как видите, оба вызова f используют первую переменнуюx, Определениеlet x = 0;; определяет новую переменнуюx, но не переопределяетf.

14

let x = 3, вы привязываете идентификаторx к стоимости3, Если вы делаете это второй раз в той же области, вы объявляете новый идентификатор, который скрывает предыдущий, так как он имеет то же имя.

Отключение значения в F # осуществляется через оператор деструктивного обновления,<-, Это не удастся для неизменных значений, т.е.

> let x = 3;;

val x : int = 3

> x <- 5;;

  x <- 5;;
  ^^^^^^

stdin(2,1): error FS0027: This value is not mutable

Чтобы объявить изменчивую переменную, добавьтеmutable послеlet:

let mutable x = 5;;

val mutable x : int = 5

> x <- 6;;
val it : unit = ()
> x;;
val it : int = 6

Но в чем разница между ними, спросите вы? Пример может быть достаточно:

let i = 0;
while i < 10 do
    let i = i + 1
    ()

Несмотря на внешность, это бесконечный цикл.i объявлено внутри цикла другоеi это скрывает внешнее. Внешний является неизменным, поэтому он всегда сохраняет свою ценность0 и цикл никогда не заканчивается. Правильный способ написать это с изменяемой переменной:

let mutable i = 0;
while i < 10 do
    i <- i + 1
    ()
5

x Например:

> let x = 4;;
val x : int = 4
> let x = "abc";;
val x : string = "abc"
>
@ Алекс видит мой ответ для объяснения разницы.
В чем разница между скрытым и неизменным? Означает ли это, что я все еще могу получить предыдущее значение х? Alexan

Похожие вопросы