tcl 這個語言想法很簡單,每行程式碼都是一個指令,指令後面接參數。指令與參數間用空格隔開。指令的結尾一般是換行符號,有可能是] (當然,放在 {} 裡的字串不會被當作用該字串作為參數的指令當成指令結尾,下面有範例)。例如:
puts "abcd"上面指令會顯示 abcd
puts {123 456}
雖然 puts 後面有一個換行符號,然而它不會被當作指令結尾。因為它在 {} 裡面,因此被當作參數的一部分,所以不會當作指令結尾。 而在 } 後面的換行符號不在 {} 裡面,所以會被當作 puts 的指令結尾。所以上面的指令意思是把 123\n456 當作參數,傳進 puts 這個指令。
放在 {} 與 "" 裡的東西都會被視為字串。當你使用 {} 時,當不會修改裡面的內容,裡面是什麼,結果就是什麼。例如,你放 \n 在裡面,它會把它當作兩個字元,而非一個換行字元。 "" 則會做一些代換,例如,它會把 \n 當作換行字元, 它會把 $ 開頭的變數代換該變數所代表得值。像這樣。
set a 5 puts "$a\n"
像上面的程式碼,它會印出5 加上一個換行。
因為 tcl 中所有東西都是字串,因此你要做運算時,必須使用 expr 指令。
set a 5 set b [expr "$a + 5"] puts $b
上面的指令,先把 a 這個變數的值設定成 5。 [] 比較特別,它會把裡面所包含的字串當作 tcl 指令來執行,[] 所代表的值,就是裡面指令執行完後的值。 expr 會把後面的參數當作運算式做運算, 因為變數 a 的值是5, 所以"$a + 5"的 $a 會被換成 5。因此 expr 接受到的參數是 expr " 5 + 5",傳回運算式的結果是10。所以 [ expr "$a + 5" ] 的值是 10。所以 b 的值將被設定成10。 puts $b 就是顯示變數 b 的值。
tcl 的 if 也是一個指令,它會把第一個參數當作運算式,做運算。當運算式結果為真時,則會執行第二個參數裡面的指令。 tcl 中非零的情形皆為真。
set a 5 if "$a == 5" { puts a puts b }
上面的程式碼結果會印出 a\n\b\n。 \n 是指換行。因為 if 會把第一個參數當作運算式,所以你不用加 expr。 把第二個參數當作程式碼,所以你不必使用 []。迴圈的概念也和 if 相似,所以就不介紹了。
接下來介紹如何建立自己的指令(函數)。要建立自己的指令,是使用 proc 這個指令。第一個參數是該指令的參數列,第二個參數是該指令要執行的程式碼。 參數列裡,每個參數用空格隔開。如果要給參數預設值,則用 {} 把參數名稱和預設值包在一起。像下面程式碼。
proc test {a b {c 5}} { set ret [expr "$a + $b + $c"] puts ret return ret } test 1 2 3 test 1 2
test 的第三個參數 c,它的參數預設值是5。
接下來講變數視野的部分,這是程式設計很重要的議題。因為 tcl 傳參數都是傳值。所以指令無法修改到上層指令的變數。那如果有這個需求時,怎麼辦?
此時只能靠 upvar 這個指令解決。假設 upvar 接受兩個參數。 upvar 的第一個參數值是 otherVar,第二個參數值是 myVar,而 funA 呼叫 funB, funB 呼叫 upvar otherVal myVar,則 upvar 會去 funB 的上一層 funcA 找變數 otherVal,如果找不到則自己建一個。然後和 funB 的 myVar 建立連動關係。當 funB 的 myVar 改變時, funA 的 otherVal 的值也會改變。如以下程式碼。
set x 5 proc test {a} { upvar x y set y $a } test 1 puts $x
由於 test 把 x 的值改成 1 。 因此顯示 x 的值會是 1 。
變數名稱 :: 開頭的為全域變數。如下所示
set ::x 5 proc test {a} { set ::x 8 } test 1 puts $::x
我會對 tcl 有興趣主要是因為它的程式設計理念與其他程式語言不同,大部分的程式語言都脫離不了C語言的影子(lisp 、 prolog 又是另一種流派了)。而 tcl 是一種以命令、字串為導向語言,十分特別。
沒有留言:
張貼留言