变量
在 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 提供了一个极其灵活的变量命名系统。变量名区分大小写,并且没有语义含义(也就是说,语言不会根据变量名称以不同的方式对待变量)。
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 编辑环境中,您可以通过键入反斜杠 LaTeX 符号名称后跟 Tab 键来键入许多 Unicode 数学符号。例如,变量名 δ
可以通过键入 \delta
-Tab 输入,甚至 α̂⁽²⁾
可以通过 \alpha
-Tab-\hat
- Tab-\^(2)
-Tab 输入。(如果您在某个地方(例如,在其他人的代码中)发现了一个您不知道如何键入的符号,REPL 帮助会告诉您:只需键入 ?
,然后粘贴该符号。)
如果需要,Julia 甚至允许您重新定义内置常量和函数(尽管不建议这样做,以避免潜在的混淆)
julia> pi = 3
3
julia> pi
3
julia> sqrt = 4
4
但是,如果您尝试重新定义一个已经在使用的内置常量或函数,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
允许的变量名
变量名必须以字母 (A-Z 或 a-z)、下划线或大于 00A0 的 Unicode 代码点的子集开头;特别是,Unicode 字符类别 Lu/Ll/Lt/Lm/Lo/Nl(字母)、Sc/So(货币和其他符号)以及其他一些类似字母的字符(例如,Sm 数学符号的子集)是允许的。后续字符还可以包括 ! 和数字 (0-9 和 Nd/No 类别的其他字符),以及其他 Unicode 代码点:变音符号和其他修饰标记 (Mn/Mc/Me/Sk 类别),一些标点连接符 (Pc 类别),撇号,以及其他一些字符。
像 +
这样的运算符也是有效的标识符,但会被特殊解析。在某些上下文中,运算符可以像变量一样使用;例如 (+)
指的是加法函数,而 (+) = f
将重新分配它。大多数 Unicode 中缀运算符(Sm 类别),例如 ⊕
,都被解析为中缀运算符,并且可用于用户定义的方法(例如,您可以使用 const ⊗ = kron
将 ⊗
定义为中缀克罗内克积)。运算符也可以后缀修饰标记、撇号以及下标/上标,例如 +̂ₐ″
被解析为与 +
具有相同优先级的中缀运算符。以下标/上标字母结尾的运算符与后续变量名之间需要一个空格。例如,如果 +ᵃ
是一个运算符,那么 +ᵃx
必须写成 +ᵃ x
以将其与 + ᵃx
区分,其中 ᵃx
是变量名。
一类特殊的变量名是仅包含下划线的变量名。这些标识符只能赋值,而这些值会被立即丢弃,因此不能用于为其他变量赋值(即,它们不能用作rvalues
)或以任何方式使用分配给它们的最后一个值。
julia> x, ___ = size([2 2; 1 1])
(2, 2)
julia> y = ___
ERROR: syntax: all-underscore identifier used as rvalue
julia> println(___)
ERROR: syntax: all-underscore identifier used as rvalue
变量唯一明确禁止的名称是内置关键字的名称
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) 和希腊连字符 ·
(U+0387) 都被视为数学点运算符 ⋅
(U+22C5)。减号 −
(U+2212) 被视为等价于连字符减号 -
(U+002D)。
赋值表达式和赋值与变异
赋值 variable = value
将名称 variable
“绑定”到右侧计算的 value
,并且整个赋值被 Julia 视为等于右侧 value
的表达式。这意味着赋值可以链接(将相同的 value
分配给多个变量,使用 variable1 = variable2 = value
)或用于其他表达式,这也是为什么它们的结果在 REPL 中显示为右侧的值。(一般来说,REPL 显示您评估的任何表达式的值。)例如,这里 b = 2+2
的值 4
用于另一个算术运算和赋值
julia> a = (b = 2+2) + 3
7
julia> a
7
julia> b
4
一个常见的混淆是赋值(为值赋予新的“名称”) 和变异(更改值)之间的区别。如果您运行 a = 2
,然后运行 a = 3
,则您已将“名称” a
更改为引用一个新的值 3
……您没有更改数字 2
,因此 2+2
仍然会得到 4
而不是 6
!在处理像数组这样的可变类型时,这种区别会变得更加清晰,数组的内容可以被更改
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
也就是说,a[i] = value
(setindex!
的别名)改变内存中现有数组对象,可以通过 a
或 b
访问。随后设置 a = 3.14159
不会更改此数组,它只是将 a
绑定到不同的对象;数组仍然可以通过 b
访问。更改现有对象的另一种常用语法是 a.field = value
(setproperty!
的别名),它可以用来更改mutable struct
。
当您在 Julia 中调用函数时,它的行为就像您分配了参数值到对应于函数参数的新变量名,如参数传递行为中所述。(根据约定,改变一个或多个参数的函数的名称以 !
结尾。)
风格约定
虽然 Julia 对有效名称的限制很少,但采用以下约定变得很有用
- 变量名使用小写字母。
- 单词分隔可以使用下划线 (
'_'
) 表示,但除非名称难以阅读,否则不鼓励使用下划线。 Type
和Module
的名称以大写字母开头,单词分隔使用大驼峰命名法而不是下划线。function
和macro
的名称使用小写字母,不使用下划线。- 写入其参数的函数的名称以
!
结尾。这些有时被称为“变异”或“就地”函数,因为它们旨在在函数调用后在其参数中产生更改,而不仅仅是返回值。
有关风格约定的更多信息,请参阅 风格指南。