Variables
Переменная в Julia — это имя, связанное (или привязанное) к значению. Это полезно, когда вы хотите сохранить значение (которое вы получили после некоторых математических операций, например) для последующего использования. Например:
# Assign the value 10 to the variable x
julia> x = 10
10
# Doing math with x's value
julia> x + 1
11
# Reassign x's value
julia> x = 1 + 1
2
# You can assign values of other types, like strings of text
julia> x = "Hello World!"
"Hello World!"
Джулия предоставляет чрезвычайно гибкую систему для именования переменных. Имена переменных чувствительны к регистру и не имеют семантического значения (то есть язык не будет рассматривать переменные по-разному в зависимости от их имен).
julia> x = 1.0
1.0
julia> y = -3
-3
julia> Z = "My string"
"My string"
julia> customary_phrase = "Hello world!"
"Hello world!"
julia> UniversalDeclarationOfHumanRightsStart = "人人生而自由,在尊严和权利上一律平等。"
"人人生而自由,在尊严和权利上一律平等。"
Разрешены имена Unicode (в кодировке UTF-8):
julia> δ = 0.00001
1.0e-5
julia> 안녕하세요 = "Hello"
"Hello"
В Julia REPL и в нескольких других средах редактирования Julia вы можете вводить многие символы математической нотации Unicode, набирая имя символа LaTeX с обратным слэшем, а затем нажимая табуляцию. Например, имя переменной δ
можно ввести, набрав \delta
-tab, или даже α̂⁽²⁾
с помощью \alpha
-tab-\hat
-tab-\^(2)
-tab. (Если вы найдете символ где-то, например, в коде другого человека, который не знаете, как ввести, справка REPL подскажет вам: просто введите ?
, а затем вставьте символ.)
Julia даже позволит вам затенять существующие экспортированные константы и функции локальными (хотя это не рекомендуется, чтобы избежать потенциальных путаниц):
julia> pi = 3
3
julia> pi
3
julia> sqrt = 4
4
julia> length() = 5
length (generic function with 1 method)
julia> Base.length
length (generic function with 79 methods)
Однако, если вы попытаетесь переопределить встро常ую константу или функцию, которая уже используется, Julia выдаст вам ошибку:
julia> pi
π = 3.1415926535897...
julia> pi = 3
ERROR: cannot assign a value to imported variable Base.pi from module Main
julia> sqrt(100)
10.0
julia> sqrt = 4
ERROR: cannot assign a value to imported variable Base.sqrt from module Main
Allowed Variable Names
Имена переменных должны начинаться с буквы (A-Z или a-z), подчеркивания или подмножества кодовых точек Юникода, больших чем 00A0; в частности, Unicode character categories Lu/Ll/Lt/Lm/Lo/Nl (буквы), Sc/So (валютные и другие символы) и несколько других буквоподобных символов (например, подмножество математических символов Sm) разрешены. Последующие символы также могут включать ! и цифры (0-9 и другие символы в категориях Nd/No), а также другие кодовые точки Юникода: диакритики и другие модифицирующие знаки (категории Mn/Mc/Me/Sk), некоторые знаки препинания (категория Pc), апострофы и несколько других символов.
Операторы, такие как +
, также являются допустимыми идентификаторами, но обрабатываются особым образом. В некоторых контекстах операторы могут использоваться так же, как переменные; например, (+)
относится к функции сложения, а (+) = f
переназначит её. Большинство операторов Юникода в инфиксной категории (в категории Sm), таких как ⊕
, обрабатываются как инфиксные операторы и доступны для методов, определяемых пользователем (например, вы можете использовать const ⊗ = kron
, чтобы определить ⊗
как инфиксный произведение Кронекера). Операторы также могут иметь суффиксы с модифицирующими знаками, апострофами и нижними/верхними индексами, например, +̂ₐ″
обрабатывается как инфиксный оператор с такой же приоритетностью, как +
. Пробел требуется между оператором, который заканчивается на букву нижнего/верхнего индекса, и последующим именем переменной. Например, если +ᵃ
является оператором, то +ᵃx
должно быть записано как +ᵃ x
, чтобы отличить его от + ᵃx
, где ᵃx
является именем переменной.
Определенный класс имен переменных - это те, которые содержат только символы подчеркивания. Эти идентификаторы являются только для записи. То есть, им можно только присваивать значения, которые немедленно отбрасываются, и их значения нельзя использовать никаким образом.
julia> x, ___ = size([2 2; 1 1])
(2, 2)
julia> y = ___
ERROR: syntax: all-underscore identifiers are write-only and their values cannot be used in expressions
julia> println(___)
ERROR: syntax: all-underscore identifiers are write-only and their values cannot be used in expressions
The only explicitly disallowed names for variables are the names of the built-in Keywords:
julia> else = false
ERROR: syntax: unexpected "else"
julia> try = "No"
ERROR: syntax: unexpected "="
Некоторые символы Unicode считаются эквивалентными в идентификаторах. Разные способы ввода комбинирующих символов Unicode (например, акценты) рассматриваются как эквивалентные (в частности, идентификаторы Julia — это NFC. Julia также включает несколько нестандартных эквивалентов для символов, которые визуально похожи и легко вводятся некоторыми методами ввода. Символы Unicode ɛ
(U+025B: латинская строчная буква открытое e) и µ
(U+00B5: микросигн) рассматриваются как эквивалентные соответствующим греческим буквам. Средняя точка ·
(U+00B7) и греческий interpunct ·
(U+0387) оба рассматриваются как математический оператор точки ⋅
(U+22C5). Знак минус −
(U+2212) рассматривается как эквивалентный знаку дефиса -
(U+002D).
Assignment expressions and assignment versus mutation
Присваивание variable = value
"связывает" имя variable
с value
, вычисленным с правой стороны, и всё присваивание рассматривается Julia как выражение, равное правой стороне value
. Это означает, что присваивания могут быть связаны (то же value
присваивается нескольким переменным с помощью variable1 = variable2 = value
) или использоваться в других выражениях, и именно поэтому их результат отображается в REPL как значение правой стороны. (В общем, REPL отображает значение любого выражения, которое вы оцениваете.) Например, здесь значение 4
из b = 2+2
используется в другой арифметической операции и присваивании:
julia> a = (b = 2+2) + 3
7
julia> a
7
julia> b
4
Общее недоразумение заключается в различии между присвоением (давать новое "имя" значению) и мутацией (изменение значения). Если вы выполните a = 2
, а затем a = 3
, вы изменили "имя" a
, чтобы оно ссылалось на новое значение 3
… вы не изменили число 2
, поэтому 2+2
все равно даст 4
, а не 6
! Это различие становится более ясным при работе с изменяемыми типами, такими как arrays, содержимое которых может быть изменено:
julia> a = [1,2,3] # an array of 3 integers
3-element Vector{Int64}:
1
2
3
julia> b = a # both b and a are names for the same array!
3-element Vector{Int64}:
1
2
3
Здесь строка b = a
не создает копию массива a
, она просто связывает имя b
с тем же массивом a
: оба b
и a
"указывают" на один массив [1,2,3]
в памяти. В отличие от этого, присваивание a[i] = value
изменяет содержимое массива, и измененный массив будет виден через оба имени a
и b
:
julia> a[1] = 42 # change the first element
42
julia> a = 3.14159 # a is now the name of a different object
3.14159
julia> b # b refers to the original array object, which has been mutated
3-element Vector{Int64}:
42
2
3
That is, a[i] = value
(an alias for setindex!
) mutates an existing array object in memory, accessible via either a
or b
. Subsequently setting a = 3.14159
does not change this array, it simply binds a
to a different object; the array is still accessible via b
. Another common syntax to mutate an existing object is a.field = value
(an alias for setproperty!
), which can be used to change a mutable struct
. There is also mutation via dot assignment, for example b .= 5:7
(which mutates our array b
in-place to contain [5,6,7]
), as part of Julia's vectorized "dot" syntax.
Когда вы вызываете function в Julia, он ведет себя так, как будто вы присвоили значения аргументов новым именам переменных, соответствующим аргументам функции, как обсуждалось в Argument-Passing Behavior. (Под convention, функции, которые изменяют один или несколько своих аргументов, имеют имена, заканчивающиеся на !
.)
Stylistic Conventions
Хотя Julia накладывает немного ограничений на допустимые имена, стало полезным принять следующие соглашения:
- Названия переменных написаны строчными буквами.
- Разделение слов может быть обозначено с помощью подчеркиваний (
'_'
), но использование подчеркиваний не рекомендуется, если только имя не будет трудно читать в противном случае. - Названия
Type
иModule
начинаются с заглавной буквы, а разделение слов отображается с помощью верхнего верблюжьего регистра вместо подчеркиваний. - Имена
function
иmacro
написаны строчными буквами, без подчеркиваний. - Функции, которые записывают в свои аргументы, имеют имена, заканчивающиеся на
!
. Их иногда называют "мутирующими" или "in-place" функциями, потому что они предназначены для внесения изменений в свои аргументы после вызова функции, а не просто для возврата значения.
Для получения дополнительной информации о стилистических конвенциях см. Style Guide.