过程与作用域

一个过程创建好后,就可以象 Tcl 内建命令一样直接使用。 

Tcl8.0 以后的版本增加了名字空间(name space),它为过程和变量提供了新的作用域。 

1. proc—过程定义命令 

使用 proc 命令定义过程: 

proc procName { var1 var2 ... } { body

 

} 

proc 命令有三个参数:

  • procName 是定义的过程名字

  • {var1 var2 ...}是输入、输出参数列表;

  • body 是过程执行命令体。 body 的界定大括弧和 if 等命令的命令执行体遵循相同的规则和注意事项 

  • 可以使用 return 命令在需要的时候返回调用程序。 
  • 使用过程的时候,不一定输入所有的参数值。过程的输入参数可以有默认值。默认值由{默认参数名 默认值}指定。如果调用过程时没有指定这些参数的值则会使用其默认值,否则使用输入值来替代默认值。在使用默认参数的时候要注意,如果默认参数之后还有非默认参数,则在调用此过程的时候,默认参数的值也要求输入,否则会出错。

带有默认参数的过程定义示例:

proc Test {a {b 7} {str "hello World"}}  {

  puts "$str"

  return [expr ab]

}

Test 10

 => Hello World

  70

Test 10 5 "Call Test"

 => Call Test

  50

如果参数列表中最后一个参数是 args 的话,则过程可以接收可变数目的输入参数。当调用过程时,除了指定参数以外的参数值都被 args 接收。如果参数列表中只有 args 一项,则 args 接收所有输入参数值

proc vParam {args} {

  puts "input values are : $args"

vParam

 => input values are :

vParam 1 "Hello" 2 3 "End"

 => input values are : 1 Hello 2 3 End

2. 作用域       

2.1 过程的作用域           

默认情况下,过程名具有单一的作用域即全局作用域。所以可以在脚本的任何地方使用一个过程(使用之前,过程必须已经定义)。可以通过名字空间来限定过程的作用范围。如可以通过名字空间命令设置一个过程可以让外部调用,也可以设置过程不为外部所使用。 

过程的定义可以嵌套,低层定义的过程只有在上层过程被执行后才能生效。 

proc one {} {

  puts "I'm one"

  proc two {} {

     puts "I'm two"

  }

  puts "Call two in one:"

  two

}   

two

 => invalid command name "two"

one

 => I'm one

  Call two in one:

  I'm two

  two

 => I'm two

2.2 变量的作用域 

对于变量而言,根据其作用域可分为全局变量和局部变量。在所有过程之外定义的变量为外部变量,即全局变量,它的作用域为从开始定义到执行结束,除非中间有显式取消其定义在一个过程体内定义的变量为内部变量,即局部变量,局部变量的作用域只限于过程内部使用,在此过程外面不能使用这些变量。在一个过程内部,即可以使用自身的局部变量,又可以使用全局变量,但是全局变量在过程内部不会自动可见,需要通过 global 命令来事先声明。因为作用域不同,所以过程中的变量可以与全局变量、其他过程中的变量有相同的名字。

在过程定义中的输入、输出参数列表中的参数为过程的内部参数。 

set a 5

set b -8

set c 10

proc P1 {a} {

set b 42

global c

puts "$a"

puts "$b"

puts "$c"

}

P1 $b

 => -8

  42

  10

全局变量的定义不一定要在过程外完成,可以在任何一个过程中完成,其效果是将一个局部变量的作用域进行了扩展但是在引用全局参数的值之前全局参数应首先已被赋值

另外当一个过程中要使用与局部变量相同名字的参数时,用global 命令就要小心:你不能在定义完成一个局部变量后再用 global 命令使用同名的全局参数,这会出错 

proc P2 {} {

  global var1

  set var1 100

  puts "var1=$var1"  #在P2内定义全局变量

}

proc P3 {} {

  global var1

  puts "var1=$var1"

}

proc P4 {} {

  global var2

  put $var2

}

proc P5 {} {

  set a 30

  global a

  puts "a=$a"

}

P2

 => var1=100

P3

 => var1 = 100

P4  #试图使用不存在的全局变量

 => can't read "var2:no such variable"

P5  #在定义局部变量后视图引用同名全局变量

 => variable "a" already exists

还有另外一种方式来直接使用全局变量即用双冒号( ::,见下例:

proc test {} {

  puts "The value of global variable var1 is $::var1"

}

set var1 20

 => 20

test

 => The value of global variable var1 is 20

2.3 upvar命令

upvar 命令的作用与 global 的作用相似, upvar 通过“引用”来使用上层过程中的变量,它传递的是参数名而非值 

语法:

  • upvar ?level? otherVar1 myVar1 ?otherVar2 myVar2 ... ? 

upvar 命令将 myVar1 定义为 otherVar1 的一个引用otherVar 是有 level指定的本过程调用栈中的向上 level 层的变量。当定义好之后,本过程就可以通过 myVar 参数来使用 otherVar 参数。 

level 有两种表示方式:

  • level 为一个整数值时,表示从当前作用域向全局作用域上溯到level 层作用域比如 level 1 时,代表调用过程作用域, level 2 时为上一层作用域
  • 如果 level 是一个”#”跟一个整数则表示从全局作用域向当前作用域下溯。比如 level #0,则表示全局作用域,此时的作用同 global 命令

上面介绍 global 的时候提到,如果过程已经用 set 命令定义了一个参数,此时用 global 命令使用全局变量中相同名字的参数就会出错,报告参数已经存在。而通过 upvar命令却可以作到这一点, upvar 命令通过一个不同的参数名来引用全局变量。 

2.4 rename 命令

rename 命令可以用来更改命令名,这些命令包括 TCL 自带的内建命令和读者自己定义的过程。

语法:

  • rename oldFuncName newFuncName 

如有一个命令名为 old,则通过命令:

  • rename old new 

将命令名改为了 new。如果以后要调用原来的命令就不能用 old,只能用 new。如果新命令名 newFuncName 是空字符串{},则 rename 命令此时的作用是取消一个命令。

2.5 特殊变量 

当 Tcl shell 被调用的时候, tclsh 或 wish 会设定一些变量,如命令行参数和环境变量数组。在编程时,可以使用命令行参数和环境变量数组传递参数信息。 

2.5.1 命令行参数 

命令行参数是在 Tcl shell 被调用时定义/初始化的。命令行参数有: 

  • argc :命令行参数的数目,不包括执行脚本的名字

  • argv0 :脚本名

  • argv :命令行参数列表 

下面示例中,先编写一个 Tcl 脚本文件test.tcl,然后调用 Tcl shell tclsh 来运行此脚本文件打印命令行参数信息。第一次没有输入任何命令行参数,第二次输入了 5 个命令行参数。 

步骤一:编写test.tcl脚本文件

puts "The number of command line arguments is:$argc"

puts "The name of command the scriptis is:$argv0"

puts "The command line arguments are:$argv"

示例一:运行test.tcl脚本文件,不添加命令行信息

tclsh test.tcl  #不添加命令行信息

 => The number of command line arguments is:0  #表示命令行参数的数目为0

  The name of the scriptis:test.tcl         #表示脚本名

  The command line arguments are:         #表示命令行参数列表

示例二:运行test.tcl脚本文件,添加命令行信息

tclsh test.tcl a b c d e  #添加命令行信息

 => 

  The number of command line arguments is:5  #表示命令行参数的数目为0

  The name of the scriptis:test.tcl          #表示脚本名

  The command line arguments are:a b c d e   #表示命令行参数列表

2.5.2 env - 环境变量数组

TCL 提供了一 事先就定义好的全局环境变量数组,这个数组叫做 env。读者可以通过环境变量数组元素的名字来使用各元素的值。 

posted @   小熊酱  阅读(139)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示