每种语言都有其擅长和不足的地方,在某项工作甚至工作的某一部分中选择合适的语言往往可以达到事半功倍的效果。所以,多掌握一些知识是很有必要的,当然了也可以用一些大语言,比如说
C
或者
Java
,它们几乎是可以通吃一切问题的,但是付出的代价一样高昂,一些可以用几行
Perl
或者
Python
实现的功能,换作
Java
可能需要花费几倍的工作量,所以这里就不谈了。
在很久以前,为了方便工作人员录制电视节目,我用
Perl
写了一个基于
Tk
的设置界面。界面如下图:
大致上就是设置一个时间,然后在该时间点自动启动一个录制程序。当时由于时间仓促,本着够用就好的精神,很快就写好了,所以难免留下一些
bug
。比如说设置完之后,没有将按钮重置为退出。这还是小事,最主要的还是一旦录制程序启动,整个界面就被阻塞,这是
windows
下
Perl
的老毛病了,几乎无药可救。
其实即便如此,这个程序还是可以顺利使用的,但是作为一个解决长时间运算阻塞界面的办法,将它移植到
Tcl
上,还是有一些意义的。在上一篇随笔中,我大致讲到了
filevent
和
select
在
windows
下的差别,正好可以在这里验证一下,同时通过移植的过程,也可以更清楚地了解和区分两种语言在某些功能上的不同实现办法。最终实现的工具如下图
:
这里将代码拆分开来进行分析。
首先是界面部分,这一部分其实是最简单的,所以在实现上几乎一样,只不过是语法上的差别而已。有一点值得注意的是
Tcl
中是不需要的
mainloop
这样的命令来显式地启动主循环。
第二,因为定时启动需要计算启动时间与当前事件的差值,所以需要处理一些时间相关的参数。
Perl
中可以使用
localtime
来得到年份、月、日和秒等共
9
个值,供组合使用。在
Tcl
中,有一个
clock
命令,通过
format
可以实现类似的功能,感觉上
Tcl
的更方便一些。相同的感觉也处理时间差值时也存在,因为
Perl
中需要拆分一个某种形式的时间表达式,提取必要参数给
timelocal
计算总秒数,而
Tcl
的
clock
有
scan
可以直接生成。
第三,在像
Perl
的
BrowseEntry
和
Tcl
的
ComboBox
的下拉框中,经常会插入一串连续的数字。
Perl
可以使用形如“(
1..10
)”来表示
1-10
这
10
个数字,但是在
Tcl
里没有类似的命令,所以当遇到大数组表达式的时候,最好是写一个方法来模拟
Perl
中的这种功能。
proc listOfNum {from to {step 1}} {
set lst [list ]
set index $from
while {$index <= $to} {
lappend lst $index
set index [expr $index + $step]
}
return $lst
}
第四,为了确保录制任务在制定的时间点启动,需要有检查是否超时。在
Tcl
里这个实现因为有
after
变得很轻松,只要指定一个需要等待时间戳,
Tcl
就会在过晚这段时间之后启动需要执行的指令,而
Perl
就麻烦多了。在
Tk
的
mainloop
中,使用
repeat(1000, sub {…})
使其每隔一秒钟执行一次检查,看是否超时。一旦检查到超时则停止检查并启动录制;若没有则提示继续下次检查。
第五,在如何启动录制这点上,两者使用了不同的手段。
Tcl
使用管道来启动进程,使得自身不被阻塞(不过在使用producer的时候还是会阻塞,用ping就没问题,这个很奇怪),并且使用
filevent
监测打开句柄的状态。而
Perl
因为不可靠的
select
,我们只能使用
system
,通过阻塞的办法来获知任务是否完成,这也是一个无可奈何的事情了。
(代码下载)