流程控制#

流程控制是所有编程语言中的基本工具,Colang 也支持这一点。它可以在单个流程中实现交互模式的分支和重复。

条件分支 (if/elif/else)#

重要

条件分支的语法定义

if <condition1>
    <interaction pattern sequence 1>
[elif <condition2>
    <interaction pattern sequence 2>]
.
.
.
[else
    <interaction pattern else sequence>]

条件分支是一个众所周知的概念,其工作原理与 Python 完全相同

control_flow_tools/conditional_branching/main.co#
flow main
    $number_of_users = 1
    if $number_of_users == 0
        await user became present
    elif $number_of_users > 1
        bot say "I am sorry, I can only interact with a single user!"
    else
        bot say "Welcome! Nice to meet you!"
    match RestartEvent()

在此示例中,bot 的反应取决于变量 $number_of_users 的状态,该变量包含可用用户的数量。

事件分支 (when/or when/else)#

事件分支是基于 Colang 的新概念,它允许基于预期事件进行分支。

重要

基于事件的分支的语法定义

when <MixedGroup1>
    <interaction pattern sequence 1>
[or when <MixedGroup2>
    <interaction pattern sequence 2>]
.
.
.
[else
    <interaction pattern else sequence>]
  • <MixedGroup> 表示流程、操作和事件的混合分组

  • when/or when 语句中的所有操作和流程将并发启动

  • 如果既没有使用 or when 语句也没有使用 else 语句,则 when 结构可以仅替换为 awaitmatch 语句

通过并发模式匹配机制,我们已经看到了根据用户输入设计分支交互模式的一种方法

control_flow_tools/concurrent_patterns/main.co#
flow main
    bot say "How are you?"
    bot react to user feeling good or bot react to user feeling bad

flow bot react to user feeling good
    user said "Good" or user said "Great"
    bot say "Great"

flow bot react to user feeling bad
    user said "Bad" or user said "Terrible"
    bot say "Sorry to hear"

根据用户的回答,我们将得到不同的 bot 反应。尽管这种并发流程机制非常强大,但在某些情况下,借助 when 结构将所有内容放在单个流程中会更好

control_flow_tools/event_branching/main.co#
flow main
    bot say "How are you?"
    bot react to user wellbeing

flow bot react to user wellbeing
    when user said "Good" or user said "Great"
        bot say "Great"
    or when user said "Bad" or user said "Terrible"
        bot say "Sorry to hear"

通过添加更多的 or when 语句,可以轻松扩展案例数量。else 语句仅在所有 when/or when 语句都失败时才会触发。

从定义中可以看出,when/or when 语句支持包含事件、操作和流程的混合组。对于事件,这类似于 match 语句,而对于操作和流程,其行为类似于 await 语句。因此,操作和流程将启动,然后与它们的 Finished 事件进行匹配。请注意,所有流程和操作将在不同的 when/or when 语句中并发启动,并在第一个案例成功时立即停止。

重要

所有 when/or when 语句中启动的所有流程和操作将在任何一个案例成功时立即停止。

我们还可以使用此结构轻松地为一个完成或失败的流程创建分支

control_flow_tools/catch_failing_flow/main.co#
flow main
    start pattern a
    when pattern b
        bot say "Pattern b has finished"
    else
        bot say "Pattern b has failed"

flow pattern a
    user said "Hello"
    bot say "Hello"

flow pattern b
    user said something
    bot say "Hi"

由于事件生成冲突解析,'pattern b' 对于用户输入“Hello”将失败,但对于用户输入“Hi”将成功完成

> Hello

Hello

Pattern b has failed

> Hi

Hi

Pattern b has finished

当与以操作开头的类似操作的流程一起使用时,这被认为是“糟糕的设计”

flow bot greet then comment
    when bot say "Hi there!"
        bot say "I am done talking first"
    or when bot gesture "Wave with one hand"
        bot say "I am done gesturing first"

flow bot say $text
    await UtteranceBotAction(script=$text)

flow bot gesture $gesture
    await GestureBotAction(gesture=$gesture)

此示例将无法正常工作,因为由于 UtteranceBotActionGestureBotAction 之间的操作冲突,两个操作中只有一个会启动。请注意,如果遵循适当的流程命名约定,可以轻松检测到此类情况,因为 when bot say "Hi there!" 在语法上不正确。上面的示例需要按如下方式实现

flow bot greet then comment
    start bot say "Hi there!" as $action_1_ref
        and bot gesture "Wave with one hand" as $action_2_ref
    when $action_1_ref.Finished()
        bot say "I am done talking first"
    or when $action_2_ref.Finished()
        bot say "I am done gesturing first"

重要

when/or when/else 分支只能与类似意图的流程一起使用。

循环 (while)#

重要

循环的语法定义

while <condition>
    <interaction pattern sequence>

在此示例中,bot 将从一数到十

control_flow_tools/loop/main.co#
flow main
    bot count to 10

flow bot count to $number
    $current_number = 1
    while $current_number < $number
        bot say "{$current_number}"
        $current_number = $current_number + 1

为了提早中止循环或跳过当前循环迭代的其余部分,可以使用关键字 breakcontinue

flow bot count to $number
    $current_number = 0 # Initialized it with 0
    while True # Endless loop
        bot say "{$current_number}"
        $current_number = $current_number + 1
        if $current_number == 0
            continue # Skip the number 0
        if $current_number > $number
            break # Break out of loop when target number was reached

结束或中止流程 (return/abort)#

可以在流程的任何点使用关键字 returnabort 来结束或失败流程

flow main
    user greeted then expressed feeling unwell

flow user greeted then expressed feeling unwell
    match user greeted
    when user expressed feeling unwell
        return
    or when user said something
        abort
    # We never reach this, except if both cases fail

此外,return 接受一个可选值,以便您可以像普通函数一样使用流程

flow main
    $result = await multiply 3 4
    bot say "{$result}"

flow multiply $number_1 $number_2
    return $number_1 * $number_2

如果未提供返回值,则默认传递 None

注意

将流程的返回值赋给变量时,流程名称前的 await 不再可选。

无操作 (pass)#

有时,拥有一个无操作关键字 pass 很有用,例如作为占位符使语法有效

flow main
    user greeted then expressed feeling unwell

flow user greeted then expressed feeling unwell
    match user greeted
    when user expressed feeling unwell
        pass # Just continue with the flow
    or when user said something
        abort
    # The flow will successfully finish here