给大家安利一个免费且实用的前端刷题(面经大全)网站,👉点击跳转到网站。
是时候进行一些语言考古了!Tcl/Tk 是一种大家很少再看到的语言,但它在当时比较流行。它对嵌入非常友好——最初是一种用于编写现有应用程序的语言,而不是用于创建独立程序。它还带有内置的图形工具包(“Tk”部分),在它非常罕见的时候。
在新操作系统上安装 Tcl/Tk 是非常痛苦的。OSX 捆绑了一个过时的版本,当你运行一个 hello world 时会打印一个警告。要使用 brew 版本,我们必须使用 Tcl/Tk 可执行文件的完整路径(或弄乱$PATH
)。
如果你熟悉 Unix shell 脚本,就更容易理解 Tcl/Tk。如果我们将语言放在类似 unix-shell 的尺度上,它会是这样的:
$
印记,但仅此而已-nle
, $.
)#
评论UNIXshell 脚本的工作方式是每一行都是一个命令-行的第一个单词是命令名,其余的是字符串参数。变量都只包含字符串-数字42
和字符串“42
”之间没有真正的区别。如果行包含任何$X
,则在运行之前将其替换为变量 X 的字符串内容。TCL/TK 有点复杂,但这是一个很好的起点。
#!/usr/local/opt/tcl-tk/bin/tclsh
puts "Hello, world!"
我是不是不小心放成了 Ruby 代码?不,绝对没有。#!
指向完整路径的行是由于 OSX brew 问题,如果你在不同的系统上运行它,你将需要不同的系统。#
也用于评论。
#!/usr/local/opt/tcl-tk/bin/tclsh
set who "world"
puts "Hello, $who!"
变量都是字符串。内插双引号字符串。
需要注意的一件事是 $x 指变量的内容 x。
这是大多数语言没有的区别。即使在使用 sigils 的 Perl 或 PHP 中,也 $x 指变量(在=符号左侧)或其内容(在=符号右侧)。Shell 和 Tcl 对这两种情况进行了区分——它们没有 x=y 样式变量赋值。
#!/usr/local/opt/tcl-tk/bin/tclsh
set x 2
set y "4"
set z [expr $x+$y]
puts [string toupper Hello]
puts [string tolower "World"]
puts "$x + $y = $z"
puts {$x + $y = $z}
puts stdout hello
输出
HELLO
world
2 + 4 = 6
$x + $y = $z
hello
变量都是字符串,所以 2 和 "2"都是一样的。你通常不需要引用它们,因此hello在"hello"大多数情况下,它们是相同的。
可以[function arguments]用来调用函数。[string action argument]是一个奇怪的函数,它根据它的参数执行许多操作,应用于第二个。如你所见,你是否通过 Hello 或"Hello".
要进行数学运算,你需要调用[expr …]函数。由于所有变量都是字符串,因此单独x+ y执行任何操作都没有任何意义。
{…}也是一个字符串,但不像"…"它不插入任何东西。Tcl 有许多看起来像控制结构的东西,但在某种程度上,它们只是传递包含代码的此类字符串。
而对于最后一个,puts hello 它本身应该可以工作,但是 puts 有可选参数在哪里打印它,当你输入puts helloTcl 时,如果你打算将 puts hello 字符串输出到标准输出,或者 puts 任何默认值到 hello 流中,你会感到困惑。也许我们不要想太多,我只是想提一下,hello 在"hello"大多数情况下几乎是一样的,但并非总是如此。
在大多数语言中,我们可以立即获得 Fibonacci 和 FizzBuzz,但对于 Tcl,我们必须在此之前采取一些额外的步骤。
#!/usr/local/opt/tcl-tk/bin/tclsh
proc fib n {
if { $n <= 2 } {
return 1
} else {
return [expr [fib [expr $n-1]] + [fib [expr $n-2]]]
}
}
for {set i 1} {$i <= 30} {incr i} {
puts [fib $i]
}
让我们一步一步来:
好的,看起来不错。除了那大多是谎言。{ }没有定义一个块,它只是我们传递的一个字符串。if, else, proc,return而不是关键字 - 它们只是命令。
所以这个糟糕的代码做同样的事情:
#!/usr/local/opt/tcl-tk/bin/tclsh
"proc" "fib" "n" {
"if" { $n <= 2 } "return 1" "else" { "return" [expr ["fib" [expr $n-1]] + [fib ["expr" $n-2]]] }
}
"for" "set i 1" {$i <= 30} "incr i" { puts [fib $i] }
#!/usr/local/opt/tcl-tk/bin/tclsh
proc fizzbuzz n {
if { $n % 15 == 0 } {
return "FizzBuzz"
} elseif { $n % 3 == 0 } {
return "Fizz"
} elseif { $n % 5 == 0 } {
return "Buzz"
} else {
return $n
}
}
for {set i 1} {$i <= 100} {incr i} {
puts [fizzbuzz $i]
}
这是 GUI hello world:
#!/usr/local/opt/tcl-tk/bin/wish
wm geometry . 800x600
button .hello -text "Hello, World!" -command { exit }
pack .hello
这是它的样子:
请注意可执行文件从 更改tclsh为wish。
这与浏览器的工作方式非常不同。我们没有在某些标记中定义应用程序的结构,并且有代码来控制它——我们只是发出命令来直接控制 GUI:
wm geometry . 800x600- 将窗口大小设置为 800x600 button .name -text “…” -command {…}- 使用给定的文本和给定的 onclick 命令创建按钮,并将其保存到变量name pack .name- 将小部件放在name窗口中(默认水平居中,在顶部)
接下来让我们实现点击计数器:
#!/usr/local/opt/tcl-tk/bin/wish
set counter 0
proc plus_one args {
global counter
incr counter
}
proc minus_one args {
global counter
set counter [expr $counter-1]
}
wm geometry . 800x600
label .counter -textvariable counter -font "Helvetica -64"
button .plus -text "+1" -command plus_one -font "Helvetica -48"
button .minus -text "-1" -command minus_one -font "Helvetica -48"
place .counter -x 400 -y 200 -anchor s
place .minus -x 400 -y 300 -anchor e
place .plus -x 400 -y 300 -anchor w
这是它的样子:
让我们回顾一下:
2021 年不是真的。对于常规编程,实际上有数百种更好的编程语言。对于嵌入式应用,我认为几乎每个人都转向 JavaScript、Lua 或 Python 等,或者基本上是 Tcl/Tk 以外的任何东西。
至于你的 shell 脚本的快速 GUI,Tk 是一个相当糟糕的工具包,我在我的 Electron Adventures 系列中介绍了许多更好的工具包。但即使你真的想使用 Tk,不知何故,由于历史原因, Ruby 和 Python 等许多现代语言在其标准库中仍然包含某种 Tk 代码。
Tcl/Tk 实际上只是作为一种历史产物感兴趣,而不是作为一种任何人都可能认真用于新软件的语言。
我什至很难说它对其他语言和 GUI 系统有多大影响。大多数 Tcl 特性也可以在 Unix shell 脚本和比 Tcl 早几个月发布的 Perl 中找到。因此,Unix shell 或 Perl 的影响可以更好地解释任何相似之处。旧风格的 GUI 几乎被浏览器风格的 GUI 所取代,所以我无法判断 Tk 是否对其他 GUI 工具包影响很大。在我看来,它基本上过期了,没有任何实际影响。有些语言已经过去了,但留下了很多遗产——就像大多数 ES6+ JavaScript 特性都来自 CoffeeScript;Perl 对几乎所有后 Perl 语言都产生了巨大的直接或间接影响。对于 Tcl/Tk,我真的没有看到类似的东西。它做了它的事,然后它就静静地死去,现在它几乎被遗忘了。