在 python 中我们可以定义一个函数 function 来完成特定的任务。函数可以接受参数输入,这些参数可以用于在函数内部进行操作和计算。参数分为两类:位置参数和关键字参数。在函数定义时,我们可以给这些参数设置默认值,这样在函数调用时,如果没有给这些参数赋值,就会使用默认值。而在 TCL 中,我们可以通过 创建过程 proc 来达到相同的目的。
TCL 语言中的过程的创建可以分为三个步骤:
一 定义过程:
在 TCL 中,过程就是一段代码块,可以用 proc 命令来定义。proc 命令的语法规则为:
proc procedureName {args} {
# 过程体
return $result
}
其中 procedureName 为要创建的过程的名称,{args} 为过程的参数列表,用花括号括起来,多个参数之间用空格分隔。过程体是实现该过程功能的具体代码,可以包含多条 TCL 语句。如果要从过程中返回值,可以使用 return 命令。其中,$result 是将返回的值。
二 调用过程:
定义过程之后,可以通过过程名来调用它。调用过程需要传入对应的参数。如果过程没有参数,可以直接使用过程名进行调用。
procedureName value1 value2
三 传递参数:
要在过程中传递参数,在定义 proc 的时候就要指定对应的参数列表。在 TCL 中,参数列表一般有以下几种情况。
- 参数列表指定为一个空字符串,这种情况下,过程不获取参数,直接用过程名进行调用
# 例如 定义一个过程 输出一段字符串 proc hello {} { puts "Hello, world!" }
调用上述定义的 hello 过程
hello
执行上述代码后,屏幕输出:
Hello, world!
- 参数列表指定为固定参数,这种情况下,参数是按照过程定义中的顺序进行传递的
# 例如 proc test {a b c} { puts "a is $a\nb is $b\nc is $c" } # 在调用上述过程 test 1 2 3
将得到如下输出结果:
a is 1
b is 2
c is 3
这里的
1
是传递给a
参数的值,2
是传递给b
参数的值,3
是传递给c
参数的值。这些参数的顺序必须与过程定义中的顺序匹配。
# 例如 定义一个名为difference的过程,计算两个数的差 proc difference {x y} { set diff [expr {$x - $y}] puts "The diff of $x and $y is $diff." return $diff } difference 1 7
输出结果:
The diff of 1 and 7 is -6.
上述定义了一个名为 difference 的过程,计算两个数的差,调用该过程,需要两个固定参数。与 python 不同的是 TCL 中不支持改变输入参数的顺序。例如我们用如下命令调用过程时会报错。
difference -y 1 -x 7 # 报错 wrong # args: should be "difference x y" while executing "difference -y 1 -x 7"
- 参数列表为任意数量的参数,这种情况通过关键字 args 来实现。
# 例如,定义一个过程,可以计算任意数量的和 proc my_proc {args} { set sum 0 foreach arg $args { set sum [expr {$sum + $arg}] } return $sum } set result [my_proc 1 2 3 4 5] puts "The sum of the numbers is $result."
输出结果:
The sum of the numbers is 15.
这定义了一个名为 my_proc 的 proc,它使用 args 参数接受可变数量的参数。在 proc 内部,使用 foreach 循环遍历 args 中的所有参数并存储在 arg 变量中,再为每一个值执行一次循环体中的脚本也就是将每一个参数添加到 sum 变量中。最后,返回 sum 变量。
要调用此 proc 并获取一组数字的总和,可以传入任意数量的以空格分隔的参数。在上面的示例中,使用参数 1 2 3 4 5 调用了 my_proc 过程,并将结果存储在 result 变量中。然后使用 puts 命令打印出结果。
- 当然也可以为参数设置默认值
# 例如 我们定义一个过程 把一个定值加一个增量 增量的默认值是1 proc function {value {incr "1"}} { set result [expr {$value + $incr}] return $result } puts [function 9] puts [function 9 10]
输出结果:
10
19
在第一个调用中,value被设置为 9,incr 被设置为默认值1。因此,输出结果为 10。
在第二个调用中,value被设置为 9,incr被设置为 10。因此,输出结果为 19。
四 设置有默认值的参数的注意事项
参数列表中:设置有默认值的参数必须要放在没有设置默认值的参数的后面,否则调用过程可能会产生错误。我们通过下面的例子进行测试:
# 在这个例子中 param2和param4有默认值 proc my_proc {param1 {param2 100} param3 {param4 "default_value"}} { puts "param1: $param1" puts "param2: $param2" puts "param3: $param3" puts "param4: $param4" }
my_proc 1 2 3 4 # 输出 # param1: 1 # param2: 2 # param3: 3 # param4: 4 my_proc 1 2 3 # 输出 # param1: 1 # param2: 2 # param3: 3 # param4: default_value my_proc 1 2 # 输出 wrong # args: should be "my_proc param1 ?param2? param3 ?param4?" while executing "my_proc 1 2 " my_proc 1 # 输出 wrong # args: should be "my_proc param1 ?param2? param3 ?param4?" while executing "my_proc 1 "
从程序报错就可以看出,param2 和 param4 是可选参数,而 param1 和 param3 是调用过程必需要的参数,所以要正确调用该过程,最少要给定 3 个参数。
五 项目实战
想象我们淘宝购物的场景,假如让你编写一个购物清单的程序,需要定义一个 proc 来添加商品到购物清单中。运用所学 TCL 语法知识如何实现呢?
我们来捋一捋思路,首先我们需要想好购买物品的名称,比如鞋子、衣服、裤子等;一般来说我们默认一件商品购买数量为 1 ,但是有对象的就不一样了,你可能想和你对象买个情侣套装,也就是买两件商品;你喜欢黑色,而你对象偏爱红色,你的尺码大,而你对象尺码小。
根据上述分析 ,我们可定义三个参数 一个参数用于指定商品名称 item ;第二个参数用于指定商品的数量,并且默认值为 1 ;第三个参数为可变参数,通过 args 实现,用于指定商品的其它属性,如尺寸、颜色等。
# 代码实现 1 通过if判断语句
proc add_to_shopping_list {item {quantity "1"} args} {
if {$args ne ""} {
set result "$item x $quantity with options : $args"
} else {
set result "$item x $quantity"
}
puts "Add $result to shopping list"
}
# 代码实现 2 通过数组实现
proc add_to_shopping_list {item {quantity "1"} args} {
array set options $args
set result "$item x $quantity"
if {[array exists options]} {
set result "$result with options : [join [array get options] ,]"
}
puts "Add $result to shopping list"
}
# 代码实现 3 通过字典实现
proc add_to_shopping_list {item {quantity "1"} args} {
set options [dict create {*}$args]
set result "$item X $quantity"
if {[dict size $options] > 0} {
set result "$result with options: [join [dict get $options] ,]"
}
puts "Add $result to shopping list"
}
# 调用过程
add_to_shopping_list T-shirt 2 "color=red" "size=50kg"
上述三个输出结果一致:
Add T-shirt x 2 with options : color=red,size=50kg to shopping list