贡献者: addis
参考 Julia 文档。
float, double 等不是对象,只有 struct, class 定义的才是对象。Julia 中的对象没有成员函数。
::变量类型 用于确认它具有该类型,如果类型不符会产生异常。如果 变量类型 是抽象的,那么表达式只能是它的一个子类。
常见类型
Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64(即 Int), UInt64, Int128, UInt128, Float16, Float32, Float64, ComplexF16, ComplexF32 和 ComplexF64
BigInt 是任意大小的整数,BigFloat 是任意精度浮点数。
julia> BigFloat(2.1) # 2.1 here is a Float64
2.100000000000000088817...
julia> BigFloat("2.1") # the closest BigFloat to 2.1
2.099999999...99999986
julia> BigFloat("2.1", RoundUp)
2.100000000...0000021
julia> BigFloat("2.1", precision=128)
2.0999999...995
julia> BigFloat("2.1", RoundUp, precision=128)
2.100000000...00000000000007
使用 typeof(var) 来询问变量类型,用 isa(var, type) 来确定类型。sizeof(变量或类型) 来查看类型的字节数
setprecision(二进制精度); 可以设置运算默认的精度
BigFloat(pi) 会默认为上面设置的精度,BigFloat(pi, precision=...) 可以临时改变精度,但是 BigFloat(pi, precision=...)*2 仍然是上面设置的精度,因为乘法使用上面设置的精度。
pi 的加减乘除都得到 Float64 类型。
Bool 类型的值可以是 true 或者 false
any([true, false, ...]) 和 all([trua, false, ...])
typeof(3) 是 Int64;typeof(12345678902234567890) 是 Int128,typeof(1234567890223456789032345678904234567890) 是 BigInt。typemin(类型) 和 typemax(类型) 可以查看最大最小值。
a = Int8(1),a += 1 后 a 会变为 Int64。因为 1 相当于 Int64(1)。
Float64。
eps(Float64) 返回 2.220446049250313e-16
NaN 是 not a number,可以用 isnan(x) 来判断
:名字 表示任意名字的 Symbol,常用于字典的 key,类似于 C++ 的 enum。
Symbol(又例如 :abc,:a)注意 :pi 和 :π 是两个不同的 Symbol。
Symbol("#3ac!3f") 创建。
Symbol(:abc, :def, :ghi) 可以合并符号名,得到 :abcdefghi
pi 的类型是 Irrational{:π} 其中 :π 的类型是
BigFloat(pi, precision=500) 可以获得 500 位二进制的 pi。
Char,字符串的类型是 String。
sizeof(Char) = 4
a = "你好 Julia" 中,a[1] 是 你,a[4] 是 好,a[8] 是 J。a[2] 会报错!
i = nextind(str, i) 来获取下一个字符的合法索引!
for c = str 也可以遍历每个字符(不是每个字节)
for i = eachindex(a) 可以遍历每个字符所在的索引
length(str) 返回字符个数(不是每个字节数)
s = "abcde" 的类型是 String,注意 String 并不是 Array{Char, 1}! s[i] 可以获取单个 Char,但是不能赋值,因为 String 是不可改变的(immutable)。
s1 = replace(s, "bc" => "BC")。s1 也可以是 s 本身。
s = s1*s2 拼接字符串(等效地:s = string(s1, s2)),s *= s1 可以 append。
string(str1, str2, ...) 也可以拼接
s = s1^3 重复字符串 3 次,s ^= 3 同理。相当于 repeat(s1, 3)
findfirst("abc", s) 搜索字符串,返回一个 UnitRange{Int64},如 3:5。
findnext("abc", s, ind) 从 ind 开始搜索下一个
collect(str) 可以得到一个字符数组,即 Vector{Char}。
s = b"abcABC123" 的类型是 Base.CodeUnits{UInt8, String},s[i] 的类型是 UInt8
bytes = Vector{UInt8}(str) 可以把字符串转换为字节。
str = raw"Hello\nJulia" 创建裸字符串(\n 不当作换行)
a[i] = 'b';
"""...""" 可以表示多行字符串
"The sum of $x and $y is $(x + y)."
== 或 < 对比两个字符串。
new_str = replace(str, "Julia" => "World") 可以替换字符串。
str1 = strip(str) 可以除去两边空格。
parts = split(str, ",") 可以拆分字符串。
str = join(parts, ", ") 可以组合。
startswith(str, key) 和 endswith(str, key)。
findfirst(str, key) 和 findlast(str, key)
str = "Hello, Julia!"; m = match(r"Julia", str) 正则表达式匹配
new_str = original_str[1:7] * insert_str * original_str[8:end]
声明抽象类型
abstract type 子类名 <: 母类名 end
声明后,可以用 类1 <: 类2 来判断是否符合该关系,返回一个 Bool。
用 supertype(类) 可以查看某个类的母类,subtypes(类) 可以查看所有子类。
例子
abstract type Number end
abstract type Real <: Number end
abstract type AbstractFloat <: Real end
abstract type Integer <: Real end
abstract type Signed <: Integer end
abstract type Unsigned <: Integer end
最高级的抽象类是 Any,这里的 Number 就是 Any 的子类。
以及
Complex{T<:Real} <: Number
Rational{T<:Integer} <: Real
Irrational{sym} <: AbstractIrrational
原始类型(primitive type)是由 bit 组成的具体类型。Julia 可以自定义原始类型。定义原始类型的格式为
primitive type 类名 比特数 end
primitive type 类名 <: 父类名 比特数 end
例如
primitive type Float16 <: AbstractFloat 16 end
primitive type Float32 <: AbstractFloat 32 end
primitive type Float64 <: AbstractFloat 64 end
primitive type Bool <: Integer 8 end
primitive type Char <: AbstractChar 32 end
primitive type Int8 <: Signed 8 end
primitive type UInt8 <: Unsigned 8 end
primitive type Int16 <: Signed 16 end
primitive type UInt16 <: Unsigned 16 end
primitive type Int32 <: Signed 32 end
primitive type UInt32 <: Unsigned 32 end
primitive type Int64 <: Signed 64 end
primitive type UInt64 <: Unsigned 64 end
primitive type Int128 <: Signed 128 end
primitive type UInt128 <: Unsigned 128 end
Array{类型,维数}。一维数组 Array{类型,1} 也记为 Vector{类型},不区分行和列;Array{类型,2} 也记为 Matrix{类型},区分行向量和列向量。
[1, 2] 和 [1; 2] 的类型都是 Array{Int64,1},但 [1 2] 的类型是 Array{Int64,2}
类型[1,2,3] 可以创建指定类型的数组。
append!(数组, 元素) 或者 push!(数组, 元素) 可以在列向量最后添加一个元素。
push!([1, 2, 3], 4, 5) 或者 append!([1, 2, 3], [4, 5])
类型[] 创建空数组
a = [1 2; 3 4] 得到 Array{Float64,2} 注意不能用逗号,但可以不写 ; 而使用换行。
[1, "abc", 1.2] 的类型是 Vector{Any}。
[2^i for i = 1:10] 可以用通项公式快速生成一个数组。
typeof(1:3) 是 UnitRange{Int64}。支持 T<:Real 元素类。如 UnitRange(3.3, 5.6)。
typeof(1:2:5) 是 StepRange{Int64, Int64}。
typeof(1.1:3) 和 typeof(1.1:2:5) 的类型都是 StepRangeLen{T,R,S,L}。它的 constructor 是 a = StepRangeLen(ref::R, step::S, len::L, [offset=1])。其中 T 是标量类型即 a[i] 的类型,R 是 ref 即 a[offset] 的类型,S 是 step 的类型,L 是元素个数 len 的类型。
push!(v, 元素) 可以在 Vector 后面增加一个元素,同时也会返回新的 v。pop!(v) 移除最后的元素,返回最后一个元素。
splice!(v, 3:5) 可以删除 v[3:5]
A .= 值 或者 fill!(v, 值) 可以把 v 的每个元素赋值。
a[:, j, :]
typeof(:) 是 Colon
size(矩阵, 维度),元素个数 length()(相当于 Matlab 的 numel),isempty() 检查空矩阵,reverse() 元素倒序排序
findmax(), findmin() 找到矩阵的最大最小元素。
Array{Float64,2}(undef, 2, 3) 创建矩阵,矩阵元不初始化。
zeros(整数) 或 zeros(整数, 整数) 分别返回 Array{Float64,1} 和 Array{Float64,2}。也可以用 zeros(类型, 整数, 整数) 指定类型。
rand(N1, N2, ...) 或者 rand(类型, N1, N2, ...)。
hash(矩阵),类型为 UInt64。把运算结果的 hash 输出可以保证计算过程不被优化掉。事实上可以作用于任何对象(包括自定义类型)。
Int64
a[:, 1] 或者 a[1, :] 仍然得到 Array{Int64,2}
a[:, 1] = [3; 4] 可以修改 a 的值
a = b 是浅复制,a 改变了 b 也会改变(同一对象)。
a = copy(b) 是真复制,新生成一个对象。
a === b 来判断是否是同一对象。
objectid(1.23) 会返回一个哈希如 0xae6a147d33244922。objectid(x) == objectid(y) 一定有 x === y,反过来大部分情况成立,但不保证。
b = a[:, 1] 也是真复制。
a 作为参数传给函数是 pass by reference,相当于 C 语言传递指针(有例外,见 Julia 的函数)
Float32[1, 4, 5]。
Any。例如 ["a", 1.23] 的类型就是 Vector{Any} 即 Array{Any, 1}
函数.(数组) 可以对数组内的每个元素分别作用,返回数组。例如 sin.([1,2,3])。sin([1,2,3]) 是错误的用法。
exp([1 2;3 4]) 是矩阵的指数,exp.([1 2;3 4]) 是逐个元素做指数。
collect(1:5) 可以把类似 range 的类型变为 Vector{} 类型。
v .+ 标量 可以把数组的每一个元素加上标量。如果用 + 会出错。同理也有 .+=。其他算符同理。
矩阵 .+ 行向量 可以对每一行都加行向量。
B = [A; A] 可以拼接矩阵
resize!(矢量, N) 可以用于改变矢量长度,已有的元素值不会改变,新增的元素不初始化。
A = reshape(数组, N1, N2, ...) 或者 A = reshape(数组, (N1, N2, ...)) 可以改变数组的形状甚至维度。但改变前后元素个数必须不变。注意 A 和 数组 共享内存,改变一个另一个也会变。
A' 是厄密共轭,转置再取共轭,相当于 conj(transpose(A))
maximum(v) 求最大值,maximum(A,2) 求第二个维度的最大值。
argmax(v) 同理,返回 index。
v = Core.svec(1, "a", :x) 创建一个简单矩阵,通常不被用户使用而在内核内部使用。可以用 v[i] 获取值,但不能改变(unmutable)
length(v) 检查长度
collect(v) 变为普通数组
较新版的 Julia dump(Matrix{Float64})
Matrix{Float64} <: DenseMatrix{Float64}
ref::MemoryRef{Float64}
size::Tuple{Int64, Int64}
其中
MemoryRef{Float64} <: Ref{Float64}
ptr_or_offset::Ptr{Nothing}
mem::Memory{Float64}
其中
Memory{Float64} <: DenseVector{Float64}
length::Int64
ptr::Ptr{Nothing}
分配内存:
m = Memory{Float64}(undef, 10) # 10 个未初始化的 Float64
m[2:5] # 返回类型还是 Memory{Float64}
例如
julia> a = [1 2; 3 4; 5 6]
3×2 Matrix{Int64}:
1 2
3 4
5 6
julia> a.ref.ptr_or_offset
Ptr{Nothing} @0x0000023055ec13d0
julia> a.ref.mem
6-element Memory{Int64}: 1 3 5 2 4 6
julia> dump(a.ref.mem)
Memory{Int64}
length: Int64 6
ptr: Ptr{Nothing} @0x0000023055ec13d0
a[:, 1] 作为参数传给函数是 pass by value,如果需要 by reference,使用 view 函数获取 SubArray 类
SubArray 不存数据,可以用来给函数参数 pass by reference
SubArray 类型的 5 个参数 SubArray{标量类,维数,矩阵类,Tuple{各维度索引类型},是否支持快速索引}
view(a, :, 1) 的类型是 SubArray{Int64,1,Matrix{Int64},Tuple{Base.Slice{Base.OneTo{Int64}},Int64},true}
view(a, 1, :) 的类型是 SubArray{Int64,1,Matrix{Int64},Tuple{Int64,Base.Slice{Base.OneTo{Int64}}},true}
view(a, 1:2, 2:3) 的类型是 SubArray{Int64,2,Matrix{Int64},Tuple{UnitRange{Int64},UnitRange{Int64}},false}
SubArray <: AbstractArray{T,Ndim} <: Any
Array{T,Ndim} <: DenseArray{T,Ndim} <: AbstractArray{T,Ndim} <: Any
AbstractArray,就可以同时接受 Array, SubArray。
SubArray 的结构
struct SubArray{T,N,P,I,L} <: AbstractArray{T,N}
parent::P
indices::I
offset1::Int # for linear indexing and pointer, only valid when L==true
stride1::Int # used only for linear indexing
...
end
1:5 等效于 range(1,5),类型是 UnitRange{Int64}
Vector(3:5)。
1:3:9 等效于 StepRange(1, 3, 9),类型是 StepRange{Int64, Int64} 注意 StepRange 类型的参数只能是整数。StepRange(1, Int8(3), 9) 的类型是 StepRange{Int64, Int8}
1.2:5.1(等效于 range(1.2,5.1))和 1:0.2:4.1(等效于 1:0.2:4 和 range(1,4,16))的类型是 StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}。range(2,4,3) 虽然每个元素都是整数,但类型也是一样的。
LinRange(初始值,终止值,个数) 概念上是等间距数组,相当于 Matlab 的 linspace。但类型为 LinRange{Float64, Int64}。
range(1,2,length=3) 等效于 1.0:0.5:2.0。
AbstractRange <: AbstractVector <: Any,都可以像数组一样用 size(x, dim) 来获取尺寸,length() 获取元素个数,可以用 x[i] 获取元素。
复合类型(composite) 类似于 C++ 中的 struct,但是不能有成员函数。
struct Foo
bar # 抽象类型是 Any
baz::Int
qux::Float64
end
创建该类型的对象
foo = Foo("Hello, world.", 23, 1.5) # 叫做 constructor
foo.bar, foo.baz 等。用 struct 声明的复合类型的变量在定义后就不能被改变。如果 struct 里面有矩阵等,那么矩阵元仍然是 mutable 的(没有 lower level const)。
mutable struct 来声明即可。mutable struct 通常存在 heap 中而不是在 stack 中。
fieldnames(类型),如果还要显示成员类型,用 dump(类型)。
getglobal(module::Module, name::Symbol, [order::Symbol=:monotonic]) 可以从模块中获取符号。
getproperty(a, b) 相当于算符 a.b,会根据 a, b 的类型调用 getfield(::Type, ::Symbol)(结构体获取字段),getfield(::Tuple, ::Int)(Tuple 获取元素),getfield(::Array, ::Int),getfield(自定义struct, 字段序号::Int),getglobal(::Module, ::Symbol)(从模块获取符号)
isdefined(对象, :字段名) 可以判断对象的字段是否存在
ismutable(Foo) 可以判断是否 mutable struct。注意 ismutable(Matrix{Int64}) 是 true 而 ismutable(Matrix) 是 false。
? 进入 help 模式,然后再输入 Foo。等效地也可以用 @doc Foo。
struct Person
name::String
age::Int
# === inner constructors ===
# 调用如 Person(...)
# 一旦定义了任何其他 constructor,就不会默认提供
function Person(name::String, age::Int, add::Int)
# new(<field1>, <field2>, ...) 只能在 inner constructor 中使用
new(name, age+add)
end
# 调用如 Person.abc(...)
function abc(name::String, age::Int, add::Int)
new(name, age+add)
end
end
Base.convert(::Type{类型1}, f::类型2),转换用 g = convert(类型1, f)
mutable struct User
id::Int
name::String
email::String
age::Int
end
user1 = User(1, "Alice", "alice@example.com", 30)
mutable,构造后将不能改变字段值。
fieldnames(类型) 查看所有字段,fieldname(类型, i) 查看第 i 个,nfields(对象) 是数量,fieldtypes(类型) 查看对应的类型。dump(类型) 查看详情,methods(类型) 查看有哪些函数(似乎只能显示构造函数)。
dump(Rational{Int64}) 得到
Rational{Int64} <: Real
num::Int64
den::Int64`
nfields(1//2) 得到 2。注意 nfields(Rational{Int64}) 是 8,因为 typeof(Rational{Int64}) 是 DataType,而 dump(DataType) 是
# 以 Matrix{Float64} 为例
DataType <: Type{T}
name::Core.TypeName # typename(Array) 的返回值,见下文
super::DataType # 超类(父类)如 DenseMatrix{Float64}
parameters::Core.SimpleVector # 模板参数,如 svec(Float64, 2)
types::Core.SimpleVector # 每个字段的类型,如
# svec(MemoryRef{Float64}, Tuple{Int64, Int64})
instance::Any
layout::Ptr{Nothing}
hash::Int32
flags::UInt16
# 作为 Core.TypeName 是 DataType 字段 name 的类
# 还是以 Matrix{Float64} 为例, 其 name 字段就是 Core.typename(Array) 的返回值
mutable struct Core.TypeName <: Any
const name::Symbol # 如 `:Array`
const module::Module # 所在模块,如 `Core`
singletonname::Symbol # 如 `:Array`
const names::Core.SimpleVector # 字段名,如 svec(:ref, :size)
atomicfields::Ptr{Nothing}
constfields::Ptr{Nothing}
const wrapper::Type
Typeofwrapper::Type
cache::Core.SimpleVector
linearcache::Core.MethodCache
partial::Any
const hash::Int64
max_args::Int32 # 如 0
const n_uninitialized::Int32
const flags::UInt8
cache_entry_count::UInt8
max_methods::UInt8
constprop_heuristic::UInt8
fieldnames(Rational{Int64}) 得到 (:num, :den),fieldtypes(Rational{Int64}) 得到 (Int64, Int64)。
C:\Users\addis\AppData\Local\Programs\Julia-1.11.6\share\julia\base\boot.jl):
struct Pair{A, B}
first::A
second::B
Pair(a, b) = new{typeof(a), typeof(b)}(a, b)
function Pair{A, B}(@nospecialize(a), @nospecialize(b)) where {A, B}
@inline
return new(a::A, b::B)
end
end
IntOrString = Union{Int, AbstractString}
1 :: IntOrString
"Hello!" :: IntOrString
1.0 :: IntOrString # 异常
但是,这和使用 <: 有什么区别?一个类只可能有一个非 Union 的母类,如果一个函数的参数想要支持两个母类不同的类怎么办?那就用 Union 即可。
另外一个应用的例子是 Union{T, Nothing} 作为函数参数,这样这个参数就可以忽略了。
复数类型 ComplexF16, ComplexF32 和 ComplexF64 是 Complex{Float16}, Complex{Float32} 和 Complex{Float64} 的别名。Complex 就是一个含参类型(parametric type)
例如
struct Point{T}
x::T
y::T
end
那么 Point{Float64} 等都是合法的具体类型。
Point 本身是一个抽象类,是其具体类的母类
julia> Point{Float64} <: Point
true
julia> Point{AbstractString} <: Point
true
<: 相当于一个二元算符,输出 Bool。
例子:
function norm(p::Point{Real})
sqrt(p.x^2 + p.y^2)
end
constructor
p = Point{Float64}(1.0, 2.0)
含参抽象类型(Parametric Abstract Types) 例如
abstract type Pointy{T} end
struct Point{T} <: Pointy{T}
x::T
y::T
end
值1 => 值2 的数据类型是 Pair{类型1, 类型2},两种类型都可以是 Any。
"abc" => 1.23 的类型是 Pair{String, Float64},令 p = "abc" => 1.23,那么 p.first 和 p.second 分别可以获取两个变量。
Pair 同样是 immutable 的。
Tuple 是函数参数列表的抽象。例如两个元素的 tuple type 类似于如下的含参 struct 类型
struct Tuple2{A,B}
a::A
b::B
end
例子
julia> typeof((1,"foo",2.5))
Tuple{Int64, String, Float64}
julia> Tuple{Int,AbstractString} <: Tuple{Real,Any}
true
julia> Tuple{Int,AbstractString} <: Tuple{Real,Real}
false
t = (值1, 值2, 值3, ...) 就是 Tuple
Tuple 的元素类型可以不同
t = (1, "3.1", [1 2; 3 4]) 的类型是 Tuple{Int64, String, Matrix{Int64}}
length(),isempty(),reverse() 同样适用于 Tuple。
t[i] 获取某个元素,但不能对其赋值! Tuple 的元素永远不能改变! Tuple 类型是 immutable 的。
x = (a=2, b="abc") 等效于 x = NamedTuple{(:a, :b)}((2, "abc")),类型为 NamedTuple{(:a, :b), Tuple{Int64, String}},语法糖为 @NamedTuple{a::Int64, b::String}。然后可以使用 x.a 和 x.b 来获取元素。和 Tuple 一样,创建后值无法改变。typeof(x) 打印出语法糖。
(1,),空 tuple 用 () 表示,类型为 Tuple{}。
(a1,a2,a3) = my_tuple 可以把 Tuple 拆开
(x,y) = (1,"ab") 或者 x,y = (1,"ab") 会分别把元素赋值给 x, y。这可以用于函数返回多个值。
p = pointer(v) 可以获取一个数组第一个元素的指针,类型是 Ptr{元素类型}。unsafe_load(p) 可以获得第一个元素的值 p + sizeof(元素类型) 可以获得下一个元素的指针。
unsafe_store!(p, 值) 可以给指针的元素赋值。
Ref{类型} 创造一个安全的引用,保证类型不变,被引用的对象不会被回收。
ccall 调用 C 函数。
# immutable
x = 3
r = Ref(x) # Base.RefValue{Int64}(3)
println(r[]) # 解引用,打印 3
x = 4 # 不会改变 r[]
r[] = 2 # 不会改变 x
println("x = $x, r[] = $(r[])")
# 调用 C 函数
# ccall(:foo, Cvoid, (Ref{Int},), r)
# mutable
x = [1,2,3]
r = Ref(x) # Base.RefValue{Vector{Int64}}([1, 2, 3])
println(r[]) # 解引用,打印 [1, 2, 3]
x[1] = 4 # 会改变 r[]
r[][2] = 5 # 会改变 x
println("x = $x, r[] = $(r[])")
# 应用:函数改变 immutable 入参
function g(x::Ref{Int})
x[] = 10
end
a = Ref(3)
g(a)
a[] # 10
Set 是无序集合,若要有序,用 OrderedCollections.jl 中的 OrderedSet
s = Set{Int64}() 生成某种类型的空 set。
s = Set([1,2,3]) 把数组变为 Set(自动推导出类型 Set{Int64})
push!(s, 123, 23, 532) 添加若干元素。
empty!(s) 清空集合。
in(123, s) 查看某个元素是否存在
union!(s1,s2) 计算并集,赋值给 s1,s = union(s1,s2) 计算并集,赋值给 s。
d = Dict{key类型,Val类型}() 创建一个字典(哈希表),也可以直接用 Dict("ab"=>12, "bc"=>23)(会自动推导类型 Dict{String, Int64})
d = Dict("a" => 1, "b" => 2),取值用 d["a"],d["c"] 会报错,若不想报错也可以用 get(d, "c", nothing) 当 key 不存在就会返回第三个入参。
Dict("ab"=>12, 12=>"ab") 的类型是 Dict{Any, Any}。
isempty() 可以检查容器是否为空。
push!(d, key1=>val1, key2=>val2) 添加若干 entry,如果 key 已经存在,就覆盖 val。
a[key] = val。
a[key] 获取对应的 val,如果 key 不存在则会出错。
@inbounds a[key] 和数组一样,可以避免边界检查(当你确信 key 一定存在)
haskey(d, 12) 检查 key 是否存在。
delete!(d, key)。
keys(d) 表示所有存在的 key,类型是 Base.KeySet{key类型, Dict{key类型, val类型}},不会复制值。
vals(d) 同理,类型是 Base.ValueIterator{Dict{String, Int64}}
for (k, v) in d
...
end
kw... 时,kw 的类型就是这个。
NamedTuple。NamedTuple(kw) 可以把它转换。
another_fun(...; kw..., abc = 123) 可以把它继续传递给别的函数。
DataType。例如 my_func(Int32) 就是把类型值作为入参。此时 typeof(Int32) 是 DataType。
DataType 的超类是 Type{T}。
Type{Int32} 是一个单例类,它的唯一对象就是 Int32。
isa() 的用法是 isa(值,所属类或超类),例如 isa(3.1, Float64) 返回真,isa(3.1, AbstractFloat) 返回真。
isa(Int32, DataType), isa(Int32, Type), isa(Int32, Type{Int32})
isa(Int32, Type{Integer}) 返回假,isa(Int32, Type{Float64}) 返回假。
使用等号。例如
# 32-bit system:
julia> UInt
UInt32
# 64-bit system:
julia> UInt
UInt64
实现方法
This is accomplished via the following code in base/boot.jl:
if Int === Int64
const UInt = UInt64
else
const UInt = UInt32
end
julia> isa(1, Int)
true
julia> typeof(Rational{Int})
DataType
julia> typeof(Union{Real,String})
Union
julia> typeof(DataType)
DataType
julia> typeof(Union)
DataType
julia> supertype(Float64)
AbstractFloat
julia> supertype(Number)
Any
julia> supertype(AbstractString)
Any
julia> supertype(Any)
Any
A = rand(2, 2); B = A.^2; 在 IR 中会翻译成如下代码
A = rand(2, 2);
# two 类型为单例类 Val{2},相当于执行 two=Val{2}() 或 Val(3)
two = (Core.apply_type(Base.Val, 2))()
expr = Base.broadcasted(Base.literal_pow, Main.:^, A, two)
B = Base.materialize(expr)
Core.apply_type(类模板, 模板参数 ...) 可以从模板创建一个类型,模板参数应该需要为编译时常量。
类() 或者 (类)() 调用默认构造函数。
Base.literal_pow(Main.:^, 3, Val{2}()) 可以计算 3^2 = 9
Base.broadcasted(算符或函数, 参数1, 参数2, ...) 其中 参数* 本身或者其矩阵元被传入 算符或函数。
Val{2} 的父类是 Any