资讯详情

learnxinyminutes-docs 仓颉语言极速入门:从 cangjie.md 全特性代码导览到实战要点

📅 2026/10/5 10:19:31 | 华诺云谱 👁 阅读
learnxinyminutes-docs 仓颉语言极速入门:从 cangjie.md 全特性代码导览到实战要点
文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载本文以本仓库根目录下的 cangjie.md 为核心骨架完整解读这份Learn X in Y minutes风格的仓颉Cangjie语言导览。仓颉是一门静态类型的通用编程语言表层语法接近 C 系语言同时提供类型推断、表达式化控制流、代数枚举、模式匹配、类、接口、泛型、属性、函数值与操作符重载等现代语言特性。读完本文你将掌握用cjc编译单文件、用cjpm组织工程的完整流程并逐一理解仓颉在变量、控制流、集合、函数、面向对象与模式匹配方面的核心写法能够在真实工程中快速上手。文档定位一份可运行的代码即教程本仓库 README.md 明确说明这里的每一篇文档都是以有效、带注释的代码呈现的旋风式语言导览Whirlwind tours presented as valid, commented code and explained as they go。这与本仓库其他语言文档如根目录下的 python.md、rust.md的体例完全一致文档本身就是一份可以编译运行的示例程序边运行边讲解。仓库还提供了该文档的中文翻译版本 zh-cn/cangjie.md两版内容一一对应便于对照学习。同时仓库在 lint/frontmatter.py 中实现了对每篇文档 YAML 前置元数据name、filename、contributors、translators等键的自动化校验这从工程层面保证了文档结构的规范性——读者在阅读任何一篇导览时都可以依赖其前置元数据快速定位贡献者与文件名。快速上手从单文件编译到工程管理仓颉源文件以**包声明package declaration**开始导入语句紧跟其后。示例开篇给出了最小的可运行骨架// Source files begin with a package declaration. package learnxinyminutes // Imports come after the package declaration. import std.convert.* import std.math.* import std.random.* // With the Cangjie SDK, a single file can be compiled with: // cjc learncangjie.cj // Larger projects normally use cjpm and a cjpm.toml manifest. // Single-line comments start with two slashes. /* Multi-line comments look like this. */这里透露出两个关键的工程事实单文件场景安装仓颉 SDK 后直接执行cjc learncangjie.cj即可编译单个源文件大型工程场景较大项目通常使用cjpm包管理工具并配合cjpm.toml清单文件组织依赖与构建配置。注释方面单行注释以两个斜杠//开头多行注释使用/* ... */与 C 系语言保持一致。导入使用通配符形式如import std.convert.*一次性引入标准库某个包下的全部成员这与后文标准库初探一节中的std.math、std.random、std.convert三个包形成呼应——它们正是这份导览运行时所依赖的核心标准库模块。程序入口、输出、输入与变量创建与 C 语言类似main是仓颉可执行程序的入口其返回类型为Int64// main is the entry point of an executable program. main(): Int64 { // println writes a line to standard output. println(Hello, Cangjie!) // print writes without appending a newline. print(This prompt stays on the same line: ) println(done) // readln() reads one line from standard input as a String. // Keep this commented so the tour can run without waiting for input. // let rawInput readln() // let parsedNumber Int64.parse(rawInput) // Create an immutable binding with let. let language: String Cangjie // Create a mutable variable with var. var releaseYear: Int64 2024 releaseYear 1 // Type annotations are often optional for local variables. let inferredInt 42 let inferredFloat 3.14159 println(${language} ${releaseYear}) println(${inferredInt}, ${inferredFloat}) learnBindings() learnStringsAndNumbers() learnControlFlow() learnCollections() learnFunctions() learnStructsClassesAndInterfaces() learnEnumsAndOptions() learnStandardLibrary() return 0 }这一节浓缩了仓颉最基础、也最日常的语法要素标准输出println输出一行并换行print输出但不追加换行标准输入readln()从标准输入读取一整行并返回String若要做数值处理需先调用Int64.parse(rawInput)进行解析示例中特意保持注释状态避免导览程序运行时阻塞等待输入绑定语义let创建不可变绑定immutable bindingvar创建可变变量mutable variablereleaseYear 1验证了var的可变性类型推断局部变量的类型标注通常可以省略let inferredInt 42会自动推断为Int64let inferredFloat 3.14159会自动推断为浮点类型字符串插值${language} ${releaseYear}使用${...}语法嵌入表达式。main依次调用八个learn*函数这既是导览的目录结构也给出了推荐的学习顺序绑定与基本类型 → 字符串与数字 → 控制流 → 集合 → 函数 → 结构体/类/接口 → 枚举与 Option → 标准库。贯穿全篇的预备声明一个迷你类型系统在进入各专题之前导览先集中声明了一批后续各节都会用到的类型。这些声明本身就是仓颉类型系统的一次总预习——结构体、接口、类、泛型、枚举、泛型函数、函数重载在这里全部亮相// Cangjie has struct for value-like records. struct Vec2 { // A primary constructor can declare fields directly. public Vec2(var x: Float64, var y: Float64) {} public func length(): Float64 { sqrt(x * x y * y) } // mut marks a struct method that changes the receiver. public mut func scale(k: Float64): Unit { x * k y * k } // Operators are functions too. public operator func (rhs: Vec2): Vec2 { Vec2(x rhs.x, y rhs.y) } public func toString(): String { (${x.format(.1)}, ${y.format(.1)}) } } // Interfaces describe behavior. Implementing types use :. interface Named { prop label: String } // Classes are reference types and can carry fields, constructors, properties, // instance methods, static methods, and operator functions. class Person : Named { let id: Int64 private let rawName: String public init(id: Int64, name: String) { this.id id this.rawName name } // Properties use get and, for mutable properties, set. public prop label: String { get() { ${id}:${rawName} } } public func greet(): Unit { println(Hello, I am ${rawName}.) } } // A compact class constructor can declare fields in the parameter list. class BoxT { public Box(var value: T) {} public func mapR(f: (T) - R): BoxR { BoxR(f(value)) } } class Directory { private let people: ArrayPerson public init(people: ArrayPerson) { this.people people } // Overload [] to make a small lookup type. public operator func [](id: Int64): ?Person { for (person in people) { if (person.id id) { return Some(person) } } return None } } // Enums are algebraic data types. Constructors can hold data. enum Command { Quit | Echo(String) | Move(Vec2) | Repeat(Int64, String) } // OptionT is an enum with Some(T) and None. // ?T is shorthand for OptionT. func firstT(items: ArrayT): ?T { if (items.size 0) { return None } return Some(items[0]) } func run(command: Command): Unit { match (command) { case Quit println(quit) case Echo(text) println(text) case Move(delta) println(move by ${delta.toString()}) case Repeat(times, text) for (_ in 0..times) { println(text) } } } func printNamedT(item: T): Unit where T : Named { println(item.label) } // Overload functions by parameter types. func twice(x: Int64): Int64 { x * 2 } func twice(x: Float64): Float64 { x * 2.0 }这段预备声明值得逐条拆解因为它几乎覆盖了仓颉类型系统的全部核心概念struct与值语义Vec2是值类型的记录value-like record。其主构造函数primary constructor直接在参数列表中声明字段var x: Float64, var y: Float64mut关键字标记会修改接收者receiver的方法scale因此可以原地改写x、y操作符在仓颉中同样以函数形式声明operator func 重载了加法运算toString配合format(.1)输出格式化后的坐标。interface与实现约束Named接口声明了一个属性prop label: String。实现接口使用:符号class Person : Named而不是其他语言常见的implements关键字。class与引用语义Person是引用类型拥有字段、构造函数、属性与实例方法。属性使用get可变属性再加set定义读写逻辑label属性在读取时动态拼出${id}:${rawName}字符串。字段可用private修饰实现封装。泛型类BoxT演示了紧凑的类构造函数——在参数列表中直接声明字段var value: T泛型方法mapR接收一个函数值f: (T) - R把BoxT变换为BoxR。操作符重载实现索引访问Directory重载[]操作符使directory[id]可以按编号查找Person返回类型为?Person即OptionPerson未找到时返回None——用类型系统显式表达可能不存在。代数数据类型enum Command的构造子可以携带数据Echo(String)、Move(Vec2)、Repeat(Int64, String)各自携带不同形态的载荷。OptionT与?TfirstT返回?T空数组返回None否则返回Some(items[0])完全绕开了空指针问题。模式匹配run用match对Command的四种形态逐一解构case Repeat(times, text)还能同时解出载荷中的两个值。泛型约束与函数重载printNamedT用where T : Named约束类型参数必须实现Named接口twice则以参数类型区分两个同名函数重载。由于这些声明会在后文各节被反复调用建议读者先通读一遍、不必强记细节等后续章节真正用到时再回头对照。绑定与基本类型显式转换与字面量进制learnBindings展示了仓颉的常用基本类型与字面量写法func learnBindings(): Unit { // Common primitive types. let ok: Bool true let signed: Int64 -42 let unsigned: UInt64 42 let f32: Float32 1.25 let f64: Float64 2.5 println(${ok}, ${signed}, ${unsigned}, ${f32}, ${f64}) // Integer literals support familiar base prefixes. let decimal: Int64 255 let binary: Int64 0b11111111 let octal: Int64 0o377 let hex: Int64 0xFF println(${decimal}, ${binary}, ${octal}, ${hex}) // Numeric conversions are explicit. let count: Int64 3 let price: Float64 19.95 let total Float64(count) * price println(total: ${total.format(.2)}) }要点归纳基本类型覆盖布尔Bool、有符号整型Int64、无符号整型UInt64、单精度浮点Float32、双精度浮点Float64进制字面量十进制直接书写二进制0b前缀、八进制0o前缀、十六进制0x前缀0b11111111、0o377、0xFF均等于十进制的255显式数值转换仓颉不允许隐式跨类型数值转换Int64转Float64必须显式调用构造形式Float64(count)这正是静态类型语言保证精度的典型做法格式化输出total.format(.2)将浮点数格式化为保留两位小数是贯穿全篇的标准库format用法。字符串、字符、元组与插值learnStringsAndNumbers聚焦文本处理与组合类型func learnStringsAndNumbers(): Unit { let name Ada let score 99.5 // String interpolation uses ${...}. println(${name} scored ${score.format(.1)}) // readln() reads a String. Parse it before numeric work. // let line readln() // let n Int64.parse(line) let csv red,green,blue let parts csv.split(,) println(parts[0]) // Rune represents a Unicode character. let letter: Rune Rune(UInt32(65)) let lineBreak: Rune Rune(UInt32(10)) let generated: Rune Rune(UInt32(65)) println(${letter}${lineBreak}${generated}) // Tuples group a fixed number of values. let pair: (String, Int64) (answer, 42) let (word, value) pair println(${word}: ${value}) }关键点插值即表达式${name} scored ${score.format(.1)}表明${...}中可以直接书写带方法调用的表达式而非仅限简单变量输入解析readln()返回String数值计算前必须显式Int64.parse(line)字符串分割csv.split(,)返回分割后的数组parts[0]取下标为 0 的元素Rune字符类型Rune表示一个 Unicode 字符由UInt32码点构造Rune(UInt32(65))即字符A元组与解构元组(String, Int64)将固定数量的值组合在一起let (word, value) pair一次性解构出两个绑定。表达式化控制流if 是表达式区间左闭右开仓颉的控制流整体是**面向表达式expression-oriented**的这是它区别于普通 C 系语言的核心体验之一func learnControlFlow(): Unit { let temperature 22.5 // if can be used for branching. if (temperature 30.0) { println(hot) } else if (temperature 10.0) { println(cold) } else { println(comfortable) } // if can also produce a value. let status if (temperature 18.0) { open } else { closed } println(status) // a..b is left-closed and right-open. for (i in 0..3) { print(${i} ) } println() // a..b includes both ends. var sum: Int64 0 for (i in 1..100) { sum i } println(sum) var x: Int64 4 while (x 0) { x - 1 } // do-while runs its body at least once. do { x 1 } while (x 2) while (true) { if (x 2) { continue } break } }逐项解读if的双重身份既能作为语句进行分支也能作为表达式产出值——let status if (...) { open } else { closed }直接把分支结果绑定给变量无需三元运算符区间语法a..b左闭右开0..3遍历 0、1、2a..b两端都包含1..100求和即 5050循环家族for ... in遍历区间或集合while先判断后执行do-while至少执行一次循环体continue/break在while (true)中配合条件跳出或提前进入下一轮迭代语义与其他语言一致。数组与集合字面量推断与重复初始化learnCollections演示了数组Array的两类创建方式与遍历func learnCollections(): Unit { // Array literals infer their element type. let primes [2, 3, 5, 7, 11] println(first prime: ${primes[0]}) // Create a fixed-size Array with a repeated initial value. var squares: ArrayInt64 Array(5, repeat: 0) for (i in 0..squares.size) { squares[i] i * i } for (value in squares) { print(${value} ) } println() let maybeFirst first(squares) if (maybeFirst.isSome()) { println(first square: ${maybeFirst.getOrThrow()}) } }要点字面量推断[2, 3, 5, 7, 11]自动推断元素类型primes[0]按下标取值固定大小 重复初值Array(5, repeat: 0)创建长度为 5、初始值全部为 0 的数组通过squares.size取长度结合区间0..squares.size完成按索引写入值遍历for (value in squares)直接遍历元素首次接触 Option 消费端first(squares)返回?Int64用isSome()判断有值后再以getOrThrow()取出——这是仓颉用类型表达可能缺失的日常写法后文枚举与 Option一节还会深入。函数、闭包与重载函数是一等值learnFunctions系统展示了函数类型、lambda、闭包与函数值func learnFunctions(): Unit { // Function types use arrows. var op: (Int64, Int64) - Int64 { a: Int64, b: Int64 a b } println(op(2, 3)) op { a: Int64, b: Int64 a * b } println(op(2, 3)) // Closures can capture local variables. let offset 10 let addOffset: (Int64) - Int64 { n: Int64 n offset } println(addOffset(5)) // Functions are values. let f: (Int64) - Int64 twice println(f(21)) println(twice(21)) println(twice(21.0).format(.1)) let boxed BoxInt64(21) let mapped boxed.map({ n: Int64 value${n} }) println(mapped.value) }核心结论函数类型用箭头(Int64, Int64) - Int64表示接收两个Int64、返回Int64的函数类型lambda 写法为{ a: Int64, b: Int64 a b }左侧是参数列表、右侧是函数体变量可重新绑定到不同函数op先指向加法 lambda再指向乘法 lambda说明函数类型变量可以重新赋值闭包捕获lambda{ n: Int64 n offset }捕获了外层局部变量offset函数即值命名函数twice可以直接赋值给函数类型变量let f: (Int64) - Int64 twice重载按参数类型分派twice(21)命中Int64版本返回整数twice(21.0)命中Float64版本返回浮点高阶泛型BoxInt64(21).map({ n value${n} })把BoxInt64变换为BoxString印证了预备声明中mapR的泛型函数类型(T) - R。结构体、类、接口、属性与操作符面向对象的完整拼图learnStructsClassesAndInterfaces是整份导览中信息密度最高的运行示例把预备声明里定义的类型全部串了起来func learnStructsClassesAndInterfaces(): Unit { var a Vec2(3.0, 4.0) let b Vec2(1.0, 2.0) let c a b println(a.length().format(.1)) println(c.toString()) a.scale(2.0) println(a.toString()) let ada Person(1, Ada) ada.greet() // Person implements Named, so it can be used by a generic function // constrained with where T : Named. printNamedPerson(ada) let directory Directory([ Person(1, Ada), Person(2, Grace), Person(3, Edsger) ]) // This calls Directory.operator[]. let maybePerson directory[2] if (maybePerson.isSome()) { let person maybePerson.getOrThrow() println(found ${person.label}) } }运行效果与设计意图值语义与操作符重载Vec2(3.0, 4.0)与Vec2(1.0, 2.0)通过重载的得到Vec2(4.0, 6.0)a.length()计算模长 5.0mut方法原地修改a.scale(2.0)因为scale以mut修饰可以原地把a变为(6.0, 8.0)若在不可变绑定上调用mut方法会编译报错引用类型与多态Person(1, Ada)是引用类型实例ada.greet()调用实例方法泛型约束的兑现Person实现了Named接口因此可以传给受where T : Named约束的printNamedPerson输出label属性值1:Ada操作符[]的调用directory[2]表面是下标访问实际触发Directory.operator[]返回?Person用isSome()/getOrThrow()取出后打印label。枚举、模式匹配与 Option用类型消灭空指针learnEnumsAndOptions把代数枚举、match与Option三种机制组合使用func learnEnumsAndOptions(): Unit { let commands: ArrayCommand [ Echo(ready), Move(Vec2(5.0, -2.0)), Repeat(2, again), Quit ] for (command in commands) { run(command) } let directory Directory([Person(1, Ada)]) let missing directory[99] match (missing) { case Some(person) println(person.label) case None println(no person with that id) } // if let style conditions are concise for one successful pattern. if (directory[1].isSome()) { let person directory[1].getOrThrow() println(hello ${person.label}) } }理解要点带数据的枚举Command的四个构造子被实例化后存入数组——Echo(ready)携带字符串、Move(Vec2(5.0, -2.0))携带坐标、Repeat(2, again)携带次数与文本、Quit不携带数据穷尽式匹配run(command)中的match对四种形态逐一给出case分支且能在分支内解构载荷如case Repeat(times, text)实现按形态分发逻辑Option显式处理缺失directory[99]找不到人返回Nonematch分别处理Some(person)与None两个分支编译器保证两个分支都被覆盖if let风格的简写当只关心一种成功模式时可先用isSome()判断、再getOrThrow()取值写出更简洁的顺序式代码。标准库初探math、random、convert 三件套导览结尾用一小段程序演示标准库三个包的典型用法func learnStandardLibrary(): Unit { // std.math.* println(sqrt(81.0)) println(abs(-12)) // std.random.* let rng Random() let dice rng.nextInt64(6) 1 println(dice: ${dice}) // std.convert.* let n Int64.parse(123) let y Float64.parse(3.5) println(${n}, ${y.format(.2)}) // Cangjie also has packages for collections, I/O, time, regex, // concurrency, testing, reflection, macros, and C interoperability. }std.mathsqrt(81.0)开平方得 9.0abs(-12)取绝对值std.randomRandom()创建随机数生成器nextInt64(6)生成[0, 6)区间的随机整数加 1 即得 16 的骰子点数std.convertInt64.parse(123)、Float64.parse(3.5)将字符串解析为数值与开篇Int64.parse(rawInput)的处理方式完全一致更广阔的标准库版图导览同时提示仓颉还提供集合collections、I/O、时间time、正则regex、并发concurrency、测试testing、反射reflection、宏macros以及 C 互操作C interoperability等包为后续深入学习划定了地图。总结仓颉与普通 C 系语言的差异文档末尾对全篇做了凝练收束指出这份导览刻意保持紧凑但已经足以展示仓颉区别于普通 C 系语言的五个核心特质表达式都有类型if、循环等控制结构可以产出值类型系统全程参与Option取代大量类 null场景?T与Some/None让可能不存在成为类型的一部分配合isSome()/getOrThrow()安全取值枚举携带数据代数数据类型把形态与载荷绑定在一起配合match实现穷尽式模式匹配接口约束泛型:与where T : Named让泛型代码既能抽象又能受检操作符与属性是普通声明operator func 、operator func []、prop的get/set都是语言中的一等声明而非编译器魔法。若想继续深入可以对照本仓库的中文版 zh-cn/cangjie.md 逐段精读并参照 README.md 了解本仓库代码即教程的文档规范——这份导览本身就是一份可直接用cjc编译运行的完整程序动手跑一遍比任何讲解都更直观。赞分享文档教程【免费下载链接】learnxinyminutes-docsCode documentation written as code! How novel and totally my idea!项目地址https://gitcode.com/gh_mirrors/le/learnxinyminutes-docs点击查看免费下载相关推荐大麦抢票自动化完整指南ticket-purchase 从环境搭建到提交订单大麦抢票自动化完整指南ticket purchase 从环境搭建到提交订单 热门演出开票即售罄手动刷新加点击常常慢半拍。大麦自动抢票项目 ticket pu文档教程CoffeeScript 语法速成指南逐句编译为 JavaScript 的现代语言入门learnxinyminutes-docs 版CoffeeScript 语法速成指南逐句编译为 JavaScript 的现代语言入门learnxinyminutes docs 版 CoffeeScri文档教程Ubuntu 24.04 上 ROCm apt update 报 Release 文件缺失3 步修好Ubuntu 24.04 上 ROCm apt update 报 Release 文件缺失3 步修好 在 Ubuntu 24.04 上跑 apt upda文档教程上一篇ParadeDB Top-K 升序 BM25 基准查询详解Stack Overflow 数据集中等选择性场景top_k_score_asc_medium_selectivity下一篇PVZ Toolkit 植物大战僵尸修改器从安装到进阶玩法的完整教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑