仓颉语言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
相关推荐
想你依然心痛10 分钟前
HarmonyOS 5.0音视频开发实战:基于ArkMedia Kit的实时直播与AI增强处理系统
人工智能·音视频·harmonyos
芙莉莲教你写代码37 分钟前
Flutter 框架跨平台鸿蒙开发 - 谜语大全
flutter·华为·harmonyos
2501_920627619 小时前
Flutter 框架跨平台鸿蒙开发 - 古文学习应用
学习·flutter·harmonyos
芙莉莲教你写代码11 小时前
Flutter 框架跨平台鸿蒙开发 - 魔术教学
flutter·华为·harmonyos
纯爱掌门人12 小时前
鸿蒙文件预览开发实践:从打开文件到加速感知
华为·harmonyos
云和数据.ChenGuang13 小时前
当智能体遇上原生鸿蒙:开启下一代操作系统的“智慧觉醒”
华为·harmonyos
左手厨刀右手茼蒿13 小时前
Flutter 三方库 bs58 的鸿蒙化适配指南 - 在鸿蒙系统上构建极致、高效的 Base58 数字货币与区块链数据编解码引擎
flutter·harmonyos·鸿蒙·openharmony
加农炮手Jinx13 小时前
Flutter 组件 substrate_bip39 的适配 鸿蒙Harmony 实战 - 驾驭区块链级助记词原语、实现鸿蒙端金融级 BIP39 安全私钥推导方案
flutter·harmonyos·鸿蒙·openharmony·substrate_bip39
左手厨刀右手茼蒿13 小时前
Flutter 组件 substrate_bip39 的适配 鸿蒙Harmony 实战 - 驾驭区块链级 BIP39 安全底座、实现鸿蒙端私钥派生与国密级密钥保护方案
flutter·harmonyos·鸿蒙·openharmony·substrate_bip39
加农炮手Jinx13 小时前
Flutter 三方库 fast_base58 的鸿蒙化进阶指南 - 挑战编解码吞吐量极限、助力鸿蒙端大规模区块链与分布式存储数据处理
flutter·harmonyos·鸿蒙·openharmony·fast_base58