多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Julia 语言实战入门:从同像性函数式设计到多重分派(learnxinyminutes-docs 教程全解)

Julia 语言实战入门:从同像性函数式设计到多重分派(learnxinyminutes-docs 教程全解) 文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载本篇技术指南以 learnxinyminutes-docs 仓库中的葡萄牙语教程 pt-br/julia.md 为绝对核心骨架系统讲解 Julia 语言的同像性homoiconic函数式设计、基础类型与运算符、变量与集合、控制流、函数、类型系统与多重分派机制并深入到底层 LLVM/汇编代码。读完本文你将掌握 Julia 从语法到运行机制的完整知识脉络并能对照仓库内基于 Julia 1.0 的英文原版 julia.md 与 zh-cn/julia.md 完成新旧版本差异的迁移理解。版本说明原教程明确声明「Este tutorial é baseado no Julia 0.3」本教程基于 Julia 0.3。文中标注为 Julia 0.3 语法的写法在仓库英文原版中已更新至 Julia 1.0.0 语法本文会在对应小节给出新旧写法对照方便读者在两种环境下实践。1. 注释与代码块的书写方式Julia 的注释体系非常直观单行注释与多行注释都支持# 单行注释以井号#开头 # 多行注释可以这样写 在文本前放 #在文本后放 # 多行注释还可以嵌套使用 #这是整个 learnxinyminutes-docs 教程的通用组织形式所有教程都以「合法的、带注释的代码」为载体边运行边讲解。正如 README.md 所述这些文件是「以代码形式书写的文档」code documentation written as code每个文件本身就是一份可以直接运行的示例程序。2. 基础类型与运算符Tipos primitivos e operadoresJulia 中一切都是表达式Everything in Julia is an expression这是理解这门语言的首要心智模型。它是一门面向技术计算technical computing的同像性函数式语言——既拥有同像性宏homoiconic macros、一等函数first-class functions和底层控制能力的全部威力又像 Python 一样容易学习和使用。2.1 数值类型Julia 拥有丰富的原生数值类型直接在 REPL 中输入即可查看其类型3 # 3 Int64 3.2 # 3.2 Float64 2 1im # 2 1im Complex{Int64}复数字面量 2//3 # 2//3 Rational{Int64}有理数字面量字面量结果类型说明3Int64平台相关的有符号整数64 位平台默认3.2Float64双精度浮点2 1imComplex{Int64}复数im是虚数单位2//3Rational{Int64}精确有理数//构造有理数2.2 常规中缀运算符所有常规中缀算术运算符都可用1 1 # 2 8 - 1 # 7 10 * 2 # 20 35 / 5 # 7.0 5 / 2 # 2.5 # 注意Int 除以 Int 得到浮点数 div(5, 2) # 2 # 需要截断整除结果时使用 div 5 \ 35 # 7.0 # 反斜杠是左除35/5 的另一种写法 2 ^ 2 # 4 # ^ 是幂运算不是位运算异或 12 % 10 # 2 # 取余 (1 3) * 2 # 8 # 用括号强制优先级需要特别强调的是5 / 2返回2.5整数相除总是产生浮点数这与许多语言如 Python 2不同若要截断整除请使用div。这一点在英文原版 julia.md 中以10 / 2 # 5.0 # dividing integers always results in a Float64再次强调。2.3 位运算符~2 # -3 # 按位取反not 3 5 # 1 # 按位与and 2 | 4 # 6 # 按位或or 2 $ 4 # 6 # 按位异或xor 2 1 # 1 # 逻辑右移高位补 0 2 1 # 1 # 算术右移符号位扩展 2 1 # 4 # 左移版本差异0.3 时代异或用$英文原版Julia 1.0已改为函数形式xor(2, 4)。2.4 用 bits 查看二进制表示你可以用bits函数查看一个数字的二进制表示这是理解整数与浮点内部存储差异的利器bits(12345) # 0000000000000000000000000000000000000000000000000011000000111001 bits(12345.0) # 0100000011001000000111001000000000000000000000000000000000000000版本差异Julia 1.0 中该函数更名为bitstring见英文原版 julia.md 中的bitstring(12345)。2.5 布尔值与比较运算布尔值是原生类型true false !true # false # 逻辑非 !false # true 1 1 # true 2 1 # false 1 ! 1 # false 2 ! 1 # true 1 10 # true 1 10 # false 2 2 # true 2 2 # true # 比较可以链式书写与 Python 类似多数语言不支持 1 2 3 # true 2 3 2 # false2.6 字符串、字符与插值Isso é uma String. # 字符串用双引号 a # 字符字面量用单引号Julia 从 1 开始索引与 MATLAB 一致而非多数语言的 0 起始Isso é uma string[1] # I # 取第 1 个字符不过原教程特意提醒对 UTF-8 编码的字符串直接按索引取字符并不安全多字节字符会破坏索引语义因此推荐用迭代map、for循环等而非索引来遍历字符串。英文原版 julia.md 补充了安全做法仅含 ASCII 字符的字符串才可放心索引例如ascii(This is a string)[1]。字符串插值用$加括号包裹任意 Julia 表达式2 2 $(2 2) # 2 2 4格式化输出可用printf宏0.3 时代直接可用Julia 1.0 起需先using Printf加载标准库模块printf %d é menor que %f 4.5 5.3 # 输出5 é menor que 5.300000屏幕输出极其简单println(Eu sou Julia. Prazer em conhece-lo!) # 输出Eu sou Julia. Prazer em conhece-lo!3. 变量与集合Variáveis e coleções3.1 变量声明与命名约定Julia不需要在赋值前声明变量some_var 5 # 5 some_var # 5访问未赋值的变量会报错try some_other_var # ERROR: some_other_var não definida未定义 catch e println(e) end变量名以字母开头之后可以包含字母、数字、下划线和感叹号SomeOtherVar123! 6 # 6Unicode 变量名被广泛支持尤其适合数学记号☃ 8 # 8 # 雪人符号也是合法变量名 2 * π # 6.283185307179586 # 数学常量 π3.2 Julia 命名约定速查表对象约定示例类型大写字母开头CamelCaseTiger、Int64函数/宏全小写不用下划线push!、println变量小写下划线分隔仅在难以阅读时使用some_var就地修改函数名称以!结尾变异函数/就地函数push!、sort!3.3 数组Array数组存储一组由整数 1 到 n 索引的值a Int64[] # 0-element Int64 Array空数组元素类型 Int64 # 一维数组字面量用逗号分隔 b [4, 5, 6] # 3-element Int64 Array: [4, 5, 6] b[1] # 4 b[end] # 6 # end 是最后一个索引的简写 # 二维数组空格分隔列值分号分隔行 matrix [1 2; 3 4] # 2x2 Int64 Array: [1 2; 3 4]数组增删操作以!结尾表示就地修改push!(a, 1) # [1] # 追加到末尾 push!(a, 2) # [1, 2] push!(a, 4) # [1, 2, 4] push!(a, 3) # [1, 2, 4, 3] append!(a, b) # [1,2,4,3,4,5,6] # 拼接整个数组 pop!(b) # 6 # 弹出末尾元素b 变为 [4,5] push!(b, 6) # b 恢复为 [4,5,6] a[1] # 1 # 再次强调Julia 从 1 开始索引 a[end] # 6 # end 可用于任何索引表达式 # 0.3 版本的头尾操作 shift!(a) # 1 # 弹出头部元素a 变为 [2,4,3,4,5,6] unshift!(a, 7) # [7,2,4,3,4,5,6] # 在头部插入版本差异Julia 1.0 起shift!/unshift!更名为popfirst!/pushfirst!见英文原版 julia.md。!后缀的含义验证——sort与sort!的对比是最经典的例子arr [5, 4, 6] # 3-element Int64 Array: [5,4,6] sort(arr) # [4,5,6] # 返回新数组arr 仍是 [5,4,6] sort!(arr) # [4,5,6] # 就地排序arr 现在是 [4,5,6]越界访问会抛出BoundsErrortry a[0] # ERROR: BoundsError() in getindex at array.jl:270 a[end 1] # ERROR: BoundsError() in getindex at array.jl:270 catch e println(e) end原教程指出错误信息会列出出错的行号和文件名即使错误来自标准库也是如此。如果从源码构建 Julia可以在 Julia 目录下的base文件夹中找到这些源文件。区间Range与切片a [1:5;] # 5-element Int64 Array: [1,2,3,4,5] # 用区间初始化数组 a[1:3] # [1, 2, 3] # 切片语法 a[2:end] # [2, 3, 4, 5]版本差异英文原版提醒a [1:5]不带分号在 Julia 1.0 中得到的是包含一个UnitRange的数组只有[1:5;]才会展开成元素数组。按索引删除元素用splice!arr [3, 4, 5] splice!(arr, 2) # 4 # 删除并返回索引 2 处的元素 arr # [3, 5]成员判断与长度b [1, 2, 3] append!(a, b) # a 现在为 [1, 2, 3, 4, 5, 1, 2, 3] in(1, a) # true # 判断元素是否存在 length(a) # 8 # 获取长度3.4 元组Tuple不可变的序列tup (1, 2, 3) # (1,2,3) # 一个 (Int64,Int64,Int64) 元组 tup[1] # 1 try tup[1] 3 # ERROR: não há método setindex!((Int64,Int64,Int64),Int64,Int64) catch e println(e) end元组不可变但多数数组函数同样适用length(tup) # 3 tup[1:2] # (1,2) in(2, tup) # true**解包unpacking**是元组的核心用法a, b, c (1, 2, 3) # (1,2,3) # a1, b2, c3 d, e, f 4, 5, 6 # (4,5,6) # 省略括号也能创建元组单元素元组与普通值不同(1,) 1 # false (1) 1 # true交换两个变量只需一行e, d d, e # (5,4) # d 现在是 5e 现在是 43.5 字典Dictempty_dict Dict() # Dict{Any,Any}() # 空字典 # 用字面量创建字典0.3 语法 filled_dict [one 1, two 2, three 3] # Dict{ASCIIString,Int64} filled_dict[one] # 1 # 用 [] 取值版本差异Julia 1.0 推荐Dict(one 1, ...)写法且键类型显示为String而非ASCIIString见英文原版 julia.md。键与值的遍历keys(filled_dict) # KeyIterator{Dict{ASCIIString,Int64}}([three3,one1,two2]) # 注意字典键既无序也不按插入顺序排列 values(filled_dict) # ValueIterator{Dict{ASCIIString,Int64}}([three3,one1,two2])键存在性检查用in与haskeyin((one, 1), filled_dict) # true in((two, 3), filled_dict) # false haskey(filled_dict, one) # true haskey(filled_dict, 1) # false查找不存在的键会抛错可用get提供默认值规避try filled_dict[four] # ERROR: key not found: four in getindex at dict.jl:489 catch e println(e) end # get(dictionary, key, default_value) get(filled_dict, one, 4) # 1 # 键存在返回 1 get(filled_dict, four, 4) # 4 # 键不存在返回默认值 43.6 集合Set无序唯一值empty_set Set() # Set{Any}() filled_set Set(1, 2, 2, 3, 4) # Set{Int64}(1,2,3,4) # 重复值 2 自动去重 push!(filled_set, 5) # Set{Int64}(5,4,2,3,1) in(2, filled_set) # true in(10, filled_set) # false版本差异Julia 1.0 中集合构造推荐传数组Set([1, 2, 2, 3, 4])。集合运算交集、并集、差集other_set Set(3, 4, 5, 6) # Set{Int64}(6,4,5,3) intersect(filled_set, other_set) # Set{Int64}(3,4,5) union(filled_set, other_set) # Set{Int64}(1,2,3,4,5,6) setdiff(Set(1,2,3,4), Set(2,3,5)) # Set{Int64}(1,4)4. 控制流Controle de fluxo4.1 if / elseif / else缩进在 Julia 中没有语义意义代码块由end界定some_var 5 if some_var 10 println(some_var 完全大于 10。) elseif some_var 10 # elseif 子句可选 println(some_var 小于 10。) else # else 子句也可选 println(some_var 恰好等于 10。) end # 输出 some_var 小于 10。4.2 for 循环for循环遍历一切可迭代对象Range、Array、Set、Dict、String 等# 用 或 in 均可两种写法等价 for animal [dog, cat, mouse] println($animal is a mammal) end # 输出 # dog is a mammal # cat is a mammal # mouse is a mammal for animal in [dog, cat, mouse] println($animal is a mammal) end # 输出同上遍历字典的两种模式——先取 Pair 再解包或直接解构for a in [dogmammal,catmammal,mousemammal] println($(a[1]) is a $(a[2])) end # 输出 # dog is a mammal # cat is a mammal # mouse is a mammal for (k, v) in [dogmammal,catmammal,mousemammal] println($k is a $v) end # 输出同上4.3 while 循环x 0 while x 4 println(x) x 1 # 即 x x 1 的简写 end # 输出 # 0 # 1 # 2 # 34.4 异常处理 try/catchtry error(help) catch e println(caught it $e) end # caught it ErrorException(help)error抛出ErrorException被catch e捕获后可查看异常对象。5. 函数Funções5.1 基本定义与返回值用function关键字定义函数函数返回其最后一个语句的值# function name(arglist) # corpo... # end function add(x, y) println(x is $x and y is $y) x y # 最后一个表达式即返回值 end add(5, 6) # 先打印 x is 5 and y is 6再返回 11变长参数用...称为 splatfunction varargs(args...) return args # 用 return 关键字可在函数任意位置提前返回 end # varargs (generic function with 1 method) varargs(1, 2, 3) # (1,2,3)splat 的两种用法——定义时收集参数、调用时展开参数# 调用时展开 Array 或 Tuple 内容为参数列表 Set([1,2,3]) # Set{Array{Int64,1}}([1,2,3]) # 这是「一个包含数组的集合」 Set([1,2,3]...) # Set{Int64}(1,2,3) # 等价于 Set(1,2,3) x (1,2,3) # (1,2,3) Set(x) # Set{(Int64,Int64,Int64)}((1,2,3)) # 一个包含元组的集合 Set(x...) # Set{Int64}(2,3,1) # 展开成三个元素5.2 可选位置参数function defaults(a, b, x5, y6) return $a $b and $x $y end defaults(h, g) # h g and 5 6 defaults(h, g, j) # h g and j 6 defaults(h, g, j, k) # h g and j k try defaults(h) # ERROR: no method defaults(Char,) defaults() # ERROR: no methods defaults() catch e println(e) end注意参数个数不足时错误是MethodError找不到匹配的方法——这正是 Julia「函数 泛型函数 多个方法」模型的外在表现。5.3 关键字参数关键字参数在参数列表中使用分号;与位置参数分隔function keyword_args(;k14, name2hello) return [k1k1, name2name2] end keyword_args(name2ness) # [name2ness, k14] keyword_args(k1mine) # [k1mine, name2hello] keyword_args() # [name2hello, k14]5.4 组合所有参数类型function all_the_args(normal_arg, optional_positional_arg2; keyword_argfoo) println(normal arg: $normal_arg) println(optional arg: $optional_positional_arg) println(keyword arg: $keyword_arg) end all_the_args(1, 3, keyword_arg4) # 输出 # normal arg: 1 # optional arg: 3 # keyword arg: 45.5 一等函数与匿名函数Julia 拥有一等函数函数可以作为值传递与返回function create_adder(x) adder function (y) return x y end return adder end「箭头 lambda」语法创建匿名函数(x - x 2)(3) # true下面的写法与上面的create_adder实现完全等价——y - x y本身就是返回值function create_adder(x) y - x y end也可以给内部函数命名function create_adder(x) function adder(y) x y end adder end add_10 create_adder(10) add_10(3) # 135.6 内置高阶函数与列表推导map(add_10, [1,2,3]) # [11, 12, 13] filter(x - x 5, [3, 4, 5, 6, 7]) # [6, 7]**列表推导comprehension**是更优雅的映射方式[add_10(i) for i[1, 2, 3]] # [11, 12, 13] [add_10(i) for i in [1, 2, 3]] # [11, 12, 13] # 英文原版还展示了带过滤条件的推导 [x for x in [3, 4, 5, 6, 7] if x 5] # [6, 7]6. 类型系统Tipos6.1 typeof 与一等类型每个值都有类型但变量本身没有类型。用typeof获取值的类型typeof(5) # Int64类型是一等值typeof(Int64) # DataType typeof(DataType) # DataType # DataType 是「表示类型的类型」包括它自身类型用于文档、优化与分派dispatch但不做静态检查。6.2 定义具体类型在 Julia 0.3 中用type关键字定义类 struct 的新类型# type Name # field::OptionalType # ... # end type Tiger taillength::Float64 # 带类型标注的字段 coatcolor # 不带类型标注等价于 ::Any end # 默认构造器的参数即类型字段按定义顺序 tigger Tiger(3.5, orange) # Tiger(3.5,orange) # 类型本身兼作该类型值的构造器函数 sherekhan typeof(tigger)(5.6, fire) # Tiger(5.6,fire)版本差异Julia 1.0 起type更名为structabstract type Cat end替代abstract Cat见英文原版 julia.md。两者语义一致这类 struct 风格的类型称为具体类型concrete types可以被实例化但不能有子类型。6.3 抽象类型与类型层次abstract Cat # 抽象类型只是类型层次中的一个名字和位置点 # 抽象类型不能被实例化但可以有子类型 # 例如 Number 就是抽象类型 subtypes(Number) # 6-element Array{Any,1}: # Complex{Float16} # Complex{Float32} # Complex{Float64} # Complex{T:Real} # ImaginaryUnit # Real subtypes(Cat) # 0-element Array{Any,1}每个类型都有父类型用super获取typeof(5) # Int64 super(Int64) # Signed super(Signed) # Real super(Real) # Number super(Number) # Any super(super(Signed)) # Number super(Any) # Any # 除 Int64 外上述所有类型都是抽象类型版本差异Julia 1.0 中super更名为supertype且类型链变为Int64 → Signed → Integer → Real → Number → Any英文原版中Signed的父类型是Integer。:是子类型运算符type Lion : Cat # Lion 是 Cat 的子类型 mane_color roar::String end6.4 外部构造器与内部构造器可以为类型定义更多构造器——只需定义与类型同名、返回该类型值的函数# 外部构造器定义在类型定义体之外 Lion(roar::String) Lion(green, roar) type Panther : Cat eye_color Panther() new(green) # 内部构造器定义在类型体内用 new 构造 # Panther 将只有这一个构造器不再有默认构造器 end原教程的实践建议非常明确内部构造器如 Panther 的做法让你完全掌控值的创建方式只要可能优先使用外部构造器而非内部构造器。7. 多重分派Multiple Dispatch7.1 泛型函数与方法Julia 中所有具名函数都是泛型函数generic functions由许多小方法methods堆叠而成——例如Lion的每个构造器都是泛型函数Lion的一个方法。以meow为例为不同动物类型定义同名方法function meow(animal::Lion) animal.roar # 用点号 . 访问类型属性 end function meow(animal::Panther) grrr end function meow(animal::Tiger) rawwwr end # 测试 meow meow(tigger) # rawwr meow(Lion(brown,ROAAR)) # ROAAR meow(Panther()) # grrr子类型关系验证issubtype(Tiger, Cat) # false issubtype(Lion, Cat) # true issubtype(Panther, Cat) # true定义接收Cat的函数所有 Cat 子类型自动适用function pet_cat(cat::Cat) println(The cat says $(meow(cat))) end pet_cat(Lion(42)) # 输出 The cat says 42 try pet_cat(tigger) # ERROR: no method pet_cat(Tiger,) # Tiger 不是 Cat catch e println(e) end7.2 所有参数共同参与分派面向对象语言通常采用单分派方法仅根据第一个参数的类型选择Julia 中所有参数类型共同参与最佳方法的选择。下面的fight系列最能说明问题function fight(t::Tiger, c::Cat) println(The $(t.coatcolor) tiger wins!) end # fight (generic function with 1 method) fight(tigger, Panther()) # 输出 The orange tiger wins! fight(tigger, Lion(ROAR)) # 输出 The orange tiger wins! # 当第二个参数具体是 Lion 时改用更特化的方法 fight(t::Tiger, l::Lion) println(The $(l.mane_color)-maned lion wins!) # fight (generic function with 2 methods) fight(tigger, Panther()) # 输出 The orange tiger wins! fight(tigger, Lion(ROAR)) # 输出 The green-maned lion wins! # 没有 Tiger 也能打架 fight(l::Lion, c::Cat) println(The victorious cat says $(meow(c))) # fight (generic function with 3 methods) fight(Lion(balooga!), Panther()) # 输出 The victorious cat says grrr try fight(Panther(), Lion(RAWR)) # ERROR: no method fight(Panther,Lion) catch end7.3 方法歧义ambiguity当两个方法对同一组实参都「同样合适」时Julia 会发出歧义警告fight(c::Cat, l::Lion) println(The cat beats the Lion) # Warning: New definition # fight(Cat,Lion) at none:1 # is ambiguous with # fight(Lion,Cat) at none:2. # Make sure # fight(Lion,Lion) # is defined first. # fight (generic function with 4 methods) # 这个警告是因为无法确定 fight(Lion, Lion) 会调用哪个方法 fight(Lion(RAR), Lion(brown,rarrr)) # 输出 The victorious cat says rarrr # 该结果在不同 Julia 版本中可能不同解决办法是显式定义最具体的歧义消除方法fight(l::Lion, l2::Lion) println(The lions come to a tie) fight(Lion(RAR), Lion(brown,rarrr)) # 输出 The lions come to a tie英文原版 julia.md 对此有更严谨的表述在新版 Julia 中未定义fight(::Lion, ::Lion)时调用会直接抛出MethodError: fight(::Lion, ::Lion) is ambiguous并提示「Possible fix, define fight(::Lion, ::Lion)」。7.4 底层查看 LLVM 与汇编代码Julia 的分派之所以高效是因为它在运行时为每种具体参数类型组合即时编译出专用代码。用code_native可以直接查看生成的汇编square_area(l) l * l # square_area (generic function with 1 method) square_area(5) # 25 # 喂入 Int32 时发生了什么 code_native(square_area, (Int32,)) # .section __TEXT,__text,regular,pure_instructions # Filename: none # Source line: 1 # 函数序言 # push RBP # mov RBP, RSP # Source line: 1 # movsxd RAX, EDI # 从内存取出 l # imul RAX, RAX # 计算 l 的平方结果存于 RAX # pop RBP # 恢复旧的基址指针 # ret # 结果保留在 RAX 中 code_native(square_area, (Float32,)) # ... # vmulss XMM0, XMM0, XMM0 # 单精度标量乘法AVX # ... code_native(square_area, (Float64,)) # ... # vmulsd XMM0, XMM0, XMM0 # 双精度标量乘法AVX # ...注意只要任一参数是浮点数Julia 就会自动改用浮点指令。再看一个触发整数→浮点类型提升的圆面积例子circle_area(r) pi * r * r # circle_area (generic function with 1 method) circle_area(5) # 78.53981633974483 code_native(circle_area, (Int32,)) # ... # vcvtsi2sd XMM0, XMM0, EDI # 从内存加载整数 r # movabs RAX, 4593140240 # 加载 pi 常量 # vmulsd XMM1, XMM0, QWORD PTR [RAX] # pi * r # vmulsd XMM0, XMM0, XMM1 # (pi * r) * r # ...从汇编可见整型r先经vcvtsi2sd转换为双精度再与pi常量做两次vmulsd乘法。这就是「类型驱动的即时编译JIT」——参数类型越具体生成的机器码越精简也是 Julia 在技术计算领域兼具 Python 式易用性与原生性能的根本原因。英文原版 julia.md 中code_native增加了syntax :intel参数以指定 Intel 汇编风格。8. 延伸阅读与仓库对照原教程的结尾建议读者查看官方 Julia 手册与用户邮件列表获取更多帮助。在当前仓库中你可以进一步对照与精读英文原版Julia 1.0julia.md——新增了整数下溢/溢出演示10^19回绕、big(10)^19任意精度、字符串字典序比较、copy浅拷贝、带过滤的列表推导、SubString类型层次等内容是迁移到新版 Julia 的第一手资料中文版教程zh-cn/julia.md——中文母语读者可快速对照复习其他语言译本仓库还收录了 es/julia.md、ja/julia.md、ru/julia.md 等多个语言版本可对比同一主题的不同表述仓库贡献规范若希望以同样「以代码为文档」的风格贡献或翻译教程请阅读 CONTRIBUTING.md 与 README.md仓库辅助工具lint/frontmatter.pyFrontmatter 校验与 lint/encoding.sh编码检查展示了这类教程文档的工程化维护方式。结语从基础类型、集合操作、控制流、函数设计到类型系统与多重分派再到code_native揭示的 LLVM/汇编级细节——本文完整覆盖了 pt-br/julia.md 的全部知识脉络并补充了 Julia 0.3 与 1.0 的语法差异对照。建议读者在 REPL 中逐段运行文中的代码先体验「一切皆表达式」与「按类型分派」的直觉再对照英文原版 julia.md 完成向新版语法的迁移即可快速建立 Julia 从语法到运行机制的完整认知体系。赞分享文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载相关推荐learnxinyminutes-docs 仓库 Julia 速成教程深度解析从基础类型、集合到多重分派的完整实战指南learnxinyminutes docs 仓库 Julia 速成教程深度解析从基础类型、集合到多重分派的完整实战指南 本文以 learnxinyminute文档教程learnxinyminutes-docs 中的 JavaScript 入门教程从基础语法、函数闭包到原型链全解析learnxinyminutes docs 中的 JavaScript 入门教程从基础语法、函数闭包到原型链全解析 导读 本文以开源仓库 learnxiny文档教程learnxinyminutes-docs 仓颉语言极速入门从 cangjie.md 全特性代码导览到实战要点learnxinyminutes docs 仓颉语言极速入门从 cangjie.md 全特性代码导览到实战要点 本文以本仓库根目录下的 cangjie.md文档教程上一篇Plain Craft Launcher 2终极高效的Minecraft启动器深度技术解析下一篇思源宋体CN免费开源字体终极指南7种字重一站式解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表