Непоследовательное поведение в массивах, созданных с помощью Array.create и Array.init - PullRequest
1 голос
/ 01 марта 2011
let a = Array.create 3 (Array.create 3 0)
let b = Array.init 3 (fun _ -> Array.init 3 (fun _ -> 0))

Оба этих массива имеют подпись int [] [] и начальное значение [| [| 0;0;0 |];[| 0;0;0 |];[| 0;0;0 |] |].

Однако:

a.[0].[0] <- 3
b.[0].[0] <- 3

дает разные результаты:

a: [|[|3; 0; 0|]; [|3; 0; 0|]; [|3; 0; 0|]|]
b: [|[|3; 0; 0|]; [|0; 0; 0|]; [|0; 0; 0|]|]

Результат для b - это результат, который я ожидал бы для обоих.

Мне кажется логичным, что идентичные подписи должны действовать одинаково.Может кто-нибудь сказать мне, что мне не хватает?

Ответы [ 3 ]

3 голосов
/ 01 марта 2011

Второй аргумент Array.create - это единственное значение, которое используется для инициализации каждого слота в массиве.То есть, подумайте о следующем:

let a =
    let v = Array.create 3 0
    Array.create 3 v

v сохраняется во всех 3 слотах a, поэтому изменение любого элемента в a влияет на все 3 слота.: Рассмотрим также логически эквивалентное:

let b =
    let v = Array.create 3 0
    Array.init 3 (fun _ -> v)
3 голосов
/ 01 марта 2011

Мне кажется логичным, что идентичные подписи должны действовать одинаково.Может кто-нибудь сказать мне, что мне не хватает?

Совместное использование

Использование Array.create приводит к массиву элементов, которые имеют одинаковое значение.Использование Array.init вызывает функцию для создания значения каждого элемента.

Следовательно, это выделяет два массива:

let a = Array.create 3 (Array.create 3 0)

, тогда как это выделяет четыре массива:

let b = Array.init 3 (fun _ -> Array.init 3 (fun _ -> 0))

Вы можете предпочесть это в терминах литералов массива, где первый эквивалентен:

let xs = [|0;0;0|]
[|xs;xs;xs|]

, а последний эквивалентен:

let xs = [|0;0;0|]
let ys = [|0;0;0|]
let zs = [|0;0;0|]
[|xs;ys;zs|]
3 голосов
/ 01 марта 2011

В первой версии (Array.create 3 0) оценивается ДО того, как он будет передан в качестве аргумента, поэтому все ячейки массива получают одинаковое значение.Массивы являются ссылочными типами, поэтому практически все ячейки одинаковы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...