Подтвердить что ты не робот

Создание копий в Julia with = operator

Когда я создаю некоторый массив A и назначаю его B

A = [1:10]
B = A

Я могу изменить A, а изменение отражает в B

A[1] = 42
# B[1] is now 42

Но если я делаю это со скалярными переменными, изменение не распространяется:

a = 1
b = a
a = 2
# b remains being 1

Я могу даже смешивать вещи и преобразовывать вектор в скаляр, а изменение не распространяется:

A = [1:10]
B = A
A = 0
# B remains being 1,2,...,10

Что именно делает оператор =? Когда я хочу скопировать переменные и изменить старые, сохраняя целостность новых переменных, когда следует использовать b = copy(a) только для b=a?

4b9b3361

Ответ 1

Путаница проистекает из этого: присваивание и мутация - это не одно и то же.

Назначение. Назначение выглядит как x = ... - то, что осталось от =, является идентификатором, то есть именем переменной. Изменения присваивания, к которым относится переменная x (это называется привязкой к переменной). Он не мутирует никаких объектов вообще.

Мутация. Есть два типичных способа изменить что-то в Julia: x.f = ... - то, что осталось от =, является выражением доступа к полю; x[i] = ... - то, что осталось от =, является индексирующим выражением. В настоящее время полевая мутация является фундаментальной - этот синтаксис может означать только то, что вы изменяете структуру, изменяя ее поле. Это может измениться. Синтаксис мутации массива не является фундаментальным - x[i] = y означает setindex!(x, y, i), и вы можете либо добавить методы в setindex! или локально изменить какую общую функцию setindex!. Фактическое назначение массива - встроенная функция, реализованная в C (и для которой мы знаем, как создать соответствующий код LLVM).

Мутация изменяет значения объектов; он не меняет никаких привязок переменных. После выполнения любого из вышеперечисленного, переменная x все еще относится к тому же объекту, который он делал ранее; однако этот объект может иметь различное содержимое. В частности, если этот объект доступен из какой-либо другой области действия - скажем, функция, вызывающая одну, выполняющую мутацию, - тогда там будет видно измененное значение. Но никаких привязок не изменилось - все привязки во всех областях все еще относятся к тем же объектам.

Вы заметите, что в этом объяснении я ни разу не говорил о изменчивости или неизменности. Это связано с тем, что он не имеет ничего общего с этим: изменяемые и неизменяемые объекты имеют точно такую ​​же семантику, когда речь идет о назначении, передаче аргументов и т.д. Единственное отличие состоит в том, что если вы попытаетесь сделать x.f = ..., когда x является неизменным, вы получите сообщение об ошибке.

Ответ 2

Такое поведение похоже на Java. A и B - это переменные, которые могут содержать либо "простой" тип данных, как целое число, float и т.д., Или ссылки (так называемые указатели) на более сложную структуру данных. В отличие от Java, Julia обрабатывает многие не абстрактные типы как "простые" данные.

Вы можете проверить с помощью isbits(A), имеет ли ваша переменная A значение бит или содержит ссылку на другой объект данных. В первом случае B=A скопирует каждый бит из A в новое выделение памяти для B, в противном случае будет скопирована только ссылка на объект.

Также играйте с pointer_from_objref(A).