使用变量和表达式

简介

与 Python 类似,Colang 支持以下基本数据类型:stringintfloatboollistsetdict,以及 Colang 特定的 event、action 和 flow 引用。我们已经了解了如何使用 ... as $ref 符号将 event、action 和 flow 引用分配给变量。这里 $ref 也只是一个变量。为了在 flow 名称中启用空格字符,Colang 变量必须始终以 $ 字符开头,并且自身不能包含空格字符。

重要提示

变量命名约定

  • 必须以字母字符开头

  • 可以包含字母数字字符,包括 _

  • 区分大小写

Regular expression: \$[^\W\d]\w*

Colang 中的变量行为与 Python 中完全相同。因此,对于像 list 这样的可变数据类型,新的变量赋值不会复制,而只是被新变量引用。

variables/assignment/main.co
flow main
    $value = "Hi"
    $value_copy = $value # Copy of the value
    await UtteranceBotAction(script=$value_copy)
    match AnEvent()

请注意,Colang 引用也是可变的,因此指向相同的底层对象

variables/references/main.co
flow main
    match UtteranceUserAction.Finished() as $ref
    $ref_copy = $ref # Both references are pointing to same event object
    await UtteranceBotAction(script=$ref_copy.final_transcript)
    match AnEvent()

目前,不支持创建其他变量的引用。引用只能指向 event、action 或 flow 对象,并且在 sendmatchstartawait 语句中使用 as 关键字创建。

重要提示

  • 对变量的赋值将始终在内存中创建值的副本

  • event、action 或 flow 引用的副本仍然指向相同的对象

  • Flow 参数按值传递

以下是一些变量赋值示例

$string_value = "Hi"
$integer_value = 42
$float_value = 3.14159
$list_of_strings = ["one", "two", "three"]
$list_of_integers = [1, 2, 3, 4]
$set_of_floats = {0.1, 0.2, 0.3}
$dictionary = {"value_a":1, "value_b": 2}

表达式求值

Colang 支持对简单和复合数据类型求值常见的 Python 表达式(请参阅 Simple Eval

# Arithmetic expressions
21 + 21
21 + 19 / 7 + (8 % 3) ** 9

# Supported operators
+, -, *, / # standard arithmetic operators
** # to the power of: 2 ** 10 -> 1024
% # modulus
==, <, >, <=, >= # comparison operators
in # is something contained within something else
not in # is something not contained within something else
>>, <<, ^, |, &, ~ # Bitwise operators

# Conditional expressions
"equal" if x == y else "not equal"
"a" if 1 == 2 else "b" if 2 == 3 else "c"

# Compound data types
list_variable[0] # Access item by index
dict_variable[key] # Access item by key
object.attribute # Access object attribute

# Supported custom functions
len(obj: Any) -> int # Return number of items of a compound variable
regex(pattern: str) -> Pattern # Creates a regex pattern that can be compared to
search(pattern: str, string: str) -> bool # Check for regex pattern in string
findall(pattern: str, string: str) -> List[str] # Return all matches of regex pattern with string
uid() -> str # Create new universal unique identifier
int(string: str) -> int # Convert the number in the string to an int
float(string: str) -> float # Convert the number in the string to a float
str(x: Any) -> str # Convert x to a string
pretty_str(x: Any) -> str # Convert x to a formatted string
int(x: Any) -> int # Convert x to a int
float(x: Any) -> float # Convert x to a float
escape(string: str) -> str # Escape a string and expressions inside the string
is_bool(x: Any) -> bool # Check if x is a bool
is_int(x: Any) -> bool # Check if x is an int
is_float(x: Any) -> bool # Check if x is a float
is_str(x: Any) -> bool # Check if x is a str
is_regex(x: Any) -> bool # Check if x is a regex pattern
rand() -> float # Return a random float between 0 and 1
randint(x: int) -> int # Return a random int below x
flows_info() -> dict # Returns a dictionary that contains more information about the current flow

以下是如何在 Colang 中使用表达式的方法

# Expression in an assignment
$dict = {"value": 2 + 3}

# Expression as standalone statement
($dict.update({"value": 4}))

# Expression as a flow parameter
bot count to ($dict["value"])

您可以看到表达式如何在不同的上下文中使用,并且如果用作独立语句flow 参数,则需要用括号括起来。

Flow 变量访问

默认情况下,在 flow 中定义的变量具有局部作用域,并且无法从 flow 外部访问。启用访问的一种方法是在 flow 定义中使用 定义 Flow 中所示的符号将它们声明为 flow 属性

variables/flow_attributes/main.co
flow main
    await user said something as $ref
    await UtteranceBotAction(script=$ref.transcript)
    match AnEvent()

flow user said something -> $transcript
    match UtteranceUserAction.Finished() as $event_ref
    $transcript = $event_ref.final_transcript

通过这种方式,我们可以访问用户转录,并使用它通过 bot 发言动作重复它。

在 flow 之间使用变量共享信息的另一种方法是使用关键字 global 使其成为全局变量。

variables/global_variables/main.co
flow main
    global $transcript
    await bot said something
    await UtteranceBotAction(script=$transcript)
    match AnEvent()

flow bot said something
    global $transcript
    match UtteranceUserAction.Finished() as $event_ref
    $transcript = $event_ref.final_transcript

正如您从示例中看到的,我们需要在每个 flow 中定义变量 $transcript 是全局的,以便访问全局实例。否则,它将是一个隐藏全局实例的局部变量。但是,请三思而后行是否使用全局变量,因为它可能表明 Colang 设计不是最优的。

字符串中的表达式

与 Python 的格式化字符串文字一样,我们可以使用花括号来计算字符串内的表达式 "{$variable}"

variables/string_expression_evaluation/main.co
flow main
    $user_name = "John"
    await UtteranceBotAction(script="Hi {$user_name}!")
    match AnEvent()

如果需要在文字文本中包含花括号字符,可以通过加倍来转义它:{{}}

内置 Flow 变量

重要提示

这是正在进行的工作,一些内置变量将来可能会更改或删除。

目前,有一些变量名称不能在 flow 中用作自定义变量名称。它们包含 flow 实例特定信息

$system: dict # System specific data like e.g. the current bot configuration `$system.config`
$uid: str # The unique id of the flow instance
$flow_id: str # The name of the current flow
$loop_id: Optional[str] # The interaction loop id of the current flow
$parent_uid: Optional[str] # The unique id of the parent flow instance
$child_flow_uids: List[str] # All unique ids of the child flow instances
$context: dict # The current variable context that contains all user defined variables in the flow
$priority: float # Current priority of the flow
$arguments: dict # All arguments of the flow
$flow_instance_uid: str # Flow instance specific uid
$source_flow_instance_uid: str # The parent flow uid of the flow
$activate: bool # True if the flow was activated and will therefore restart immediately when finished
$new_instance_started: bool # True if new instance was started of an activated flow

# Other internal flow members that cannot be used:
$hierarchy_position, $heads, $scopes, $head_fork_uids, $action_uids, $global_variables,
$status_updated, $source_head_uid

接下来,我们将学习如何使用 Flow 控制 来创建分支或循环交互模式。