仓颉语言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
相关推荐
米羊1211 小时前
【鸿蒙心迹】工匠雕琢,攻克难题(下)
华为·harmonyos
chenbin___16 小时前
鸿蒙键盘遮挡react native内容尝试
react native·harmonyos
爱笑的眼睛1117 小时前
深入解析HarmonyOS ArkTS:从语法特性到实战应用
华为·harmonyos
安卓开发者19 小时前
鸿蒙NEXT SSAP连接与数据传输实战:轻松实现跨设备通信
华为·harmonyos
安卓开发者1 天前
在鸿蒙NEXT中使用WebSocket实现实时网络通信
websocket·华为·harmonyos
fruge2 天前
提升 HarmonyOS 开发效率:DevEco Studio 6.0 热更新调试模式全指南
华为·harmonyos
2501_919749032 天前
鸿蒙:使用Image组件展示相册图片或rawfile图片
华为·harmonyos
2501_919749032 天前
鸿蒙:PersistenceV2页面间持久化存储数据
华为·harmonyos
一尘之中2 天前
操作系统内核架构深度解析:从单内核、微内核到鸿蒙分布式设计
架构·harmonyos·ai写作
咕噜企业签名分发-淼淼2 天前
App防止恶意截屏功能的方法:iOS、Android和鸿蒙系统的实现方案
android·ios·harmonyos