Skip to content
当前页大纲

Mojo 函数与错误处理

本篇覆盖:函数定义、类型化签名、可选参数、错误处理(raises / try-except)、docstring、闭包。

一、函数定义:def 一统天下

Mojo 1.0 里函数统一用 def 定义(旧版的 fn 关键字已淡出主线)。参数和返回值必须标注类型

mojo
def greet(name: String) -> String:
    return "Hello, " + name + "!"

def main():
    print(greet("Mojo"))    # Hello, Mojo!

没有返回值的函数省略箭头:

mojo
def log(msg: String):
    print("[INFO]", msg)

一个完整的例子

mojo
def calculate_average(temps: List[Float64]) -> Float64:
    var total = 0.0
    for temp in temps:
        total += temp
    return total / Float64(len(temps))

def main():
    var temps: List[Float64] = [20.5, 22.3, 19.8, 25.1]
    print(calculate_average(temps))   # 21.925

二、可选参数与关键字参数

mojo
def power(base: Float64, exp: Int = 2) -> Float64:
    var result = 1.0
    for _ in range(exp):
        result *= base
    return result

def main():
    print(power(3.0))          # 9.0,使用默认值
    print(power(2.0, 10))      # 1024.0,位置传参
    print(power(base=2.0, exp=3))  # 8.0,关键字传参

三、错误处理:raises + try-except

这是 Mojo 和 Python 差异最大的地方之一。可能抛出错误的函数必须声明 raises,编译器据此检查调用链:

mojo
def calculate_average(temps: List[Float64]) raises -> Float64:
    if len(temps) == 0:
        raise Error("没有温度数据")
    var total = 0.0
    for temp in temps:
        total += temp
    return total / Float64(len(temps))

调用方必须处理:

mojo
def main():
    var temps: List[Float64] = []
    try:
        var avg = calculate_average(temps)
        print(avg)
    except e:
        print("出错:", e)      # 出错: 没有温度数据

这个设计的好处:

  1. 错误传播路径在函数签名上显式可见——不进函数体就能知道它会不会炸
  2. 编译器保证「能抛错的函数一定被 try 包住」,不会出现 Python 那种运行时才爆的裸异常
  3. raises 函数对编译器还是性能提示——无 raises 的函数不会生成异常处理路径

自定义错误信息

Error 接受字符串描述,异常对象可直接打印:

mojo
raise Error(t"参数非法: 期望正数, 实际 {x}")

四、docstring

三引号字符串即 docstring,mojo doc 命令可据此生成 API 文档:

mojo
def calc_bmi(weight: Float64, height: Float64) -> Float64:
    """计算 BMI 指数。

    Args:
        weight: 体重(千克)
        height: 身高(米)

    Returns:
        BMI 值 = weight / height²
    """
    return weight / (height * height)

五、闭包与 lambda

Mojo 支持现代的 lambda 表达式(比旧版 @parameter 闭包语法更简洁):

mojo
def main():
    # lambda 表达式
    var double = lambda(x: Int) -> Int: x * 2
    print(double(21))          # 42

    # 闭包:捕获外部变量
    var factor = 10
    var scaled = lambda(x: Int) -> Int: x * factor
    print(scaled(5))           # 50

闭包细节(捕获方式、move 语义)会在需要时再深入,日常使用先记住这个形态。

六、函数是「一等性能公民」

两个值得知道的底层事实:

  1. 小类型走寄存器IntFloat64SIMD 等小类型传参永远走 CPU 寄存器,没有堆分配——这是 Mojo 数值代码快的重要原因
  2. 编译器可内联与专门化:配合编译期参数(第七篇),同一个函数会为不同类型/常量生成专门版本

七、小结

PythonMojo 1.0
随时 raise Exception必须先声明 raises
调用方可不处理编译器强制 try 或继续上抛
lambda x: x*2lambda(x: Int) -> Int: x * 2
docstringdocstring + mojo doc 生成文档
默认参数/关键字参数一致支持

下一篇:struct 结构体与生命周期。

MIT License.