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.