Mojo 控制流语句详解if、while、for、短路求值与仓库示例代码的运行验证【免费下载链接】mojoThe Modular Platform (includes MAX Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo本篇围绕 Mojo 手册的 Control flow控制流章节及其配套示例目录 control-flow 展开完整覆盖if/elif/else、短路求值、条件表达式、while与for循环含break/continue/else子句、引用迭代、range 生成器及 Python 集合迭代的全部语法要点与可运行代码。读完后你将掌握 Mojo 条件与循环语句的完整用法并能直接通过仓库自带的 Bazel 示例目标复现、验证每一段代码的输出行为。一、目录定位手册章节的示例代码与测试入口示例目录 Mojo/docs/site/code/manual/control-flow 是 Mojo 手册 Control flow 章节 的代码示例与测试载体其 README 明确说明了两点组织约定目录中每个.mojo文件都是一个独立的 Mojo 应用程序目录中的 BUILD.bazel 为每个.mojo文件定义了一个mojo_binary目标目标名取文件名去掉扩展名一个modular_run_binary_test目标以_test为后缀。当前目录中的示例文件与对应主题的一一对应关系如下示例文件对应手册小节if_statement.mojoif语句基础、单行、elif/elseshort_circuit.mojo短路求值or/andconditional_expression.mojo条件表达式三元运算符while_loop.mojowhile语句含break/continue/elsefor_loop.mojofor语句集合、range、引用迭代、Python 集合构建与测试目标的细节control-flow 的 BUILD.bazel 通过 glob 收集全部.mojo源文件并用列表推导批量生成目标load(//bazel:api.bzl, modular_run_binary_test, mojo_binary) package(default_visibility [//oss/modular/docs:__subpackages__]) MOJO_SRCS glob([*.mojo]) [ mojo_binary( name src.split(.)[0], srcs [src], deps [ mojo//:std, ], ) for src in MOJO_SRCS ] [ modular_run_binary_test( name src.split(.)[0] _test, size small, binary src.split(.)[0], target_compatible_with select({ //:asan: [platforms//:incompatible], //conditions:default: [], }), ) for src in MOJO_SRCS ]几个值得注意的实现细节每个二进制的唯一依赖是mojo//:std即 Mojo 标准库说明这些示例只依赖语言内建能力不需要额外第三方库测试目标通过target_compatible_with在开启asanAddressSanitizer配置时标记为不兼容即//:asan构建下会自动跳过这些运行时测试包可见性声明为//oss/modular/docs:__subpackages__从源码结构看该目录在 Bazel 工作区中的包映射归属于oss/modular/docs子树测试目标命名统一为文件名_test例如if_statement_test、for_loop_test可用bazel test按标签运行以验证程序能否成功构建并执行。二、if语句条件执行、单行形式与 elif/else 链Mojo 支持if语句用于条件代码执行当给定的布尔表达式求值为True时执行其后的缩进代码块。示例来自 if_statement.mojovar temp_celsius Float64(25) if temp_celsius 20: print(It is warm.) print(The temperature is, temp_celsius * 9 / 5 32, Fahrenheit.)输出It is warm. The temperature is 77.0 Fahrenheit.注意示例中temp_celsius显式使用Float64(25)构造条件比较与浮点算术均按Float64语义执行因此华氏温度输出为77.0而非整数。如果只需条件执行单条短语句整个if语句可以写成一行temp_celsius 22 if temp_celsius 15: print(It is cool.) # Skipped because condition is False if temp_celsius 20: print(It is warm.)输出It is warm.第一条单行if因条件为False被跳过第二条命中并执行。if语句还可以包含任意多个elif子句每个子句给出一个布尔条件与对应代码块。条件按书写顺序依次测试一旦某个条件为True执行其代码块后不再测试后续条件else子句则在所有条件均为False时执行temp_celsius 25 if temp_celsius 0: print(It is freezing.) elif temp_celsius 20: print(It is cool.) elif temp_celsius 30: print(It is warm.) else: print(It is hot.)输出It is warm.手册中同时明确了一处与 Python/C 的差异Mojo不支持等价于 Pythonmatch或 Cswitch的匹配/分支语句多分支判断统一使用elif链表达。短路求值Short-circuit evaluationMojo 对布尔运算符遵循短路求值语义or运算符若第一个操作数求值为True则不求值第二个操作数and运算符若第一个操作数求值为False则不求值第二个操作数。short_circuit.mojo 通过两个带副作用打印日志的函数直观验证了这一点# Short-circuit or evaluation def true_func() - Bool: print(Executing true_func) return True def false_func() - Bool: print(Executing false_func) return False print(Short-circuit or evaluation) if true_func() or false_func(): print(True result) # Short-circuit and evaluation print(Short-circuit and evaluation) if false_func() and true_func(): print(True result)输出Short-circuit or evaluation Executing true_func True result Short-circuit and evaluation Executing false_funcor表达式中true_func()返回True后false_func()从未被执行没有 Executing false_func 日志and表达式中false_func()返回False后true_func()同样未被执行。该示例也表明短路求值在避免不必要的函数调用与副作用方面是可观察、可测试的行为。条件表达式三元运算符Mojo 支持与 Python 相同语法形式的条件表达式true_result if boolean_expression else false_result最常见的用法是根据布尔条件为变量赋值两个候选值之一。conditional_expression.mojo 同时展示了表达式形式与等价的if语句形式var temp_celsius 15 var forecast warm if temp_celsius 20 else cool print(The forecast for today is, forecast) # Equivalent if-else statement if temp_celsius 20: forecast warm else: forecast cool print(The forecast for today is, forecast)输出两次The forecast for today is cool The forecast for today is cool与示例文件对应的写法差异值得注意示例文件中直接复用第一次声明的forecast变量var forecast warm if ... else cool随后在等价if语句中重新赋值而手册中的等价写法则先做类型声明var forecast: String再分支赋值。两种方式语义一致前者更简洁后者在变量需要在两个分支中首次绑定时更清晰。三、while语句循环、break/continue 与 else 子句while循环在布尔表达式为True期间重复执行代码块。while_loop.mojo 用一个 Fibonacci 数列生成器展示了最基本的while用法——输出所有小于 50 的 Fibonacci 数var fib_prev 0 var fib_curr 1 print(fib_prev, end) while fib_curr 50: print(,, fib_curr, end) fib_prev, fib_curr fib_curr, fib_prev fib_curr输出0, 1, 1, 2, 3, 5, 8, 13, 21, 34注意循环体中的元组解包赋值fib_prev, fib_curr fib_curr, fib_prev fib_curr一行完成两个变量的同步更新这是 Mojo 语法的一个常用习惯。continue与breakcontinue跳过代码块剩余部分直接从循环测试表达式继续break立即终止循环。var n 0 while n 5: n 1 if n 3: continue print(n, end, )输出1, 2, 4, 5,n 0 while n 5: n 1 if n 3: break print(n, end, )输出1, 2,while的else子句何时执行、何时不执行while循环可选地携带else子句当循环条件求值为False时执行else块即使这是条件第一次被测试即循环体一次都不执行时else依然执行var n 5 while n 4: print(n) n 1 else: print(Loop completed)输出Loop completed关键限制是如果循环因break或return退出else子句不执行n 0 while n 5: n 1 if n 3: break print(n) else: print(Executing else clause)输出1 2break在n 3时触发因此 Executing else clause 不会打印。这一 正常结束才执行 else 的语义与 Python 一致是while循环中实现带哨兵值的处理的惯用结构。四、for语句集合迭代、range、引用修改与 Python 集合Mojo 的for循环遍历序列并为每个元素执行代码块。其迭代协议是被迭代类型需实现__iter__()方法返回的对象需定义__next__()和__len__()方法。for_loop.mojo 是该主题最完整的示例下面按小节拆解。4.1 迭代 Mojo 集合标准库collections模块中的所有集合类型都支持for迭代。List——直接遍历元素var states: List[String] [California, Hawaii, Oregon] for state in states: print(state)输出California Hawaii OregonSet——无序集合遍历顺序由集合自身决定var numbers {42, 0} for number in numbers: print(number)输出42 0Dict有两种迭代技术。第一种是直接遍历Dict产生的是键序列var capitals: Dict[String, String] { California: Sacramento, Hawaii: Honolulu, Oregon: Salem, } for var state in capitals: print(t{capitals[state]}, {state})输出Sacramento, California Honolulu, Hawaii Salem, Oregon第二种是调用items()方法产生DictEntry对象序列在循环体内通过key与value字段访问for item in capitals.items(): print(t{item.value}, {item.key})输出Sacramento, California Honolulu, Hawaii Salem, Oregon两种技术输出相同区别在于直接迭代只能拿到键取值需二次下标查找而items()每轮同时暴露键值对避免了额外查找是更推荐的写法。4.2 引用迭代在循环中修改集合元素Mojo 的集合迭代器返回的是引用默认被不可变地捕获到循环变量中。若需要拿到可变元素引用需在循环变量前加ref关键字建立与元素引用匹配的引用绑定——这在循环内修改集合内容时非常有用。示例见 for_loop.mojo 第 78-83 行var values: List[Int] [1, 4, 7, 3, 6, 11] for ref value in values: if value % 2 ! 0: value - 1 print(values)输出[0, 4, 6, 2, 6, 10]所有奇数元素1、7、3、11各减一偶数元素保持不变。若不加ref循环变量是值的不可变副本对它的修改不会影响原列表。4.3 迭代 range惰性生成整数序列标准库提供的另一种可迭代类型是range——由range()函数生成的整数序列。它与前面集合类型的本质区别在于range 以**生成器generator**方式实现按需逐个产生值而不在内存中物化整个序列。for i in range(5): print(i, end, )输出0, 1, 2, 3, 4,因此for i in range(大数)形式的循环不会消耗额外内存适合数值型循环场景。4.4for循环控制语句continue跳过本轮剩余代码并继续下一个元素for i in range(5): if i 3: continue print(i, end, )输出0, 1, 2, 4,break终止循环for i in range(5): if i 3: break print(i, end, )输出0, 1, 2,for循环同样可选地携带else子句在遍历完所有元素后执行——即使集合为空也会执行for i in range(5): print(i, end, ) else: print(\nFinished executing for loop)输出0, 1, 2, 3, 4, Finished executing for loop空集合场景var empty List[Int]() for i in empty: print(i) else: print(Finished executing for loop)输出Finished executing for loop与while相同的规则break或return终止for循环时else子句不执行var animals: List [cat, aardvark, hippopotamus, dog] for animal in animals: if animal dog: print(Found a dog) break else: print(No dog found)输出Found a dog这一语义使for...else成为查找是否成功的天然模式else分支等价于遍历结束仍未 break。4.5 迭代 Python 集合Mojo 的for循环还支持迭代 Python 集合类型每轮取出的元素都是PythonObject包装器。迭代混合类型 Python 列表from std.python import Python def main() raises: # Create a mixed-type Python list var py_list Python.list(42, cat, 3.14159) for py_obj in py_list: # Each element is of type PythonObject print(py_obj)输出42 cat 3.14159对 Python 字典同样有两种技术。第一种直接迭代得到键序列键与值均为PythonObjectfrom std.python import Python def main() raises: # Create a mixed-type Python dictionary var py_dict Python.evaluate({a: 1, b: 2.71828, c: sushi}) for py_key in py_dict: # Each key is of type PythonObject print(py_key, py_dict[py_key])第二种是调用items()得到 2-元组序列通过下标访问键值from std.python import Python def main() raises: var py_dict Python.evaluate({a: 1, b: 2.71828, c: sushi}) for py_tuple in py_dict.items(): # Each 2-tuple is of type PythonObject print(py_tuple[0], py_tuple[1])两者输出相同a 1 b 2.71828 c sushi两个值得注意的边界细节其一涉及Python.evaluate等 Python 互操作调用时main需要声明raises以允许异常传播for_loop.mojo 即如此其二PythonObject是动态类型包装因此示例中对键值只做了打印与下标访问而不能施加静态类型约束——这是 Mojo 静态类型与 Python 动态类型边界处的固有特性。五、语义速查break 对 else 子句的影响构造正常结束空/首次条件即假break退出return退出while...else执行else执行else不执行else不执行elsefor...else执行else执行else不执行else不执行else这一对照表由 while_loop.mojo 与 for_loop.mojo 中的四组对照示例n 5; while n 4、空List[Int]、n 3处break、animal dog处break共同验证。六、在仓库中验证这些示例上述行为均不是纸面描述仓库通过 Bazel 为每个示例提供了可执行验证构建/运行每个.mojo文件对应一个mojo_binary目标如if_statement、while_loop依赖仅为mojo//:std测试每个二进制对应一个modular_run_binary_test目标如if_statement_test、for_loop_testsize small通过运行二进制本身验证程序可构建、可执行注意//:asan构建配置下这些测试目标被标记为不兼容并自动排除因此验证应在默认非 ASan配置下进行由于包可见性限定为//oss/modular/docs:__subpackages__从源码结构看该目录在 Bazel 工作区中归属于oss/modular/docs包树实际bazel test标签前缀以当前工作区的包映射为准。七、小结本文完整继承了 Control flow 手册章节 的语义规定并以 control-flow 示例目录 中五个独立可运行的.mojo程序为佐证if支持单行形式与任意长度的elif链无switch/match等价物and/or严格短路求值可通过副作用观察验证条件表达式提供与if语句等价的三元赋值形式while与for均支持break/continue/else子句else仅在非 break/return 退出时执行空序列或首次条件为假时依然执行for可迭代List/Set/Dict含items()双技术、惰性range()、以及PythonObject包装的 Python 集合ref循环绑定是唯一能在循环内修改集合元素的机制。所有示例源码、构建规则与预期输出均可在 Mojo/docs/site/code/manual/control-flow 目录中直接查阅与复现。【免费下载链接】mojoThe Modular Platform (includes MAX Mojo)项目地址: https://gitcode.com/GitHub_Trending/mo/mojo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考