Tcl脚本初体验
Tcl(发音 tickle)是一种脚本语言。学习它的目的在于有本书上有这个语言的代码。但是过于老旧,无法运行了,想要自己修改下。:)
Tcl 的特性包括:
任何东西都是一条命令,包括语法结构(for、if 等),以波兰表示法书写。命令通常可变。任何事物都可以重新定义和重载。所有的数据类型都可以看作字符串,包括源代码。拥有完全动态、基于类的对象系统 TclOO,支持包括元类、过滤器和mixin在内的高级功/能。提供事件驱动给套接字和文件。基于时间或者用户定义的事件也可以。默认的变量作用域是词法作用域,但 uplevel 和 upvar 允许过程与封闭的函数作用域/交互。所有的内置命令会在误用时产生错误消息。很容易用 C、C++ 或者 Java 扩展。解释语言,支持字节码。完全的 Unicode (3.1)支持,1999 年首次发布。跨平台。支持 Win32、UNIX、Linux、Mac 等。代码紧凑,易于维护。
其实Tcl最大的特性在于它是一种字符串语言,几乎东西都默认为字符串。
Wiki示例
维基百科给出了两个示例,可以体验一下Tcl的强大:
echo_server.tcl:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| exec tclsh $0 ${1+"$@"} proc newConnection { sock addr port } { puts get_one_client puts $addr puts $port fconfigure $sock -blocking no -buffering line fileevent $sock readable [ list handleData $sock ] } proc handleData { sock } { set info [ gets $sock ] puts $info puts $sock $info if { [ eof $sock ] } { close $sock } } set port [ lindex $argv 0 ] socket -server newConnection $port vwait forever
|
语法还是很简练的,可以使用以下的Python代码测试连接服务器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| import threading import socket import time class MyThread(threading.Thread): def run(self): msg = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Expedita repudiandae, \ laborum non officiis. Ratione debitis sapiente nesciunt, quas dolore, magni aspernatur \ ipsum numquam error quae eligendi aliquid adipisci omnis in.\n" try: sock = socket.socket() sock.connect(('localhost', 12345)) sock.send(msg) res = sock.recv(2048) print res sock.close() except Exception as error: print error sock.close() time.sleep(10) def main(): print "Start main threading" threads = [MyThread() for i in range(300000)] for t in threads: t.start() for t in threads: t.join() print "End Main threading" if __name__ == '__main__': main()
|
运行时需要将server运行于12345端口。然后运行python echo_client.py就可以了。
可以看出简单几行Tcl代码,实现的功能还不少(可以异步处理TCP请求)。
三行实现一个简单的时间显示GUI程序:
1 2 3 4 5 6
| proc every {ms body} {eval $body; after $ms [info level 0]} pack [label .clock -textvar time] every 1000 {set ::time [clock format [clock sec] -format %H:%M:%S]}
|
虽然以上代码还不能完全理解,但是也能猜个大概,以后慢慢熟悉。
这里tclsh和wish都是Tcl语言的交互解释器,wish提供了一个GUI环境,可以通过简单代码构建带有图形界面的窗口应用。
下面通过几个示例脚本初步了解下Tcl的语法:
hello.tcl:
1 2 3 4 5 6 7 8
| expr 2*10 - 1 expr 2**10 + 1; puts bye puts "\a" exit 1
|
一个计算阶乘的实例:
factorial.tcl:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| exec tclsh "$0" "$@" proc factorial {val} { set result 1 while {$val > 0} { set result [expr $result*$val] incr val -1 # incr自增变量 -1为增量 } return $result } puts [factorial 10] # 使用方括号调用函数 puts [factorial 1] puts [factorial 20] puts [factorial 50]
|
最简单GUI应用(一个按钮,点击退出)
1 2 3 4 5
| button .b -text "hello world!" -command "puts bye\a; exit" pack .b
|
这里.b类似HTML中的id,-text参数类似HTML中的button元素上的内容 -command 参数是点击按钮时候的效果,这里打印出bye和警告音,然后退出。
一个计算阶乘的GUI应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| exec wish "$0" "$@" proc factorial {val} { set result 1 while {$val>0} { set result [expr $result*$val] incr val -1 } return $result } entry .value -width 6 -relief sunken -textvariable value label .description -text "factorial is " label .result -textvariable result button .calculate -text "Calculate" -command {set result [factorial $value]} button .exit_btn -text "Exit" -command "puts exit; exit" bind .value <Return> { .calculate flash .calculate invoke } grid .value .description .result -padx 1m -pady 1m grid .calculate - - -padx 1m -pady 1m grid .exit_btn - - -padx 1m -pady 2m
|
打印出来鼠标在画板的位置,如果按下键盘a字母输出信息”a is pushed”
position.tcl:
1 2 3 4 5 6 7
| exec wish "$0" "$@" bind . <Motion> {puts "pointer at %x,%y"} bind . <a> {puts "a is pushed"}
|
以下是一些小的代码片段组成的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| exec tclsh "$0" "$@" puts [expr sin(10)] set num 11111 puts "num is $num" puts [expr $num % 8] puts [lindex {red blue pink} 2] set length [string length aaaaaaabbbbbb] puts "length is $length" set a 1 set b 2 puts "$a+$b = [expr $a+$b]" set name a.out set msg "Counldn't open file \"$name\"" puts $msg set msg {Eggs: $2.18/dozen Apple: $3.09/dozen} puts $msg proc counter {value list} { set count 0 foreach el $list { if $el==$value { incr count } } return $count } puts [counter 1 {1 2 3 4 5 6 1 1 }] puts [glob *.tcl] set name color_blind set greet [format {"%s" said: hello world!} $name] puts $greet set city "Los Angeles" set bigcity $city puts $city
|
运行结果:
1 2 3 4 5 6 7 8 9 10 11 12
| -0.5440211108893699 num is 11111 7 pink length is 13 1+2 = 3 Counldn't open file "a.out" Eggs: $2.18/dozen Apple: $3.09/dozen 3 clock.tcl echo_server.tcl factorial.tcl get_pos.tcl gui_factorial.tcl hello.tcl style_button.tcl try.tcl var_example.tcl "color_blind" said: hello world! Los Angeles
|