TCL, což je akronym pro Tool Command Language (podle anglické fonetiky se čte tikl), je jazyk s poměrně jednoduchou syntaxí, který lze použít v mnoha oblastech. Dá se říci, že Tcl je jakousi modifikací unixového shellu, která není určena za denní chleba, ale k vytváření přehledných skriptů. Je tedy vhodný pro menší programy, k automatizaci určitých úkonů atd. Pro ty, kteří znají shell, nebude problém se jej naučit.
Tcl je interpretovaným jazykem. Proto není překládán do samostatně spustitelného strojového kódu, ale potřebuje interpreter. Díky němu je Tcl na platformě nezávislý, což z něj dělá ještě mocnější nástroj. Existují implementace i pro MS Windows a Apple Macintosh.
Tento jazyk je snadno rozšiřitelný, a proto také je takovýchto rozšíření opravdu dost. Většina slouží k nějakému speciálnímu účelu. Nicméně bezesporu nejznámějším a nejpoužívanějším je rozšíření Tcl o podporu vytváření GUI. Nazývá se Tk (Tool Kit) a pomocí něho můžete vytvářet prakticky cokoli, co od GUI očekáváte. Původně bylo implementováno pouze pro UNIX, nyní je podporováno i pro MS Windows či MacOS. O tomto tématu se chci ještě později zmínit. Tcl se často se používá právě kvůli své grafické nadstavbě Tk, která je velmi dobře navržená a na pár řádcích či stránkách je možno vytvořit plnohodnotné a kompletní GUI pro váš program. Dalším rozšířením je např. itcl [incr tikl], které rozšiřuje Tcl o OOP model, nebo Snack, který zase přidává multimediální funkce pro podporu zvuku.
Jak jsem již uvedl výše, ke spuštění programu v jazyce Tcl potřebujete jeho interpreter. Ten by měl být součástí každé trochu významnější distribuce Linuxu. V balíku Tcl najdete tclsh. Můžete jej používat jako jakýkoliv jiný interpreter: předat mu soubor v argumentu obsahující zdrojový kód, soubor se zdrojovým kódem označit direktivitou jádra #!/program/ke/spusteni, nebo jej spustit bez argumentů a za prompt přímo zadávat příkazy, které jsou ihned vykonávány – to se hodí při experimentování.
Příkazy jsou od sebe odděleny znakem nový řádek, chcete-li dlouhý příkaz rozložit do více řádků, použijte zpětné lomítko \ na konci řádku. Několik příkazů na tomtéž řádku musíte rozdělit pomocí středníku;. Příkazy jazyka Tcl vypadají následovně:
příkaz argument ?volitelný_argument?
Takovýto zápis používá dokumentace dodávaná s jazykem Tcl. Vyjadřuje, že příkaz má jeden povinný argument a jeden volitelný argument, který nemusí být uveden, ale ovlivní chování příkazu.
Proměnné
Proměnné v jazyce Tcl prakticky nejsou navenek žádného datového typu. Interpreter za běhu dokáže rozpoznat a náležitě konvertovat obsah. Tudíž žádné int, float, boolean atd. Prostě přiřadíte hodnotu a Tcl se postará o zbytek.
Výše jste si mohli všimnout syntaxe takového příkazu v jazyku Tcl. Tato syntaxe je používána i pro aritmetické operace. Např. pro přiřazení existuje příkaz set:
set proměnná ?hodnota?
Za proměnná vložte název proměnné a za hodnota její hodnotu. Všimněte si, že druhý argument je v otaznících. Je to tedy volitelný argument, který když vynecháte, příkaz set jen vrátí hodnotu proměnné proměnná. Zkuste si tedy následující:
set var "Hello World" puts $var
V prvním řádku nastavíme proměnnou var na hodnotu Hello World. Ve druhém řádku vytiskneme její hodnotu pomocí příkazu puts.
Jsou tu ale dvě zvláštnosti, které stojí za pozornost:
- První řádek obsahuje pozdrav v uvozovkách. Ne, že by to byl řetězec, o to se starat nemusíte, jak jsem již řekl. Problém je, že tento řetězec obsahuje bílý znak, a proto by si interpreter myslel, že se jedná o dva argumenty. A to by bylo špatně!
- Na druhém řádku musíme použít $var, protože se odkazujeme na hodnotu proměnné a ne na samotnou proměnnou. Je to stejné jako v shellu.
Další důležitou věcí je nahrazování. Představte si, že pokračujeme ve výše uvedeném příkladu a vy hodláte doslovně tisknout: pozdrav obsahuje promenna $var.
puts "pozdrav obsahuje promenna $var"
Výsledek bude: pozdrav obsahuje promenna Hello World. Jinými slovy, potřebujete zamezit rozvinutí proměnné $var. To můžete udělat hned dvojím způsobem:
puts "pozdrav obsahuje promenna \$var" puts {pozdrav obsahuje promena $var}
- S prvním řešením se již seznámil asi každý z vás. Před znak speciálního významu se vloží zpětné lomítko. Tím znak ztrácí speciální význam.
- Druhé řešení je uzavřít řetězec do složených závorek. Tím ztrácí speciální význam naprosto všechny znaky, které mezi nimi jsou.
Jsou situace, kdy potřebujete vykonat určitý kód a návratovou hodnotu tohoto kódu předat do komplexnějšího výrazu. Kýženého výsledku dosáhnete tím, že daný kód uzavřete do hranatých závorek. Tento kód se pak provede jako první a poté bude jeho místo nahrazeno návratovou hodnotou tohoto kódu. Je to podobné jako shellovský $(příkaz) nebo příkaz
.
Je možno si explicitně vynutit vykonání určitého řetězce, jako by se jednalo o programový kód. Toho dosáhnete příkazem eval, kterému takovýto řetězec předáte. Ukažme si to na příkladu:
set sayHello {puts "Hello World"} eval $sayHello
Příkaz eval vykoná obsah proměnné sayHello, jako by se jednalo o kdejaký jiný kód. Je to velmi výkonný mechanismus, díky kterému vaše skripty mohou např. za běhu dynamicky generovat kód, který budou později provádět, nebo tento kód posílat po síti klientovi, pomocí čehož jej budou ovládat. V tomto směru se fantasii žádné meze nekladou.
Matematické operace jsou také zajištěny pomocí příkazu. Tímto příkazem je expr. Samotný interpreter je natolik jednoduchý, že neobsahuje ani tyto operace, místo toho se spoléhá na rozšiřující příkaz, který to udělá za něj.
Příkaz expr toho zvládne dost. Obsahuje aritmetické, logické a bitové operace, jejichž operátory jsou stejné jako v Céčku, takže nemá smysl je tady vypisovat. Ale ukažme si pár příkladů:
set a [expr 1 + 1] set b [expr 5 % 2] set result [expr $a == $b] set result [expr $a == [expr $b + 1]]
Na těchto příkladech vidíte jak použití příkazu expr, tak i použití hranatých závorek pro vyhodnocení. Také si všimněte, že i když samotný interpreter Tcl neví nic o výrazech, díky rozšíření o další příkaz to skoro nevadí.
Vezměme si první řádek z příkladu. Příkaz set má nastavit proměnnou a. Ve druhém argumentu interpreter narazí na hranatou závorku a usoudí, že nejdříve musí vykonat ji. Spustí tedy příkazexpr a předá mu tři argumenty 1, +, 1. expr vrátí 2 a interpreter tudíž nahradí hranatou závorku číslem 2. Výsledek: set a 2 – proměnná a má odteď hodnotu 2.
Práce s poli
Snad každý programovací jazyk obsahuje pole, ani Tcl není výjimkou. Tcl je v této oblasti zvláštní, protože samotný interpreter neumí pracovat s poli jako s celky (což je rys spíše jazyka nižší úrovně), ale na druhé straně podporuje speciální typ pole, jemuž se říká asociativní pole (a to je rys spíše vysokoúrovňového jazyka). Tento typ pole se vyznačuje tím, že jako index do něj nemusíte používat celočíselný typ, ale např. i řetězec nebo číslo v plovoucí desetinné čárce. Tento index uzavřete do kulatých závorek za název pole.
set pole(8) 3 set pole(5) petka set pole(3.14) pi set pole(pi) 3.14 puts $pole(8) puts $pole(pi) # set pole1 pole2 -- NELZE !!!
Jedno pole v jazyce Tcl tedy může obsahovat více datových typů, a to jak v hodnotě, tak i v indexu (ve skutečnosti interpreter se vším zachází jako s řetězci, a jakmile potřebujete jiný datový typ, přistoupí k automatické konverzi, o kterou se ovšem starat nemusíte). Také si všimněte, že k přístupu do pole je nutno před název pole přidat $, jako je tomu u proměnných.
Pro práci s poli je určen příkaz array, který umí pracovat s celými poli a má následující tvar:
array operace názevpole ?arg arg ...?
Za operace vložíte název operace, jenž se má s polem pole provést. Pokud to operace dovoluje, je možno uvést i další argumenty. Mějte na paměti, že zde pracujeme se samotnými proměnnými, nikoliv s jejich hodnotami. Musíte tedy uvádět název proměnných bez znaku $. Dále uvádím některé operace:
array get názevpole ?vzor? | Vrací všechny prvky, popřípadě prvky, jejichž index se shoduje se vzorem vzor. |
---|---|
array names názevpole ?vzor? | Vrací názvy indexů, jež se shodují se vzorem vzor. Pokud vzor není uveden, vrací všechny indexy. |
array set názevpole seznam | Vrací nové pole, jež obsahuje prvky ze seznamu seznam. Seznamy viz níže. |
array exists názevpole | Ověřuje existenci pole názevpole. |
array size názevpole | Vrací počet prvků v poli názevpole. |
Toto je jen rychlý výčet. Další informace najdete v dokumentaci dodávané s jazykem Tcl.
Seznamy
Jazyk Tcl podporuje i práci se seznamy. Seznam je skupina objektů libovolného typu, na kterém lze provádět operace jako na celku. Zároveň je možno se odvolávat na jednotlivé prvky pomocí číselného indexu. Seznamy se zapisují pomocí složených závorek, jednotlivé prvky se oddělují bílým znakem. Tady opět uvádím nějaké příklady:
set seznam {ano ne} set seznam { {rock jazz} {tragedie komedie} } set seznam { 1 {2 3} 4 {5} { 6 {sest six} } sedm}
Nelze přehlédnout skutečnost, že seznam může obsahovat další seznamy a ty zase další seznamy. Můžete je do sebe libovolně zanořovat. Následuje stručný výčet příkazů pro práci se seznamy:
list ?arg arg …? | Příkaz list vytváří nový seznam z předaných argumentů, pokud nějaké má, jinak vytvoří prázdný seznam. |
---|---|
lindex seznam index | Vrátí prvek v seznamu seznam na pozici index. |
llength seznam | Vrací velikost seznamu seznam. |
linsert seznam index arg ?arg arg …? | Vloží jeden nebo více arg do seznamu seznam od pozice index. Můžete použít slovo end pro konec seznamu. |
lappend proměnnáSeznamu ?arg arg …? | Přidá jeden nebo více arg do seznamu proměnnáSeznamu. Tento příkaz očekává samotnou proměnou, tedy bez $. |
Praxe s těmito příkazy by mohla vypadat takto:
set novySeznam [list 1 dva 3] puts [llength $novySeznam] lappend novySeznam 4
Jazyk Tcl se dobře orientuje v textově zaměřených systémech pro analýzu různých textových zdrojů apod. Obsahuje příkazy, které dokáží řetězec převést na seznam a obráceně. Jsou jimi:
split řetězec ?oddělovače? join seznam ?oddělovače?
Každý již jistě pochopí, co který dělá, a z výše uvedených příkladů jej bude schopen aplikovat. Potřebujete-li nápovědu, podívejte se do dokumentace k jazyku Tcl.
Tímto bych ukončil nejen podkapitolu o seznamech, ale také tento díl. V dalším bych se chtěl zmínit o programových konstrukcích v jazyce Tcl a pokročilejších funkcích.
Oficiální dokumentace je většinou v linuxových distribucích ve formátu manuálových stránek. Nezapoměnte, že se vyskytují v sekci 3tcl, takže je zapotřebí man 3tcl join místo pouhého man join, které by Vám nejspíš zobrazilo shellovský join v sekci 1. Také neuškodí, když navštívíte server spol. Scriptics. Tam najdete jak programy, tak i dokumentaci a vše, co budete potřebovat při práci s jazykem Tcl.