倉頡編程語言青少年基礎教程:enum(枚舉)類型和Option類型

倉頡編程語言青少年基礎教程:enum(枚舉)類型和Option類型

enum 和 Option 各自解決一類“語義級”問題:

enum 讓“取值只在有限集合內”的約束從注釋變成編譯器強制;

Option 讓“值可能不存在”的語義顯式化。

enum類型

enum 類型提供了通過列舉一個類型的所有可能取值來定義此類型的方式。

定義 enum 時需要把它所有可能的取值一一列出,稱這些值為 enum 的構造器(constructor)。

倉頡的枚舉(enum)類型,簡單說就是:通過把一個類型所有可能的 “選項” 列出來,來定義這個類型。

枚舉只能定義在文件的最頂層(不能嵌套在函數或其他類型里)。

枚舉的定義

基本語法:

enum <類型名> {

??? | <構造器1> [參數]

??? | <構造器2> [參數]

??? ......

??? | ... // 非窮舉(non-exhaustive)構造器,只能有一個且在最后

}

說明:用enum關鍵字開頭,后面跟類型名,大括號里列出所有可能的 “選項”(官方叫 “構造器”),選項之間用|隔開。

? ?? 構造器分無參(如 Red)和有參(如 Red(UInt8))

? ?? 支持同名構造器(需參數個數不同)

? ?? 可包含遞歸定義(構造器參數使用自身類型)

? ?? 可添加 ... 作為最后一個構造器(non-exhaustive enum,不可直接匹配)

注意,構造器(constructor)的含義,枚舉的 “構造器” = 枚舉類型的 “所有可能取值”,和類里的 “構造器(構造函數)” 不是一回事。

基本示例源碼:

// 1. 頂層 enum 定義
enum RGBColor {| Red | Green                 // 無參構造器| Blue(UInt8)                 // 有參構造器(亮度值)// 成員函數:打印顏色信息public func describe(): Unit {      // ① 必須顯式寫出返回類型 Unitmatch (this) {                   // ② match 后面要加括號case Red => println("Red")case Green => println("Green")case Blue(brightness) => println("Blue with brightness: ${brightness}") // ③ 字符串插號語法}}
}// 2. 主函數入口
main(): Int64 {                        let red   = RGBColor.Red            // 全名訪問,穩妥let green = RGBColor.Green          //  為避免歧義,統一加類型名let blue  = RGBColor.Blue(150)red.describe()    // 輸出:Redgreen.describe()  // 輸出:Greenblue.describe()   // 輸出:Blue with brightness: 150return 0                        
}

編譯運行截圖:

使用(創建枚舉的實例的)規則

? ?? 通過 類型名.構造器 或直接用構造器創建實例(無歧義時)

? ?? 名字沖突時必須加類型名(如與變量 / 函數同名)

例如:

let c1 = Color.Red? // 完整寫法

let c2 = Red?????? // 簡寫,前提是不跟別的 Red 沖突

如果當前作用域里已經有一個變量叫 Red,那就必須寫全名 Color.Red,否則編譯器會以為你在用那個變量。

完整示例:

enum Color {| Red| Yellow| Green
}// 模擬變量名沖突
let Red = "字符串變量Red"func message(light: Color): String {match (light) {case Red    => "停!" case Yellow => "注意!"case Green  => "通行!"}
}main() {let light = Yellow     // 可以用 Yellow 或Color.Yellowprintln(message(light))             // 輸出:注意!let light2 = Green   // 可以用 Green 或Color.Greenprintln(message(light2))             // 輸出:通行!let light3 = Color.Red    // 只能用Color.Red ,不能用Redprintln(message(light3))             // 輸出:停!  println(Red) //  輸出:字符串變量Red
}

編譯運行輸出:

注意!
通行! ? ? ??
停!
字符串變量Red

重要事項說明

1.構造器比較靈活:
(1)可以帶參數(帶附加信息)
比如想表示 “紅色的亮度”,可以給Red加個參數(比如 0-255 的數值):
enum RGBColor {
| Red(UInt8) | Green(UInt8) | Blue(UInt8)
}
// 比如 Red(255) 就表示“亮度為255的紅色”

(2)可以有同名選項,但參數個數必須不同
比如既可以有 “單純的紅色”(不帶參數),也可以有 “帶亮度的紅色”(帶參數):
plaintext
enum RGBColor {
| Red | Green | Blue ?// 不帶參數的選項
| Red(UInt8) | Green(UInt8) | Blue(UInt8) ?// 帶參數的同名選項(參數個數不同)
}

(3)可以有一個 “省略號選項”...
加在最后,表示 “還有其他沒列出來的選項”(這種枚舉叫 non-exhaustive enum)。用的時候不能直接匹配這個...,得用通配符_(比如 “其他所有情況”):
plaintext
enum T {
| Red | Green | Blue | ... ?// 最后一個是省略號,表示還有其他可能
}

2.枚舉可以 “自己包含自己”(遞歸定義)
枚舉的選項參數可以是它自己的類型,這在定義復雜結構時很有用。
比如定義一個 “數學表達式” 類型:
? ?可以是一個數字(Num)
? ?可以是兩個表達式相加(Add)
? ?可以是兩個表達式相減(Sub)
可以這樣寫:
enum Expr {
| Num(Int64) ?// 數字,參數是具體數值(比如Num(5))
| Add(Expr, Expr) ?// 加法,參數是兩個表達式(比如Add(Num(2), Num(3))表示2+3)
| Sub(Expr, Expr) ?// 減法,同理
}
這樣你就能表達 1 + (2 - 3) 這樣的嵌套結構。
完整示例源碼如下:

// 定義遞歸枚舉:表示數學表達式
enum Expr {| Num(Int64)          // 數字| Add(Expr, Expr)     // 加法| Sub(Expr, Expr)     // 減法
}// 定義一個遞歸函數:計算Expr表達式的值
func eval(expr: Expr): Int64 {match (expr) {case Num(n) => n  // 如果是數字,直接返回數值case Add(a, b) => eval(a) + eval(b) // 加法:遞歸計算左右兩邊再相加case Sub(a, b) => eval(a) - eval(b) // 減法:遞歸計算左右兩邊再相減}
}// 構造表達式:1 + (2 - 3)
let nestedExpr = Add(Num(1), // 左邊:1Sub(Num(2), Num(3)) // 右邊:2 - 3
)main(): Unit {let result = eval(nestedExpr)println(result)   // 輸出:0,因為1 + (2-3) = 1 + (-1) = 0
}

3.枚舉里可以加 “功能”(函數 / 屬性)
可以在枚舉里定義函數或屬性,但名字不能和選項(構造器)重復。完整示例源碼如下:

// 帶亮度參數的RGB顏色枚舉
enum RGBColor {| Red(UInt8)   // 紅色(亮度0-255)| Green(UInt8) // 綠色| Blue(UInt8)  // 藍色// 成員函數:打印顏色和亮度信息func printInfo() {// 使用this指代當前實例match (this) {case Red(b) => println("紅色,亮度:${b}")case Green(b) => println("綠色,亮度:${b}")case Blue(b) => println("藍色,亮度:${b}")}}// 成員函數:判斷是否為高亮度(亮度>127)func checkHighBright(): Bool {match (this) {case Red(b) => return b > 127case Green(b) => return b > 127case Blue(b) => return b > 127}}
}// 程序入口(無需func修飾)
main() {let red = RGBColor.Red(200)let green = RGBColor.Green(50)// 調用枚舉成員函數red.printInfo()          // 輸出:紅色,亮度:200println("紅色是否高亮度:${red.checkHighBright()}")  // 輸出:紅色是否高亮度:truegreen.printInfo()        // 輸出:綠色,亮度:50println("綠色是否高亮度:${green.checkHighBright()}")// 輸出:綠色是否高亮度:false
}

輸出:

紅色,亮度:200
紅色是否高亮度:true?
綠色,亮度:50 ? ? ??
綠色是否高亮度:false

Option類型

Option 是 enum 的泛型應用,專門處理 “可能為空” 的場景,通過 Some 和 None 避免空指針錯誤,是倉頡中處理不確定性的常用方式。

Option<T> 類型 —— 一種安全處理“可能無值”情況的機制。Option 類型通過Some(有值)和None(無值)兩種狀態,讓 "值是否存在" 變得顯式可控,配合模式匹配、??操作符、?操作符等工具,能安全、簡潔地處理各種可能無值的場景,是倉頡中避免空引用錯誤的重要機制。

Option 類型使用 enum 定義,它包含兩個構造器(constructor):Some 和 None。其中,Some 會攜帶一個參數,表示有值;None 不帶參數,表示無值。當需要表示某個類型可能有值,也可能沒有值時,可以選擇使用 Option 類型。

Option 是倉頡標準庫里內置的泛型枚舉,聲明如下:

enum Option<T> {
Some(T) ? // 表示“有值”,并攜帶一個 T 類型的數據
None ? ? ?// 表示“無值”
}

其中,Some() 是倉頡語言中 Option<T> 類型的一個“構造器”(constructor),用來表示“有一個值”。用法示例:

寫法???????? ??????? 含義

Some(100)?????? 表示“有一個整數 100”

Some("Hello") 表示“有一個字符串 "Hello"”

Option 類型簡潔的寫法:

?T 等價于 Option<T>? (官方寫為:?Ty 等價于 Option<Ty>。T和Ty都是Type 的縮寫,都代表“某個具體的類型”):

?Int64????? 等價于 Option<Int64>

?String???? 等價于 Option<String>

?Bool?????? 等價于 Option<Bool>

例如

// 完整寫法
let a: Option<Int64> = Some(100) ?// 有值:100
let b: Option<String> = Some("Hello") ?// 有值:"Hello"
let c: Option<Int64> = None ?// 無值

// 簡寫形式(?Ty)
let d: ?Int64 = Some(200) ?// 等價于Option<Int64>
let e: ?String = None ?// 等價于Option<String>

Option 類型的解構使用方式

Option 是一種非常常用的類型,所以倉頡為其提供了多種解構【注】方式,以方便 Option 類型的使用,具體包括:模式匹配、getOrThrow 函數、coalescing 操作符(??),以及問號操作符(?)。

【“解構” 在這里的核心含義是:打破 Option 類型的 “包裝”,獲取 Some 中包含的具體值,或對 None 進行處理】

1.模式匹配(match 語句)

通過match匹配Some和None,顯式處理兩種狀態。?示例:

//將Option<Int64>轉換為字符串(有值則返回值的字符串,無值返回"none")
func getString(p: ?Int64): String {match (p) {case Some(x) => "數字:${x}"  // 匹配有值狀態,x綁定具體值case None => "沒有提供數字"     // 匹配無值狀態}
}main() {let a = Some(10)let b: ?Int64 = Noneprintln(getString(a))  // 輸出:數字:10println(getString(b))  // 輸出:沒有提供數字
}

2. coalescing 操作符(??

用于為None提供默認值,語法:e1 ?? e2

? ?? 若e1是Some(v),返回v

? ?? 若e1是None,返回e2(e2需與v同類型)

示例:

main() {let a: ?Int64 = Some(5)let b: ?Int64 = Nonelet r1 = a ?? 0 // a是Some(5),返回5let r2 = b ?? 0  // b是None,返回默認值0println(r1)  // 輸出:5println(r2)  // 輸出:0
}

3. 問號操作符(?

與.、()、[]、{}結合使用,實現對 Option 內部成員的安全訪問:

? ?? 若 Option 是Some(v),則訪問v的成員,結果用Some包裝

? ?? 若 Option 是None,則直接返回None(避免空訪問錯誤)

示例:

a.訪問結構體 / 類的成員(. 操作):

// 定義一個結構體
struct R {public var a: Int64public init(a: Int64) {this.a = a}
}main() {let r = R(100)let x: ?R = Some(r)  // 有值的Optionlet y: ?R = None     // 無值的Optionlet r1 = x?.a  // x是Some(r),訪問r.a,結果為Some(100)let r2 = y?.a  // y是None,直接返回Noneprintln(r1)  // 輸出:Some(100)println(r2)  // 輸出:None
}

b.多層訪問

問號操作符支持鏈式調用,任意一層為None則整體返回None:

class A {public var b: B = B()  // A包含B類型的b
}class B {public var c: ?C = C()  // B包含Option<C>類型的c(有值)public var c1: ?C = None // B包含Option<C>類型的c1(無值)
}class C {public var d: Int64 = 100  // C包含Int64類型的d
}main() {let a: ?A = Some(A())  // 有值的Option<A>// 多層訪問:a?.b.c?.d// a是Some,b存在;c是Some,d存在 → 結果為Some(100)let r1 = a?.b.c?.d// a?.b.c1?.d:c1是None → 結果為Nonelet r2 = a?.b.c1?.dprintln(r1)  // 輸出:Some(100)println(r2)  // 輸出:None
}

4. getOrThrow 函數

用于直接獲取Some中的值,若為None則拋出異常(需配合try-catch處理):

main() {let a: ?Int64 = Some(8)let b: ?Int64 = None// 獲取a的值(成功)let r1 = a.getOrThrow()println(r1)  // 輸出:8// 獲取b的值(失敗,拋出異常)try {let r2 = b.getOrThrow()} catch (e: NoneValueException) {println("捕獲異常:b是None")  // 輸出:捕獲異常:b是None}
}

Option 類型主要用于以下場景:

1.???? 處理可能為空的返回值:如函數可能返回有效結果或無結果(避免返回 null)

2.???? 安全的成員訪問:通過?操作符避免訪問空對象的成員

3.???? 簡化錯誤處理:用None表示 "無結果" 類錯誤,替代復雜的錯誤判斷

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/97858.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/97858.shtml
英文地址,請注明出處:http://en.pswp.cn/web/97858.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

javaEE-Spring IOCDI

目錄 1、什么是Spring&#xff1a; 2.什么是IoC: 3. 什么是控制反轉呢? 4.IoC容器具備以下優點: 5.DI是什么&#xff1a; 依賴注?方法&#xff1a; 三種注入方法的優缺點&#xff1a; Autowired注解注入存在的問題&#xff1a; Autowired和Resource的區別&#xff…

TensorFlow Lite 全面解析:端側部署方案與PyTorch Mobile深度對比

1 TensorFlow Lite 基礎介紹 TensorFlow Lite (TFLite) 是 Google 為移動設備&#xff08;Android, iOS&#xff09;、微控制器&#xff08;Microcontrollers&#xff09;和其他嵌入式設備&#xff08;如 Raspberry Pi&#xff09;開發的輕量級深度學習推理框架。它的核心目標是…

mapbox進階,使用jsts實現平角緩沖區

????? 主頁: gis分享者 ????? 感謝各位大佬 點贊?? 收藏? 留言?? 加關注?! ????? 收錄于專欄:mapbox 從入門到精通 文章目錄 一、??前言 1.1 ??mapboxgl.Map 地圖對象 1.2 ??mapboxgl.Map style屬性 1.3 ??jsts myBufferOp 緩沖區生成對對象 …

linux裝好顯卡后如何檢查

背景&#xff1a;客戶通知裝好了顯卡&#xff0c;我們去機器上查看一下一. 使用到的命令 watch -n 1 nvidia-smi 可實時查看gpu的使用率nvidia-smi 之查看一次 二、查看內存和顯存 內存使用命令 free -h,顯存使用 nvidia-smi 這只是查看的navidia, 其他品牌的會不一樣

人工智能深度學習——卷積神經網絡(CNN)

一、圖像卷積運算 對圖像矩陣與濾波器矩陣進行對應相乘再求和運算&#xff0c;轉化得到新的矩陣。 作用&#xff1a;快速定位圖像中某些邊緣特征 英文&#xff1a;convolution&#xff08;CNN&#xff09;池化層實現維度縮減 池化&#xff1a;按照一個固定規則對圖像矩陣進行處…

SaaS 建站從 0 到 1 教程:Vue 動態域名 + 后端子域名管理 + Nginx 配置

SaaS 建站從 0 到 1 教程&#xff1a;Vue 動態域名 后端子域名管理 Nginx 配置 一、什么是 SaaS 建站&#xff1f; SaaS&#xff08;Software as a Service&#xff09;建站&#xff0c;就是通過一套統一的系統&#xff0c;支持用戶在線注冊、綁定域名、快速生成專屬網站。…

關于神經網絡中回歸的概念

神經網絡中的回歸詳解 引言 神經網絡&#xff08;NeuralNetworks&#xff09;是一種強大的機器學習模型&#xff0c;可用于分類和回歸任務。本文聚焦于神經網絡中的回歸&#xff08;Regression&#xff09;&#xff0c;即預測連續輸出值&#xff08;如房價、溫度&#xff09;。…

JAVASCRIPT 前端數據庫-V9--仙盟數據庫架構-—仙盟創夢IDE

老版本 在v1 版本中我們講述了 基礎版的應用JAVASCRIPT 前端數據庫-V1--仙盟數據庫架構-—-—仙盟創夢IDE-CSDN博客接下載我們做一個更復雜的的其他場景由于&#xff0c;V1查詢字段必須 id接下來我們修改了了代碼JAVASCRIPT 前端數據庫-V2--仙盟數據庫架構-—-—仙盟創夢IDE-CS…

k8s核心資料基本操作

NamespaceNamespace是kubernetes系統中的一種非常重要資源&#xff0c;它的主要作用是用來實現多套環境的資源隔離或者多租戶的資源隔離。默認情況下&#xff0c;kubernetes集群中的所有的Pod都是可以相互訪問的。但是在實際中&#xff0c;可能不想讓兩個Pod之間進行互相的訪問…

PostgreSQL——分區表

分區表一、分區表的意義二、傳統分區表2.1、繼承表2.2、創建分區表2.3、使用分區表2.4、查詢父表還是子表2.5、constraint_exclusion參數2.6、添加分區2.7、刪除分區2.8、分區表相關查詢2.9、傳統分區表注意事項三、內置分區表3.1、創建分區表3.2、使用分區表3.3、內置分區表原…

Linux任務調度全攻略

Linux下的任務調度分為兩類&#xff0c;系統任務調度和用戶任務調度。系統任務調度&#xff1a;系統周期性所要執行的工作&#xff0c;比如寫緩存數據到硬盤、日志清理等。在/etc目錄下有一個crontab文件&#xff0c;這個就是系統任務調度的配置文件。/etc/crontab文件包括下面…

回溯算法通關秘籍:像打怪一樣刷題

&#x1f680; 回溯算法通關秘籍&#xff1a;像打怪一樣刷題&#xff01; 各位同學&#xff0c;今天咱們聊聊 回溯算法&#xff08;Backtracking&#xff09;。它聽起來玄乎&#xff0c;但其實就是 “暴力搜索 剪枝” 的優雅版。 打個比方&#xff1a;回溯就是在迷宮里探險&am…

嵌入式Linux常用命令

&#x1f4df; 核心文件與目錄操作pwd-> 功能: 打印當前工作目錄的絕對路徑。-> 示例: pwd -> 輸出 /home/user/projectls [選項] [目錄]-> 功能: 列出目錄內容。-> 常用選項:-l: 長格式顯示&#xff08;詳細信息&#xff09;-a: 顯示所有文件&#xff08;包括隱…

深入理解 Linux 內核進程管理

在 Linux 系統中&#xff0c;進程是資源分配和調度的基本單位&#xff0c;內核對進程的高效管理直接決定了系統的性能與穩定性。本文將從進程描述符的結構入手&#xff0c;逐步剖析進程的創建、線程實現與進程終結的完整生命周期&#xff0c;帶您深入理解 Linux 內核的進程管理…

ACP(三):讓大模型能夠回答私域知識問題

讓大模型能夠回答私域知識問題 未經過特定訓練答疑機器人&#xff0c;是無法準確回答“我們公司項目管理用什么工具”這類內部問題。根本原因在于&#xff0c;大模型的知識來源于其訓練數據&#xff0c;這些數據通常是公開的互聯網信息&#xff0c;不包含任何特定公司的內部文檔…

使用Xterminal連接Linux服務器

使用Xterminal連接Linux服務器&#xff08;VMware虛擬機&#xff09;的步驟如下&#xff0c;前提是虛擬機已獲取IP&#xff08;如 192.168.31.105&#xff09;且網絡互通&#xff1a; 一、準備工作&#xff08;服務器端確認&#xff09;確保SSH服務已安裝并啟動 Linux服務器需要…

ChatBot、Copilot、Agent啥區別

以下內容為AI生成ChatBot&#xff08;聊天機器人&#xff09;、Copilot&#xff08;副駕駛&#xff09;和Agent&#xff08;智能體/代理&#xff09;是AI應用中常見的三種形態&#xff0c;它們在人機交互、自動化程度和任務處理能力上有著顯著的區別。特征維度ChatBot (聊天機器…

2025 年大語言模型架構演進:DeepSeek V3、OLMo 2、Gemma 3 與 Mistral 3.1 核心技術剖析

編者按&#xff1a; 在 Transformer 架構誕生八年之際&#xff0c;我們是否真的見證了根本性的突破&#xff0c;還是只是在原有設計上不斷打磨&#xff1f;今天我們為大家帶來的這篇文章&#xff0c;作者的核心觀點是&#xff1a;盡管大語言模型在技術細節上持續優化&#xff0…

基于Matlab GUI的心電信號QRS波群檢測與心率分析系統

心電信號&#xff08;Electrocardiogram, ECG&#xff09;是臨床診斷心臟疾病的重要依據&#xff0c;其中 QRS 波群的準確檢測對于心率分析、心律失常診斷及自動化心電分析系統具有核心意義。本文設計并實現了一套基于 MATLAB GUI 的心電信號處理與分析系統&#xff0c;集成了數…

1臺SolidWorks服務器能帶8-10人并發使用

在工業設計和機械工程領域&#xff0c;SolidWorks作為主流的三維CAD軟件&#xff0c;其服務器部署方案直接影響企業協同效率。通過云飛云共享云桌面技術實現多人并發使用SolidWorks時&#xff0c;實際承載量取決于硬件配置、網絡環境、軟件優化等多維度因素的綜合作用。根據專業…