Tcl

Z Wikipedie, otevřené encyklopedie
Skočit na: Navigace, Hledání

Tcl (vyslovuje se „tý-sý-el“ nebo „tykl“, název je zkratka z Tool Command Language) je jednoduchý, ale poměrně mocný skriptovací jazyk, který vytvořil John Ousterhout v roce 1988. Přes svoji nezvyklou syntaxi je snadno zvládnutelný, nemá velké nároky na hardware a používá se k prototypování, vytváření nástrojů pro testování softwaru i k programování vestavěných systémů. Knihovna Tk pro vytváření grafických uživatelských rozhraní vyvinutá pro jazyk Tcl se stala prototypickou knihovnou pro další skriptovací jazyky (Perl, Python, Ruby). Přestože Tcl je možné používat i bez knihovny Tk, pro běžné operační systémy je Tk obvykle součástí Tcl balíčku, proto se pro Tcl často používá označení Tcl/Tk.

Vlastnosti[editovat | editovat zdroj]

Základní vlastnosti:

  • imperativní jazyk – program se skládá pouze z příkazů
  • všechny příkazy (i řídicí struktury) mají jednotnou strukturu v postfixové notaci (výrazy ale používají obvyklou infixovou notaci)
  • příkazy mohou mít proměnný počet parametrů
  • všechny příkazy mohou být dynamicky předefinovány nebo přetíženy
  • všechny datové typy i text programu mohou být reprezentovány jako textové řetězce
  • událostmi řízené rozhraní pro sokety a soubory; lze používat časové a uživatelem definované události
  • viditelnost proměnných implicitně omezena na lexikální oblast platnosti, příkazy uplevel a upvar dovolují procedurám komunikovat s obklopujícími funkcemi
  • všechny příkazy definované přímo jazykem Tcl generují při chybném použití chybová hlášení
  • snadná rozšiřitelnost pomocí jazyka C, C++, Java nebo samotného Tcl
  • interpretovaný jazyk používající bytecode, text programu se dá vytvářet za běhu
  • plná podpora Unicode 3.1 od roku 1999
  • přenositelnost – samotný jazyk, i mnoho knihoven (včetně Tk) jsou nezávislé na platformě (Windows, Unix, Linux, Mac)
  • úzká integrace s knihovnou grafického uživatelského rozhraní Tk

Spuštění Tcl[editovat | editovat zdroj]

Tcl má dva interprety:

  • tclsh – textový
  • wish – grafický; zahrnuje knihovnu Tk

Oba interprety lze spustit bez parametrů a pracovat s Tcl interaktivně:

tclsh
% expr 56*7
392
% exit

– procento (%) je nápověda interpretu (dále už není uváděno), expr je příkaz pro vyhodnocení matematického výrazu, hvězdička je symbol pro násobení; interpret se ukončí příkazem exit nebo znakem konce souboru, kterým je v Microsoft Windows a v MS-DOSu klávesová kombinace Ctrl-Z, v Unixu Ctrl+D.

Použití grafického interpretu:

wish
label .pozdrav -text Ahoj
pack .pozdrav -padx 40 -pady 20

Obvyklejší přístup je ale spouštění předem připravených programů neboli skriptů:

tclsh program.tcl parametr parametr ...

Souborům s programy v jazyce Tcl se obvykle dává přípona .tcl. Aby v Unixu bylo možné pouštět Tcl skripty pouze zadáním jejich jména, je potřeba dát souboru se skriptem právo execute a na jeho začátek přidat první čtyři řádky z následující ukázky:

#!/bin/sh
# -*- tcl -*-
# The next line is executed by /bin/sh, but not tcl \
exec tclsh "$0" ${1+"$@"}
 
puts "Hello, world!"

První řádek díky konstrukci Shebang zajistí, že se skript začne interpretovat programem /bin/sh; provedením příkazu exec se spustí tclsh, který začne číst soubor se skriptem zase od začátku, ale řádek s příkazem exec považuje za pokračování komentáře z předchozího řádku díky jeho zakončení obráceným lomítkem.

Syntaxe a základní sémantika[editovat | editovat zdroj]

Program (skript) v Tcl je tvořen voláním jednoho nebo více příkazů. Příkaz je posloupnost slov oddělených mezerami nebo jinými bílými znaky ukončená koncem řádku nebo středníkem:

slovo0 slovo1 slovo2 ... slovoN

Slova se mohou zapisovat třemi způsoby:

  • ohraničená pouze mezerami nebo bílými znaky
  • uzavřená v uvozovkách (aby mohla obsahovat bílé znaky)
  • uzavřená ve složených závorkách, které zabraňují provádění substitucí

První slovo je jméno příkazu. Jména příkazů v Tcl nejsou vyhrazená slova, ani nemají v jazyce žádné zvláštní postavení; jsou to obyčejné, nijak neprivilegované, funkce v knihovně. Další slova jsou argumenty:

příkaz argument1 argument2 ... argumentN

Příkazy mohou mít proměnný počet parametrů. Pokud slova obsahují mezery, je nutné je napsat do uvozovek nebo jiných operátorů seskupení.

Symboly se zvláštním významem[editovat | editovat zdroj]

  • $ – vrací hodnotu proměnné, jejíž jméno je uvedeno za znakem dolar
  • [] – závorky včetně obsahu nahradí výstupem Tcl příkazu, který je v závorkách uzavřen
  • "" – spojí obsah uvozovek do jednoho řetězce (slova), vyhodnocuje vnořené konstrukce s $, [] a \
  • {} – spojí obsah závorek do jednoho řetězce (slova) aniž by interpretoval speciální znaky uvnitř
  • \ – ruší zvláštní význam následujícího znaku nebo vytváří řídicí znak nebo znak se zadaným kódem
  • # – uvozuje komentář, který končí s koncem řádku; lze použít pouze v místě, kde může začínat příkaz

Apostrofy nemají v Tcl žádný zvláštní význam. Kulaté závorky nemají zvláštní význam, používají se pro přístup k prvkům asociativních polí a pro vyjádření priority v aritmetických výrazech.

Příkaz puts[editovat | editovat zdroj]

Příkaz puts vypíše zadaný řetězec (který musí tvořit jedno slovo, proto je vhodné jej vždy uzavírat do uvozovek) následovaný znakem konce řádku, implicitně na standardní výstup (kanál stdout):

puts "Hello, world!"

Pokud puts nemá po vypsání řetězce odřádkovat, je potřeba před řetězcem použít volbu -nonewline:

puts -nonewline "Dobrý "
puts "den!"

Před vypisovaným řetězcem lze uvést jméno výstupního kanálu (nebo proměnnou, která se odkazuje na soubor):

puts stderr "Chyba!"

Proměnné a příkaz set[editovat | editovat zdroj]

Pro přiřazení hodnoty do proměnné slouží příkaz set; pro získání obsahu proměnné je nutné před její jméno napsat znak dolar:

set x 5
puts "Hodnota proměnné x je $x."

Vypíše:

Hodnota proměnné x je 5.

Pokud není jednoznačné, co je jméno proměnné, lze jméno uzavřít do složených závorek “${foo}

Tcl není staticky typovaný jazyk: každá proměnná může obsahovat hodnotu libovolného typu – např. celé číslo, reálné číslo, řetězec, seznam, jméno příkazu nebo slovník; hodnoty se převádějí na jiné typy podle potřeby automaticky (s omezeními danými syntaxí). Hodnoty jsou ale vždy konstantní (immutable); operace, které vypadají, že mění hodnoty, ve skutečnosti pouze vrací jinou hodnotu.

Přiřazení hodnoty výrazu do proměnné není tak jednoduché; je potřeba použít příkaz expr a operátor seskupení.

Asociativní pole[editovat | editovat zdroj]

Asociativní pole je složená datová struktura, ve které se pro přístup k jednotlivým položkám používá klíč, kterým může být libovolný textový řetězec. S prvky asociativních polí se pracuje stejně jako s jednoduchými proměnnými:

set hlavni_mesta(ČR) "Praha"
set hlavni_mesta(Slovensko) "Bratislava"
set hlavni_mesta(Polsko) "Varšava"
set hlavni_mesta(Německo) "Berlín"
set hlavni_mesta(Rakousko) "Vídeň"
puts "Hlavní město Slovenska je $hlavni_mesta(Slovensko)."

Asociativní pole lze také vytvořit pomocí příkazu array set:

array set hlavni_mesta {
  "ČR"         "Praha"
  "Slovensko"  "Bratislava"
  "Polsko"     "Varšava"
  "Německo"    "Berlín"
  "Rakousko"   "Vídeň"
}
puts "Hlavní město Slovenska je $hlavni_mesta(Slovensko)."

Oba skripty vypíšou:

Hlavní město Slovenska je Bratislava.

Operátory seskupení[editovat | editovat zdroj]

Před provedením každého příkazu Tcl provede vyhodnocení proměnných a vnořených příkazů (tzv. substituce nebo expanze). Substituci lze řídit pomocí operátorů seskupení. Jazyk Tcl má 3 operátory seskupení:

  • Uvozovky ""
  • Složené závorky {}
  • Hranaté závorky []

Operátory seskupení propůjčují jazyku Tcl nezaměnitelný charakter, jsou však zároveň i příčinou proč se mu mnoho programátorů vyhýbá.

Uvozovky[editovat | editovat zdroj]

Uvozovky se chovají stejně jako v mnoha jiných skriptovacích jazycích: vytvářejí řetězec z posloupnosti slov a zároveň nezabraňují expanzi proměnných. Pokud se mají do řetězce vložit uvozovky, je nutné před nimi napsat obrácené lomítko; obrácené lomítko také ruší význam dolaru jako prostředku pro expanzi hodnoty proměnné:

puts "Prvek $i pole \$arr má hodnotu \"$arr($i)\"."

Pokud je v proměnné i hodnota 8, a prvek pole $arr s indexem 8 (indexem může být i řetězec) obsahuje řetězec "osmička", vypíše se

Prvek 8 pole $arr má hodnotu "osmička".

V uvozovkách mají některé posloupnosti začínající znakem obrácené lomítko význam řídicích nebo jiných znaků:

Posloupnost Význam
\n Znak nový řádek (line feed)
\r Znak návrat vozíku (carriage return)
\t Znak tabelátor (tab)
\v Znak vertikální tabelátor (vertical tab)
\a Znak zvonek (bell)
\b Znak backspace
\0nn Znak se zadaným kódem (v osmičkové soustavě)
\uHHHH Unicode znak U+HHHH
\xHH Znak se zadaným kódem (v šestnáctkové soustavě)

Hranaté závorky[editovat | editovat zdroj]

Do hranatých závorek lze zapsat libovolný příkaz Tcl včetně parametrů; příkaz v hranatých závorkách se provede před provedením příkazu, ve kterém je použit, a hranaté závorky se nahradí výstupem, který vyprodukuje. V následujícím příkladu je použit příkaz clock seconds, který vrací počet sekund od 1. 1. 1970 a příkaz clock format, který tento údaj zformátuje podle parametru uvedeného za volbou -format:

puts "Od 1. ledna 1970 uplynulo [clock seconds] sekund;"
puts "Je rok [clock format [clock seconds] -format "%Y"]."

vypíše

Od 1. ledna 1970 uplynulo 1366380049 sekund;
Je rok 2013.

Jak je vidět hranaté závorky a uvozovky lze vnořovat.

Nejčastější příkaz, který se píše do hranatých závorek je příkaz expr, který vyhodnocuje aritmetické výrazy:

set vyraz "1+2+3+4+5+6+7+8+9+10"
set vysledek [ expr $vyraz ]
puts "Součet $vyraz je $vysledek."

Vypíše

Součet 1+2+3+4+5+6+7+8+9+10 je 55.

Substituce pomocí hranatých závorek umožňuje použít výsledek jednoho příkazu jako argument dalšího příkazu. Pokud se má vyvolat příkaz jako funkce, která vrací hodnotu, musí se vždy uzavřít do hranatých závorek.

Tcl nepotřebuje operátor pro spojení řetězců, protože stačí jenom zapsat proměnné nebo příkazy v hranatých závorkách za sebe. Na rozdíl od unixových interpretů příkazů vyhodnocuje Tcl každý řetězec pouze jednou (pokud skript přímo nepředepisuje opakované vyhodnocení), což trochu komplikuje interaktivní použití, ale zprůhledňuje chování ve skriptech (např. mezery ve jméně souboru nepůsobí potíže známé z unixových shellů).

Složené závorky[editovat | editovat zdroj]

Obsah složených závorek se neexpanduje (jen je ignorován znak konce řádku, před kterým je zpětné lomítko). Pokud by se v příkazu puts použitém v části „Uvozovky“ nahradily vnější uvozovky složenými závorkami:

puts {Prvek $i pole \$arr má hodnotu \"$arr($i)\".}

výsledný výstup by vypadal značně odlišně; pravděpodobně úplně jinak, než bylo zamýšleno:

Prvek $i pole \$arr má hodnotu \"$arr($i)\".

Pokud jsou složené závorky vnořeny do jiných složených závorek, hranatých závorek nebo uvozovek, chovají se jako normální znak:

puts "Prvek {$i} pole \$arr má hodnotu {$arr($i)}."

vypíše

Prvek {8} pole $arr má hodnotu {osmička}.

Do složených závorek se uzavírají výrazy v příkazu expr, aby se zabránilo dvojí expanzi jména proměnných:

set i 10
set d "\$i"
puts [ expr 2*$d ]

Řídicí struktury[editovat | editovat zdroj]

Složené závorky se v Tcl používají pro vytváření řídicích struktur. Jejich syntaxe vychází ze syntaxe jazyka C, do složených závorek se v Tcl píšou nejen příkazy (i jeden příkaz musí být uzavřen ve složených závorkách), ale i podmínky. Při vytváření řídicích konstrukcí musí být okolo složených závorek (tj. před { a za }) vždy aspoň jeden bílý znak (mezera nebo konec řádku).

Interpretu Tcl je skutečnosti jedno, jaké operátory seskupení se použijí (a jestli vůbec nějaké). Vyžaduje pouze, aby jednotlivé konstrukce obsahovaly správný počet slov. Například v příkazu cyklu musí být za příkazem while dva parametry, každý tvořený jedním slovem; první je podmínka a druhý tělo cyklu.

Podmíněný příkaz[editovat | editovat zdroj]

Následující program ukazuje syntaxi podmíněného příkazu v Tcl; část else je nepovinná, příkaz může mít libovolný počet částí elseif:

if {$i > 0} {
  puts "$i je kladné číslo"
} elseif {$i == 0} {
  puts "$i je nula"
} else {
  puts "$i je záporné číslo"
}

While cyklus[editovat | editovat zdroj]

Následující ukázka použití while příkazu počítá Ludolfovo číslo \pi podle vzorce

\pi = \operatorname{arctg}\frac{1}{2} + \operatorname{arctg}\frac{1}{3}

kde funkce arkus tangens se počítá pomocí Taylorova vzorce

\operatorname{arctg} x = x-\frac{x^3}{3}+\frac{x^5}{5}-\frac{x^7}{7}+\frac{x^9}{9}-\ldots (pro x<1)
set platnych_mist 12
set epsilon "1e-$platnych_mist"
set znam 1.0
set moc2 [expr {1.0/2.0}]
set moc3 [expr {1.0/3.0}]
set n 1
set clen [expr {$moc2+$moc3}]
set suma $clen
while {abs($clen)>$epsilon} {
    incr n 2
    set znam [expr {-$znam}]
    set moc2 [expr {$moc2/4.0}]
    set moc3 [expr {$moc3/9.0}]
    set clen [expr {$znam/$n*($moc2+$moc3)}]
    set suma [expr {$suma+$clen}]
}
puts "Ludolfovo číslo: [format "%.${platnych_mist}G" [expr {4.0*$suma}]]"

Příkaz incr zvětší hodnotu proměnné, která je jeho prvním parametrem, o hodnotu zadanou druhým parametrem (nebo o 1, pokud druhý parametr chybí).

For cyklus[editovat | editovat zdroj]

V případě for cyklu se do vlastních složených závorek dává každý ze tří výrazů, které se v jazyce C píšou do kulatých závorek a oddělují středníky:

for { set i 1 } { $i <= 10 } { incr i } {
  puts "$i"
}

Definice funkcí[editovat | editovat zdroj]

Funkce se v Tcl definují příkazem proc, za kterým následují dvojí složené závorky; první obsahují seznam parametrů, druhé tělo funkce. Pokud má funkce vracet návratovou hodnotu, lze použít příkaz return (jinak vrací výsledek posledního provedeného příkazu). Naprogramovat výpočet faktoriálu rekurzivně sice není ideální, ale je to možné i v Tcl. Všimněte si, že Tcl umožňuje, aby jméno funkce byl vykřičník:

proc ! { n } {
    if {$n <= 1} {
        set res 1
    } else {
        set res [ expr {$n * [ ! [ expr { $n - 1}] ]} ]
    }
    return $res
}
 
for { set n 1 } { $n <= 20 } { incr n } {
  puts "$n! = [ ! $n ]"
}

Vhodnější výpočet faktoriálu bez rekurze by mohl vypadat takto:

proc ! { n } {
    set res 1
    for { set k 2 } { $k <= $n } { incr k } {
        set res [expr {$res*$k}]
    }
    return $res
}
 
for { set n 1 } { $n <= 20 } { incr n } {
  puts "$n! = [ ! $n ]"
}

Uživatelem definované funkce se volají stejně jako ostatní příkazy – parametry se píšou za jméno funkce a od jména funkce i sebe navzájem se oddělují mezerami nebo bílými znaky. Proto při volání funkce faktoriál není možné psát (jako v matematice) vykřičník za výraz, z něhož se má faktoriál počítat.

Většina příkazů jazyka Tcl jsou funkce s proměnným počtem parametrů. To platí i o příkazech ve standardní knihovně. Příkaz proc (konstruktor pro vytváření procedur/funkcí) umožňuje definovat implicitní hodnoty pro argumenty, které nebudou použity ve volání procedury, a parametr obsahující všechny argumenty, což umožňuje zpracování proměnného počtu argumentů ve funkcích.

Externí odkazy[editovat | editovat zdroj]

(anglicky)
(česky)