仓颉语言Option 的“问号”全景图—— 一个 `?` 与 `.` `()` `[]` `{}` 的组合写法

一句话先给结论

在仓颉里,? 是 Option 的"安全导航符";它能无缝插进任何"取值/调用/下标/代码块"场景,遇到 None 就立即短路返回 None,否则继续往后走。

下面带你一次看全所有花式用法。

基础规则速查表

符号 意义 是否可接 ? 短路行为
. 成员访问 None 时跳过成员访问
() 函数/方法调用 None 时跳过调用
[] 下标取值 None 时跳过取下标
{} lambda/闭包 None 时跳过闭包执行

场景示例

方法返回Option类型

cangjie 复制代码
func readFile(): ?String {
    None<String>
}
let cache: Option<String> = readFile()

?. 访问成员变量

cangjie 复制代码
import std.random.Random

let rand = Random()

struct User {
    User(let name: String) {}
}

func getUser(): ?User {
    if (rand.nextBool()) {
        User("unravel")
    } else {
        None
    }
}

let u: Option<User> = getUser() // 可能 None
let len = u?.name.size // Option<Int>

?() 调用函数

cangjie 复制代码
func twice(x: Int64): Int64 {
    x * 2
}

let f: Option<(Int64) -> Int64> = Some(twice)
let r = f?(10) // Some(20)

?[] 访问下标

cangjie 复制代码
// 安全下标
let arr: Option<Array<Int64>> = Some([7, 8, 9])
// arr存在时才可以返回值,不能保证下标越界的崩溃
let second = arr?[1] // Some(8)

?{} 传入尾随闭包

cangjie 复制代码
type IntCallFunc = ((Int64) -> Int64) -> Int64

func opFunc(action: (Int64) -> Int64): Int64 {
    action(5)
}

let op: ?IntCallFunc = opFunc
let doubled = op? {
    x => x * 2
} // Some(10)

链式混写------一次写完所有符号

cangjie 复制代码
type IntCallFunc = ((Int64) -> Int64) -> Int64

func opFunc(action: (Int64) -> Int64): Int64 {
    action(5)
}
class ContainerItem {
    func compute(): ?IntCallFunc {
        return opFunc
    }
}

class Container {
    Container(public let items: Array<?ContainerItem>) {}
}

// 链式混写------一次写完所有符号
let deep: Option<Container> = Container([ContainerItem()])
// 安全导航:取值→下标→调用→闭包
let result = deep?.items[0]?.compute()? {x => x + 1}

与 match 组合:把最终 None 转成默认值

当然,更建议使用coalescing操作符。coalescing操作符和下面的实现等价

cangjie 复制代码
let final0 = result ?? -1

let final = match (result) {
    case Some(v) => v
    case _ => -1
}

配合标准库ifSome、ifNone使用

cangjie 复制代码
ifSome(cache) {
    c => println("拿到缓存 ${c}")
}

ifNone(cache) {
    println("没有拿到缓存")
}

多层嵌套 struct 一路点下去

cangjie 复制代码
struct A {
    A(let b: Option<B>) {}
}

struct B {
    B(let c: Option<C>) {}
}

struct C {
    C(let value: Int64) {}
}

let a: Option<A> = A(B(C(64)))
let v = a?.b?.c?.value // Option<Int64>

数组元素本身是 Option

cangjie 复制代码
let opts: Array<Option<Int64>> = [Some(1), None, Some(3)]
let heads = opts[1] // 先取下标 → 得到 None
ifSome(heads) {
    v => println("heads的值是${v}")
}

高阶函数指针

cangjie 复制代码
type Fn = (Int64) -> Option<Int64>

let maybeFn: Option<Fn> = Some({x => Some(x * 3)})
let out = maybeFn?(7) // Some(21)

自定义下标运算符

cangjie 复制代码
extend<T> Array<T> {
    public operator func [](idx: Int64, action: (T) -> T): T {
        if (idx >= 0 && idx < size) {
            let v = this[idx]
            action(v)
        } else {
            throw Exception("下标越界")
        }
    }
} // Some(30)

let data = Some([10, 20])
let x = data?[1, {
        v => v + 10
    }]

一张图记住所有写法

text 复制代码
Option<T> 变量 ──→ ? ──→ .member     → Option<U>
                 │     │()
                 │     │[]
                 │     │{ ... }
                 │     │
                 └─→ 任意一环 None 就整体返回 None
相关推荐
爱吃大芒果5 小时前
GitCode口袋工具的部署运行教程
flutter·华为·harmonyos·gitcode
爱吃大芒果5 小时前
Flutter基础入门与核心能力构建——Widget、State与BuildContext核心解析
flutter·华为·harmonyos
威哥爱编程8 小时前
【鸿蒙开发案例篇】鸿蒙6.0计算器实现详解
harmonyos·arkts·arkui
威哥爱编程9 小时前
【鸿蒙开发案例篇】鸿蒙跨设备实时滤镜同步的完整方案
harmonyos·arkts·arkui
L、21810 小时前
统一日志与埋点系统:在 Flutter + OpenHarmony 混合架构中实现全链路可观测性
javascript·华为·智能手机·electron·harmonyos
hefengbao12 小时前
『京墨文库』鸿蒙版上线!
harmonyos·arkts·arkui·arkdata
赵浩生12 小时前
鸿蒙技术干货6:鸿蒙权限管理与后台任务开发指南(下)
harmonyos
赵浩生12 小时前
鸿蒙技术干货5:鸿蒙权限管理与后台任务开发指南(上)
harmonyos
kirk_wang13 小时前
Flutter插件跨平台适配技术分析之是否需要适配鸿蒙端-screenshot
flutter·华为·harmonyos
赵财猫._.15 小时前
React Native鸿蒙开发实战(七):性能优化与调试技巧
react native·性能优化·harmonyos