AnyMath 文档
Notebook

朱莉娅:语言特征

本文是Julia语言基础知识的简明指南,基于"最小理论-最大实践"的原则。"所有的材料都是围绕代码组织的:每个部分都用直接工作的例子说明,文本解释保持在必要的最低限度。 这种方法可以让你快速沉浸在语法中,看到典型的结构,并立即开始试验,而不会被冗长的描述分散注意力。 Julia以其表现力和速度而闻名,最好通过live code了解她—这正是拟议选择提供的机会。 在这里,您将找到使用变量、数据类型、集合、函数、多个调度和其他关键语言特性的示例。

变量和赋值

分配整数

In [ ]:
x = 100              
Out[0]:
100

在表达式中使用变量

In [ ]:
x * 5              
Out[0]:
500

重新分配变量

In [ ]:
x = 10 + 10    
Out[0]:
20

Julia是一种动态类型语言,变量可以改变其类型。

In [ ]:
x = "Hello World!"   
Out[0]:
"Hello World!"

赋值返回右侧的值

In [ ]:
b=4
a = (b = 2 + 2) * 5
Out[0]:
20

赋值链也是可能的,在下面的示例中,所有三个变量都被赋值为10

In [ ]:
x = y = z = 10
Out[0]:
10

变量名支持Unicode

In [ ]:
x1=100             
 = "点"         
δ = 0.001            
Out[0]:
0.001

案例依赖性,myvar和myVar是两个不同的变量。

In [ ]:
myvar = 1
Out[0]:
1
In [ ]:
MyVar = 2
Out[0]:
2

变量的禁止名称:

*不能以数字开头:1x=100
*语言函数不能用作变量:baremodule,begin,break,catch,const,continue,do,elseif,end,export,false,finally,for,function,global,if,import,let,local,macro,module,quote,return,struct,true,try,using,while

可变类型(数组)的行为
重要提示:赋值不会为可变对象创建副本!

In [ ]:
a = [1, 2, 3] 
Out[0]:
3-element Vector{Int64}:
 1
 2
 3

b引用与a相同的数组

In [ ]:
b = a 
Out[0]:
3-element Vector{Int64}:
 1
 2
 3

我们通过a变异数组并输出b,b也看到了变化!

In [ ]:
a[1] = 42
b
Out[0]:
3-element Vector{Int64}:
 42
  2
  3

重新连接数组

In [ ]:
a = [1, 2, 3]
b = a
a = 3.14159
b
Out[0]:
3-element Vector{Int64}:
 1
 2
 3
In [ ]:
a = [1, 2, 3]
b .= a
a = [1, 2, 30] 
b
Out[0]:
3-element Vector{Int64}:
 1
 2
 3

数据类型和注释

自动类型检测,Float64是浮点数的默认类型

In [ ]:
x = -2.0
typeof(x)
Out[0]:
Float64

Int64是整数的默认类型。

In [ ]:
x = 2
typeof(x)
Out[0]:
Int64
In [ ]:
x = -2
typeof(x)
Out[0]:
Int64

没有复数的域错误

In [ ]:
# sqrt(x) #ERROR

复杂类型的显式指示。 为复杂类型添加0im

In [ ]:
x = -2.0 + 0im        
typeof(x) 
Out[0]:
ComplexF64 (alias for Complex{Float64})
In [ ]:
sqrt(x)              
Out[0]:
0.0 + 1.4142135623730951im

类型的注释运算符 :: 检查语句"是否是给定类型的实例"。

In [ ]:
(2 + 2)::Int 
Out[0]:
4
In [ ]:
# (2 + 2)::AbstractFloat #ERROR
In [ ]:
(2.0 + 2.0)::AbstractFloat
Out[0]:
4.0

类型稳定性检查

In [ ]:
function fast_sum(arr::Vector{Int})
    s = 0
    for x in arr
        s += x
    end
    return s
end
@code_warntype fast_sum([1,2,3])   # 应显示Any::Any(或特定类型)
# @code_native fast_sum([1,2,3])#汇编代码
MethodInstance for fast_sum(::Vector{Int64})
  from fast_sum(arr::Vector{Int64}) @ Main In[57]:1
Arguments
  #self#::Core.Const(Main.fast_sum)
  arr::Vector{Int64}
Locals
  @_3::Union{Nothing, Tuple{Int64, Int64}}
  s::Int64
  x::Int64
Body::Int64
1 ─       (s = 0)
 %2  = arr::Vector{Int64}
       (@_3 = Base.iterate(%2))
 %4  = @_3::Union{Nothing, Tuple{Int64, Int64}}
 %5  = (%4 === nothing)::Bool
 %6  = Base.not_int(%5)::Bool
└──       goto #4 if not %6
2 ┄ %8  = @_3::Tuple{Int64, Int64}
       (x = Core.getfield(%8, 1))
 %10 = Core.getfield(%8, 2)::Int64
 %11 = Main.:+::Core.Const(+)
 %12 = s::Int64
 %13 = x::Int64
       (s = (%11)(%12, %13))
       (@_3 = Base.iterate(%2, %10))
 %16 = @_3::Union{Nothing, Tuple{Int64, Int64}}
 %17 = (%16 === nothing)::Bool
 %18 = Base.not_int(%17)::Bool
└──       goto #4 if not %18
3 ─       goto #2
4 ┄ %21 = s::Int64
└──       return %21

声明变量类型

In [ ]:
x = Complex(-2)   
typeof(x)                  
Out[0]:
Complex{Int64}
In [ ]:
sqrt(x)
Out[0]:
0.0 + 1.4142135623730951im

类型的层次结构:

*Int64<:Integer<:Real<:Number<:Any
*Float64<:AbstractFloat<:Real<:Number<:Any

参数类型

二维Int64阵列

In [ ]:
Array{Int64, 2}
Out[0]:
Matrix{Int64} (alias for Array{Int64, 2})

Float64矢量(一维)

In [ ]:
Array{Float64, 1}
Out[0]:
Vector{Float64} (alias for Array{Float64, 1})

整数

系统类型的别名:

Int-Int64整数

UInt-UInt64无符号整数

In [ ]:
10 
Out[0]:
10

前导零不使数字八进制。

In [ ]:
0123456789
Out[0]:
123456789

支持大数自动位深度扩展。

In [ ]:
typeof(10000000000000000000)
Out[0]:
Int128
In [ ]:
typeof(1000000000000000000000000000000000000000)
Out[0]:
BigInt

无符号整数(十六进制),大小由位数自动决定。

In [ ]:
x = 0x1              # UInt8(1字节)
x = 0x123            # UInt16(2字节)
x = 0x1234567        # UInt32(4字节)
x = 0x123456789abcdef # UInt64(8字节)
x = 0x11112222333344445555666677778888  # UInt128(16字节)
Out[0]:
0x11112222333344445555666677778888
In [ ]:
typeof(0xfffffffffffffffffffffffffffffffff)
Out[0]:
BigInt

Julia默认不检查溢出,这是一种周期性行为。

In [ ]:
x = typemax(Int64)
Out[0]:
9223372036854775807
In [ ]:
x + 1 # 溢出!
Out[0]:
-9223372036854775808
In [ ]:
x + 1 == typemin(Int64) 
Out[0]:
true
In [ ]:
x = typemax(UInt64) 
x + 1  
Out[0]:
0x0000000000000000
In [ ]:
x + 1 == typemin(UInt64) 
Out[0]:
true

BigInt溢流解决方案

In [ ]:
10^19
Out[0]:
-8446744073709551616
In [ ]:
BigInt(10)^19
Out[0]:
10000000000000000000

浮点数。

In [ ]:
1.0                  # 标准条目
1.                   # 您可以省略点后的零。
0.5                  # 一个常规分数
.5                   # 您可以省略点之前的零。
-1.23                # 否
Out[0]:
-1.23

电子符号

In [ ]:
1e10                 # 1.0e10 = 1.0 × 10^10
2.5e-4               # 0.00025
Out[0]:
0.00025

Float32可以使用后缀f指定

In [ ]:
x = 0.5f0
typeof(x)          
Out[0]:
Float32
In [ ]:
2.5f-4
Out[0]:
0.00025f0

Float16是通过显式类型赋值实现的

In [ ]:
Float16(4.)
Out[0]:
Float16(4.0)

位表示。

In [ ]:
0.0 == -0.0
Out[0]:
true
In [ ]:
bitstring(0.0)
Out[0]:
"0000000000000000000000000000000000000000000000000000000000000000"
In [ ]:
bitstring(-0.0)  
Out[0]:
"1000000000000000000000000000000000000000000000000000000000000000"

BigFloat的任意精度

In [ ]:
BigFloat(2.0)^100 / 4
Out[0]:
3.16912650057057350374175801344e+29

特殊值

*-Inf(负无穷大)
*Inf(正无穷大)

In [ ]:
typemin(Float64)
Out[0]:
-Inf
In [ ]:
typemax(Float64) 
Out[0]:
Inf

无穷无尽的算术

In [ ]:
1 / 0                # Inf
-5 / 0               # -Inf
0 / 0                # NaN
1 / Inf              # 0.0
1 / -Inf             # -0.0
Inf - Inf            # NaN
0 * Inf              # NaN
Out[0]:
NaN

南不等于自己

In [ ]:
NaN == NaN           # false!
NaN != NaN           # true
NaN < NaN            # false
NaN > NaN            # false
Out[0]:
false

为了进行正确的比较,它被使用 isequal

In [ ]:
isequal(NaN, NaN)            # true-NaN被认为是相等的
Out[0]:
true
In [ ]:
isequal([1 NaN], [1 NaN])    # true-比较数组
Out[0]:
true
In [ ]:
isequal(-0.0, 0.0)           # false-区分有符号的零!
Out[0]:
false

机器epsilon

In [ ]:
eps(Float64)
Out[0]:
2.220446049250313e-16
In [ ]:
eps(1000.) 
Out[0]:
1.1368683772161603e-13
In [ ]:
eps(0.0) # 5.0e-324-最小正数
Out[0]:
5.0e-324

字符串和符号

线条

In [ ]:
s = "Hello!"
Out[0]:
"Hello!"

插值法

In [ ]:
"插值:$s" 
Out[0]:
"Интерполяция: Hello!"
In [ ]:
"表达式:∞(2+2)" 
Out[0]:
"Выражение: 4"

字符串(不处理转义)

In [ ]:
"没有\n插值的字符串"
Out[0]:
"Строка без \n интерполяции"

多线线路

In [ ]:
multiline = """

    带连字符
    """
Out[0]:
"Строка\nс переносами\n"

串联和重复

In [ ]:
"Hello" * " " * "World" 
Out[0]:
"Hello World"
In [ ]:
"Hi"^3 
Out[0]:
"HiHiHi"

字符(Char)

In [ ]:
c = 'a' 
typeof(c)                   
Out[0]:
Char
Warning: detected a stack overflow; program state may be corrupted, so further execution might be unreliable.
In [ ]:
c+1
Out[0]:
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)

符号(Symbol)

In [ ]:
sym = :my_symbol
typeof(sym)
Out[0]:
Symbol

它们通常用作字典键。

In [ ]:
Dict(:key => "value")
Out[0]:
Dict{Symbol, String} with 1 entry:
  :key => "value"

结构和抽象类型

它们用于创建自定义类型和组织层次结构。

In [ ]:
# 不可变结构
struct Point
    x::Float64
    y::Float64
end
In [ ]:
# 可变结构
mutable struct MPoint
    x::Float64
    y::Float64
end
In [ ]:
# 抽象类型
abstract type Shape end
struct Circle <: Shape
    radius::Float64
end
struct Rectangle <: Shape
    width::Float64
    height::Float64
end
In [ ]:
# 构造函数
Point(3.0, 4.0)            # 自动的
Out[0]:
Point(3.0, 4.0)

馆藏资料

元组是一种不可变的结构,比数组工作得更快。

In [ ]:
t = (1, 2, 3)
t[1]
Out[0]:
1
In [ ]:
# t[1] = 5 #ERROR

解包元组

In [ ]:
a, b, c = t
Out[0]:
(1, 2, 3)

字典(字典)

In [ ]:
d = Dict("a" => 1, "b" => 2)
Out[0]:
Dict{String, Int64} with 2 entries:
  "b" => 2
  "a" => 1
In [ ]:
d["a"]
Out[0]:
1
In [ ]:
d["c"] = 3   
Out[0]:
3
In [ ]:
haskey(d, "a")
Out[0]:
true
In [ ]:
keys(d), values(d)
Out[0]:
(["c", "b", "a"], [3, 2, 1])

集(Set)-删除重复项

In [ ]:
s = Set([1, 2, 2, 3]) 
Out[0]:
Set{Int64} with 3 elements:
  2
  3
  1
In [ ]:
1  s 
Out[0]:
true
In [ ]:
push!(s, 4)
Out[0]:
Set{Int64} with 4 elements:
  4
  2
  3
  1

失踪,一无所有

nothing是null/None的模拟(值缺失)

In [ ]:
function f()
    return nothing
end
f() === nothing
Out[0]:
true

missing-缺失数据(分布在计算中)

In [ ]:
1 + missing
Out[0]:
missing
In [ ]:
# mean([1, missing, 3]) #ERROR

支票

In [ ]:
ismissing(missing)      
Out[0]:
true
In [ ]:
isnothing(nothing)     
Out[0]:
true

基本运算符

算术运算符

In [ ]:
1 + 10 - 5           # 加法和减法
5 * 20 / 10          # 乘法和除法
20 \ 10              # 反向除法(10/20)
3^3                  # 指数化
5.5 % -2             # 其余的除法
Out[0]:
1.5

隐式乘法(数值因子),Julia允许你写2x而不是2*x

In [ ]:
x = 3
2x                   # 隐式乘法
2(x + 1)             # 它也适用于括号。
2x^2                 # 优先级:高于隐式乘法
2^2x                 
Out[0]:
64

逻辑运算符

In [ ]:
!true                # 虚假否定
!false               # true
true && true         # 真-逻辑和(缩写)
true && false        # false
false && false       # false
true || true         # true-逻辑或(缩写)
true || false        # true
false || false       # false
Out[0]:
false

按位运算符

In [ ]:
~100                 # -101-按位表示法(反转)
121 & 232            # 104-按位和
121 | 232            # 249-按位或
121  232            # 145位XOR(Unicode字符!)
xor(121, 232)        # 145-通过功能相同
~UInt32(121)         # 0xffffff86-保型反演
~UInt8(121)          # 0x86也是UInt8结果。
Out[0]:
0x86

更新运算符(就地)

In [ ]:
x = 25
x += 25              # x = x + 25
x *= 2               # x = x * 2
x /= 4               # x = x / 4
x ^= 2               # x = x^2
Out[0]:
625.0

更新运算符可以更改数据类型。

In [ ]:
x = 0x01             
typeof(x)                     
Out[0]:
UInt8
In [ ]:
x *= 2               
typeof(x)   
Out[0]:
Int64

矢量化

创建矩阵

In [ ]:
x = [1 2 3 4 5; 6 7 8 9 10]
Out[0]:
2×5 Matrix{Int64}:
 1  2  3  4   5
 6  7  8  9  10

操作员 . 逐元素应用操作,以及此运算符创建一个新矩阵。

In [ ]:
x.^2
Out[0]:
2×5 Matrix{Int64}:
  1   4   9  16   25
 36  49  64  81  100
In [ ]:
x .+ 1               # 每个元素为+1
x .- 1               # 每个元素为1
x .* 2               # 每个元素*2
x ./ 2               # 每个元素/2
Out[0]:
2×5 Matrix{Float64}:
 0.5  1.0  1.5  2.0  2.5
 3.0  3.5  4.0  4.5  5.0

点更新运算符

In [ ]:
x = [1 2 3 4 5; 6 7 8 9 10]
Out[0]:
2×5 Matrix{Int64}:
 1  2  3  4   5
 6  7  8  9  10

通过复盖现有数组x来改变它。

In [ ]:
x .+= 1
Out[0]:
2×5 Matrix{Int64}:
 2  3  4   5   6
 7  8  9  10  11

创建一个新的数组,x不改变

In [ ]:
y = x .+ 1
Out[0]:
2×5 Matrix{Int64}:
 3  4   5   6   7
 8  9  10  11  12

比较运算符

In [ ]:
2 == 2.0             # true-不同类型,但值相等
3 == 5               # false
3 != 5               # true
3 < 5                # true
5 > 3                # true
3 <= 3               # true
5 >= 5               # true
Out[0]:
true

浮点数的特点:

*正零等于但不大于负零
*Inf等于本身,最重要的是(NaN除外)
*-Inf等于本身,最少(NaN除外)
*NaN比不上任何东西

Julia还允许您编写数学比较链。

In [ ]:
10 < 15 <= 20 < 30 == 30 > 20 >= 10 == 10 < 30 != 5
Out[0]:
true

相当于:

In [ ]:
(10 < 15) && (15 <= 20) && (20 < 30) && (30 == 30) && (30 > 20) && (20 >= 10) && (10 == 10) && (10 < 30) && (30 != 5)
Out[0]:
true

点比较

In [ ]:
x = [1 2 3 4 5; 6 7 8 9 10]
x .<= 3
Out[0]:
2×5 BitMatrix:
 1  1  1  0  0
 0  0  0  0  0
In [ ]:
1 .< x .< 7
Out[0]:
2×5 BitMatrix:
 0  1  1  1  1
 1  0  0  0  0

索引化

In [ ]:
A = [1 2 3; 4 5 6]          # 2×3 Matrix{Int64}
A[1, 2]                     # 2(第一行,第二列)
A[1, :]                     # 第一行(1×3)
A[:, 2]                     # 第二列(2×1)
A[1:2, 1]                   # 第一列就像一个向量
A[1:2, 1:2]                 # 2×2子矩阵
Out[0]:
2×2 Matrix{Int64}:
 1  2
 4  5

从末尾索引

In [ ]:
A[1, end]                   # 第一行的最后一个元素
A[end, 1]                   # 第一列的最后一个元素
Out[0]:
4

逻辑索引

In [ ]:
A[A .> 2]                   # [4, 5, 6, 3] ( 对齐到一个向量)
Out[0]:
4-element Vector{Int64}:
 4
 5
 3
 6

操作员优先级

层次结构(从最高到最低):

  1. 数值系数:2x(高于除^以外的所有二进制系数)
  2. 指数化:^
  3. 一元数:+x,-x,√x,。..
  4. 乘法/除法: *, /, \, ÷, %
  5. 加法/减法:+, -
  6. 转变: <<, >>, >>>
  7. 按位和: &
  8. 按位异或:⊻
  9. 按位或:|
  10. 比较:==,!=, <, <=, >, >=
  11. 类型语句:<:
  12. 逻辑和: &&
  13. 逻辑或:|/
  14. 管道操作符:/>
  15. 指派任务: =, +=, -=, 等等。

首先x^2=9,然后2*9

In [ ]:
x = 3
2x^2
Out[0]:
18

首先2x=6,然后2^6!

In [ ]:
2^2x                 
Out[0]:
64

控制结构

条件运算符

In [ ]:
x = 10
msg = if x > 5
    "五个以上"
else
    "很少"
end
Out[0]:
"Больше пяти"

三元运算符

In [ ]:
x > 5 ? "是的" : "非也。"
Out[0]:
"Да"

短路评估(替代if)

In [ ]:
x > 0 && println("正")   # 如果为true,则执行
x < 0 || println("不是负面的") # 如果第一个为false,则执行
Положительное
Не отрицательное

周期:

*有先决条件
*附后记

In [ ]:
for i in 1:3
    println(i)
end
1
2
3
In [ ]:
while x > 0
    x -= 1
end

遍历集合

In [ ]:
for (i, val) in enumerate(["a", "b", "c"])
    println("$i: $val")
end
1: a
2: b
3: c

生成器和理解

数组理解(创建数组)

In [ ]:
squares = [x^2 for x in 1:5]
Out[0]:
5-element Vector{Int64}:
  1
  4
  9
 16
 25

与条件

In [ ]:
evens = [x for x in 1:10 if x % 2 == 0]
Out[0]:
5-element Vector{Int64}:
  2
  4
  6
  8
 10

生成器(懒惰计算,节省内存),不会在内存中创建数组,而是一次迭代一个元素。

In [ ]:
gen = (x^2 for x in 1:1000000)
sum(gen)
Out[0]:
333333833333500000

功能和多种调度

一个简短的音符(一个表达式)

In [ ]:
f(x) = x^2 + 1
Out[0]:
f (generic function with 2 methods)
In [ ]:
f(5)
Out[0]:
26
In [ ]:
f(1)
Out[0]:
2

经典条目(代码块)

In [ ]:
function g(x, y)
    return x + y
end
Out[0]:
g (generic function with 1 method)

默认参数、键参数

In [ ]:
function greet(name; greeting="Hello", punctuation="!")
    return "$greeting, $name$punctuation"
end
greet("Engee", greeting="Hi")
Out[0]:
"Hi, Engee!"

匿名函数

In [ ]:
h = x -> x^2
h(4) 
Out[0]:
16

常用于map、filter:

In [ ]:
map(x -> x^2, [1, 2, 3])
Out[0]:
3-element Vector{Int64}:
 1
 4
 9

多个分派-根据数据类型,同一个函数的行为不同。

In [ ]:
say_hello(name::String) = "你好,男人!"
say_hello(name::Symbol) = "你好,机器人:$名称"

say_hello("安娜")
say_hello(:R2D2) 
Out[0]:
"Привет, робот :R2D2"

启动计划

image.png

将执行该文件

In [ ]:
include("example.jl")
Hello, World!

REPL模式

主要模式是julia

In [ ]:
2+2
Out[0]:
4

参考模式(?)

In [ ]:
?sqrt
search: sqrt isqrt sort sort! Cshort struct cbrt stat sprint

Out[0]:

?sqrt

分组模式(])

In [ ]:
]add DataFrames
   Resolving package versions...
     Project No packages added to or removed from `~/.project/Project.toml`
    Manifest No packages added to or removed from `~/.project/Manifest.toml`
In [ ]:
]status
Status `~/.project/Project.toml`
  [150eb455] CoordinateTransformations v0.6.4
  [a93c6f00] DataFrames v1.8.1
  [cbc4b850] ImageBinarization v0.3.1
  [4381153b] ImageDraw v0.2.6
  [92ff4b2b] ImageFeatures v0.5.3
  [6a3955dd] ImageFiltering v0.7.12
 [787d08f9] ImageMorphology v0.4.6
  [916415d5] Images v0.26.2
  [033835bb] JLD2 v0.6.3
  [c46f51b8] ProfileView v1.10.3
  [6038ab10] Rotations v1.7.1
 [90137ffa] StaticArrays v1.9.16
  [5e47fb64] TestImages v1.9.0
Info Packages marked with  have new versions available but compatibility constraints restrict them from upgrading. To see why use `status --outdated`

Shell模式(;)

In [ ]:
;ls
Language_Features.ngscript
example.jl

宏允许您生成代码和扩展语法;在Julia中,它们通常用于调试,时间测量和优化。

In [ ]:
@show 2 + 2          # 输出表达式和结果
2 + 2 = 4
Out[0]:
4
In [ ]:
@time sleep(0.1)     # 测量执行时间
  0.102356 seconds (10.70 k allocations: 1.160 MiB)
In [ ]:
@assert 1 == 1       # 检查病情
In [ ]:
macro hello(expr)
    quote
        println("嗨! 现在就要发生了:")
        println("  ", $(string(expr)))
        $(esc(expr))
    end
end
@hello 2 + 3 * 5
Привет! Сейчас выполнится:
  2 + 3 * 5
Out[0]:
17

模块和命名空间

In [ ]:
module MyModule
    export hello, PI
    const PI = 3.14
    hello() = println("Hello from module")
    # 未导出
    internal() = println("internal")
end
Out[0]:
Main.MyModule
In [ ]:
using .MyModule   # 或导入MyModule
hello()           # 可供选择
# internal()#错误,未导出
Hello from module

错误处理

In [ ]:
try
    sqrt(-1)
catch e
    println("Caught an error: $e")
finally
    println("This always runs")
end
Caught an error: DomainError(-1.0, "sqrt was called with a negative real argument but will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).")
This always runs
In [ ]:
# 错误生成
if x < 0
    error("x must be non-negative")
end
In [ ]:
# 自定义异常
struct MyError <: Exception
    msg::String
end
# throw(MyError("something went wrong")) #ERROR

文件

In [ ]:
"""
    square(x)

返回数字`x`的平方。

# Arguments
-'x':一个数字(任何数字类型)

# Example
```julia
julia> square(5)
25

"""
square(x) = x^2
Out[0]:
square

结论

你集中展示了Julia的基础知识,重点不是冗长的解释,而是视觉代码片段。 这种风格不仅可以让你了解语言的功能,而且可以立即看到它们的作用,记住语法并理解工作的逻辑。 现在你有一个紧凑的备忘单,你可以在编写自己的程序时返回。