Documente noi - cercetari, esee, comentariu, compunere, document
Documente categorii

Indrumator Tcl

INTRODUCTIE

Bine ati venit la acest indrumator Tcl. L-am scris cu scopul de a ajuta la invatarea in Tcl. Este cu scopul pentru cei care au cateva cunostinte depre programare, cu toate ca nu trebuie sa fii cu siguranta un expert. Acest indrumator intentioneata sa va insoteasca catre manualul Tcl , pagini care furnizeaza referinte despre toate comenzile Tcl.

Este impartit in scurte sectiuni acoperind diferite aspecte ale limbii. Depinde pe ce retea esti,  poti oricand sa te uiti in referinta pentru o documentare a unei comenzi de care esti curios. Pe unix de exemplu , in timp ce am 'aduce' sus pagina initiala pentru comanda intreaga.

Fiecare sectiune este insotita de exemple relevante cate iti arata cum sa pui in folosinta materialul respectiv.




SURSE ADITIONALE


Comunitatea Tcl este exagerat de pretentioasa. Este frumos din partea ta daca incerci lucrurile de unul singur, dar daca nu intelegi, suntem acolo ca sa te ajutam.

Aici sunt cele mai bune locuri sa ceri ajutor:

La comp.lang.tcl newsgroup. Acesibil via newsreader , sau Grupuri Google

Wiki are o buna distribuire a codului, exemple si discutii ale celor mai bune puncte ale pacticarii Tcl.

Daca ai nevoie de ajutor imediat, pe canalul #tcl vei gasi mereu pe irc.freenode.net care te poate ajuta, dart e rog sa nu-ti pierzi cumpatul daca nimeni nut e va ajuta pe moment - daca aveti nevoie de nivelul de suport, considerati a angaja un consultant.

Sunt mai multe carti recomandate pentru cei care vor sa patrunda in cunoasterea Tcl-ului. Clif Flynt original autor al acestui indrumator este si autor al Tcl/Tk: A Developer's Guide. Alte care folositoare : Practical Programming in Tcl and Tk.


CREDITE


Multumim prima data si celui dintai lui Clif Flynt, facand acest material valabil sub o licienta BSD. Multumiri si urmatorilor : Neil Madden, Arjen Markus, David N. Welton

Desigur , asteptam comentarii si sugestii despre cum poate fi imbunatatit - sau este bun asa, nu ne deranjeaza putinele multumiri.

Text Simplu Produs

Traditionalul start plasat pentru indrumator este programul "Hello, world". Odata ce poti tipari un String, esti pe drumul cel bun in folosirea Tcl-ului pentru distractie si profit.

Comanda pentru a produce un Sting in Tcl este comanda puts.

O singura unitate de text dupa comanda puts va fi tiparita la mecanismul de producere standard ( in acest caz, in fereastra de jos ). Lispa comportamentului este sa tipareasca o noua linie caracter ("intoarcere") potrivita pentru system dupa tiparirea textului.

Daca stringul are mai mult decat un cuvant, trebuie sa cuprinzi stringul in ghilimele sau o acolade (). Un set de cuvinte cuprinse in ghilimele sau acoladele sunt considerate ca o singura unitate, cat timp cuvintele sunt separate prin spatiu se considera mai multe argumete la comanda. Ghilimele si acoladele pot fi folosite in mai multe grupuri de cuvine intr-o singura unitate. Oricum, ele se vor purta diferit. In lectia urmatoare veti invata diferentele in comportamentul lor. Nota in Tcl, o singura ghilimea nu este semnificanta, cum sunt in programarile C, Perl si Pyton.

Multe comenzi ale Tcl-ului (incluzand puts) pot accepta mai multe argumente. Daca un string nu este cuprinsa intre ghilimele sau acolade, interpretul Tcl-ului va considera fiecare cuvant in parte fiind argument.si trece la fiecare individual comanda puts. Comanda puts va incerca sa evalueze fiecare cuvant ca un argument optional. Aceasta probabil va rezulta o eroare.

O comanda din Tcl este o lista de cuvinte terminate intr-o singura line sau de punct si virgula (;). Comentariile in Tcl sunt cu # la inceputul fiecarei linii, sau terminarea comenzii se face cu punct si virgula (;).

Example


puts 'Hello, World - In quotes' ;#Acesta este un comentariu.
puts # *Eroare* - nu exista punct si virgula!

puts 'This is line 1'; puts 'this is line 2'

puts 'Hello, World; - Cu punct si virgule in interior'

ATRIBUIREA UNEI VALORI LA O VARIABILA

In Tcl, totul poate fi reprezentat ca un string, cu toate ca in interior poate fi reprezentat ca o lista, intreg, dublu, sau alt tip, pentru a face sa mearga limba mai repede.


Atribuirea in Tcl se face cu ajutorul comenzii set.


Cand set este chemat de doua argumente can in :

set fruit 'Cauliflower'

plasarea celui de al doilea argument ('Cauliflower') in memorie spatiul se refera pentru primul argument (fruit). Set intotdeauna se intoarce la continutul primei variabile numita in primul argument si apoi se intoarce la al doilea. In exemplul de mai sus, pentru moment, se va intoarce la 'Cauliflower', fara ghilimele.

Primul argument la comanda set poate fi oricare singur cuvant, ca fruit sau pi sau poate fi un membru al unui array. Despre arrays vomd discuta mai multe mai tarziu, pentru moment amintiti-va ca mai multe date pot fi numite sub un singur nume de variabila, si ca data individuala poate fi accesata de indexul cuprins in acel array. Indexand in acel array in Tcl este manevrat de punerea indexului intre paranteze dupa numele variabilei.

Set poate fi invocat cu un singur argument. Cand este chemat cu un singur argmument, se va intoarce la continutul acelui argument.


Aici un mic rezumat despre comanda set :


Set varNAME? value?

if value este specificat, atunci continutul variabilei varNAME este egal cu value.

if varNAME consta in numai caractere aflanumerice, si nici o paranteza, este o variabila scalara.

if varNAME are forma varNAME(index) , este un membru asociat array.

Daca ne uitam in exemplul code, vei observa ca in cadrul comenzii set primul argument este tiparit numai cu numele lui, dar cand declaram puts este precedat cu $.

Semnul dolarului comanda Tcl-ului sa ia valoarea din variabila - in acest caz X sau Y.

Tcl trece date la fiecare subrutina de la nume sau de la valuare. Comenzile care nu schimba continutul variabilei uzuale au argumente proprii trecute in valoare.

Exemplu


set X 'This is a string'

set Y 1.24

puts $X
puts $Y

puts '.'

set label 'The value in Y is: '
puts '$label $Y'

EVALUAREA SI SUBSTITUIREA 1 : GRUPAREA ARGUMETELOR CU GHILIMELE ""



Aceasta lectie este una din cele trei despre care vom discuta cum Tcl-ul manevreaza substituirea in timpul preluarii comenzii.

In Tcl, preluarea unei comenzi se face in in doua faze. Prima faza este unica trecere a substituirii. Cea de a doua faza este preluarea rezultatului comenzii. Numai unul trece de substituirea facuta. Astfel in comanda puts $varName, continutul variabilei adecvate este inlocuita pentru $varNAME, si apoi comanda este exacutata. Asumand ca avem set varNAME la "Hello World" , secventa va fi vazuta asa: puts varNAME puts "Hello World" , care este executat si tiparita Hello World.
In timpul fazei de substituire, mai multe tipuri de substituiri au loc.
O comanda in paranteze patrate ( [ ] ) este inlocuita cu rezultatul executiei comenzii. (Aceasta va fi explicate in mai multe amanunte in lectia "Rezultatul unei comenezi - Math 101.")
Cuvinte cuprinse intre ghilimele sau accolade sunt grupate intr-un singur argument. Oricum, ghilimele si acoladele cauzeaza o diferenta de comportament in timpul fazei de substituire. In aceasta lectie, ne vom concentra aspura comportamentul ghilimelelor in timpul fazei de substituire.
Grupand cuvinte cuprinde de ghilimele permit substituirii sa se petreaca in citate - sau, in cunoscutul termen, "interpolare". Grupul substituit va fie evaluat ca un singur argument. Astfel in comanda puts 'The current stock value is $varName', continutul current pentru varNAME este substituit pentru $varNAME, si intregul string este tiparit la procedeul de productie, ca si in exemplul de mai sus.
In general, backslash-ul (), opreste substituirea pentru un character imediat urmat de backslash. Orice alt character urmat imediat de un backslash va sta fara substituire.
Oricum, este specific "Secventa backslash", stringul care este inlocuit de o valuare specificain timpul fazei de substituire. Urmatoarele stringuri backslash vor fi inlocuite cum sunt aratate mai jos:

String

Output

Hex Value

a

Audible Bell

0x07

b

Backspace

0x08

f

Form Feed (clear screen)

0x0c

n

New Line

0x0a

r

Carriage Return

0x0d

t

Tab

0x09

v

Vertical Tab

0x0b

0dd

Octal Value

d is a number from 1-7

xhh

Hex Value

h is a hex digit 0-9,A-F,a-f


Exceptia finala este la sfarsitul fiecarei linii dintr-un text. Aceasta cauzeaza ca interpretul sa ignore noua linie, si trateaza textul ca o singura linie din text. Interpretul va insera un spatiu gol la sfarsitul backslash-lui.

Exemplu


set Z 'Albany'
set Z_LABEL 'The Capitol of New York is: '

puts '$Z_LABEL $Z';# Prints the value of Z
puts '$Z_LABEL $Z' ;# Prints a literal $Z instead of the value of Z

puts 'nBen Franklin is on the $100.00 bill'

set a 100.00
puts 'Washington is not on the $a bill' ;# This is not what you want
puts 'Lincoln is not on the $$a bill';# This is OK
puts 'Hamilton is not on the $a bill' ;# This is not what you want
puts 'Ben Franklin is on the $$a bill' ;# But, this is OK

puts 'n.. examples of escape strings'
puts 'TabtTabtTab'
puts 'This string prints out non two lines'
puts 'This string comes out
on a single line'



EVALUARI SI SUBSTITUIRI 2 : GRUPAREA ARGUMENTELOR CU ACOLADE


In timpul fazei de substituire a comenzii evaluate, cele doua grupuri operatoare, acoladele () si ghilimele (""), sunt tratate diferit de catre interpretul Tcl.

In lectia precendenta ati observat ca gruparea cuvintelor in ghilimele lasa substituirea sa se petreaca in ghilimele. Grupand cuvinte cuprinse intre doua acolade opresc substituirea cuprinsa intre ghilimele. Caracterele cuprinse intre acolade sunt trecute in comanda exact cum sunt scrise. Numai "Secventa Backslash" care proceseaza in interiorul acoladelor au backslash la fiecare sfarsit de linie. Aceasta este tot o prelungire a caracterului.

Tineti minte ca acoladele au effect numai cand sunt folosite pentru grupuri (i.e. la inceput si la sfarsitul unei secvente de cuvinte). Daca un string este deja grupat, fie cu ghilimele fie cu acolade, si acoladele sunt in mijlocul stringului grupat (i.e. "foo

puts 'n. examples of differences in nesting '
puts

puts 'n.. examples of escape strings'
puts
puts



EVALUARI SI SUBSTITUIRI 3 : GRUPAREA ARUMENTELOR CU PARANTEZE PATRATE []


Poti obtine rezultatul unei comenzi punand comanda in paranteze patrate ([]). Este un echivalent functional al aprotrofului ( ` ) in programarea sh, sau folosind valoarea de intoarcere a unei functii in C.

Asa cum un Tcl interpret citeste in fiecare linie se schimba toate $variables cu valorile lor. Daca o portie din string este grupat in paranteze patrate, atunci stringrul dintre parantezele patrate este evaluat ca o comanda de catre interpret si rezultatul inlocuieste paranteze patrate string.

Sa luam urmatorul segment ca exemplu:

puts [readsensor [selectsensor]]]


O analiza a comenzii, se vede ca este o commanda pentru executarea substituirii: readsensor [selectsensor] , care este trimisa catre interpret pentru evaluare.

Analizand inca odata gasim o comanda care sa fie evaluate si substituita, selectsensor.

Fictive comanda selectsensor este evaluata, si dupa cum se pare se intoarce la sensor sa fie citit.

In acest moment, readsenzor are un sensor de citit, si readsenzor este comanda evaluate.

In final, valoarea de la readsenzor este trecuta in spatele comenzii puts, care este tiparita pe ecran.


Exceptiile are regulei sunt urmatoarele:

O paranteza patratacare este scapata de un este considerate ca o paranteza patrata literala.

O paranteza patrata intre acolade nu este modificata in timpul substitutiei.



Exemplu

set x 'abc'
puts 'A simple substitution: $xn'

set y [set x 'def']
puts 'Remember that set returns the new value of the variable: X: $x Y: $yn'

set z
puts 'Note the curly braces: $zn'

set a '[set x ]'
puts 'See how the set is executed: $a'
puts '$x is: $xn'

set b '[set y ]'
puts 'Note the escapes the bracket:n $b is: $b'
puts '$y is: $y'

REZULTATUL UNEI COMENZI - MATH 101



Comanda Tcl pentru a face operatii de tip matematice este expr. Urmatoarea discutie o vom avea despre comanda expr extrasa si adaptata de pe pagina principala.

Expr ia toate din argumentele ("2+2" de exemplu) si evalueaza recultatul ca Tcl "expresie" (mai mult decat o comanda normala) si se intoarce la valoare. Operatorii permint in expresiile Tcl sa includa toate funtiile matematice standarde, operatori logici, operatori bitwise, la fel ca si funtiile mathematice ca rand() , sqrt() , cosh() si altele. Expresiile aproape mereu produc rezultate numerice (interger sau valori floating-points)

Tip de performare: cuprinzand toate argumentele din expr in acolade va rezulta un cod mai rapid. Deci poti sa faci expr inloc de expr $i * 10.


OPERANZII


O expresie Tcl consta intr-o combinatie de operanzi, operatori si paranteze. Spatiul poate fi folosint intre operanzi, operatorii si parantezele: este ignorata de catre expresia procesorului. Unde este posibil ca operanzii sa fie interpretati ca valori integer. Valorile integer poti decimale (in cazuri normale), octal (daca caracterul operandului este 0 zero), sau hexadecimale (daca primele doua caractere ale operandului sunt 0x).

Nu uitat ca transformarea octalului si decimalului au loc in diferite locuri ale comenzii expr in faza de substituire a Tcl-ului. In faza de substituire, x32 poate fi convertit in ascii "2", cat timp expr poate converta 0x32 in 50 de decimale.

Daca un operand nu are una din formatele integer date mai sus, atunci este tratata ca un numar floating-points, daca este posibiil. Numerele floating-points pot fi specificate in una din caile acceptate de un ANSI-compiliant compilatorul C. De exemplu toate din urmatoarele numere floating-points sunt valide: 2.1, 3., 9.91e+16. Daca interpretarea numerica nu este posibila, atunci operandul este lasat ca un string (si numai un set limitat de operatori se vor aplica pentru el).


Operanzii pot fi specificati in mai multe forme:


Ca o valuare numerica, interger sau floatin-points.

Ca o variabila Tcl, folosint notatii standard $. Valoarea variabile va fi folosita de catre operand.


OPERATORII


Operatorii care sunt valizi sunt listati mai jos:


Unary minus, unary plus, bit-wise NOT, logical NOT. Nici unul din acesti operatori nu poate fi aplicat la un operand string, si bit-wise NOT poate fi aplicat numai in integer

Inmultire, impartire, rest. Nici unul din acesti operatori poate fi aplicat la un operand string, dar restul poate fi aplicat numai la integer, restul va avea intotdeauna acelasi semn ca ce al divizorului, si o valoarea absoluta mai mica decat a divizorului.

adunare si scadere. Sunt valide pentru operanzi numerici.

<< >> Valid pentru operanzii integer.

&  bit-wise AND. Valid pentru operanzi integer.

^bit-wise exclusiv OR. Valid pentru operanzi integer.

| bit-wise OR. Valid pentru operanzi integer.

&&  Logical AND. Produce un singur rezultat daca ambii operanzi sunt non-zero, sau chiar 0. valid pentru oepranzii numerici (integer sau floating-points).

Logical AND. Produce 0 rezultate, daca ambii operanzi sunt zero, altmiteri 1.

x?y:z  if-then-else, exact ca in C.daca valuarea lui x este diferita de zero, atunci rezultatul este valuarea lui y. Altmiteri este rezultatul valorii lui z. Operandul x trebuie sa aiba o valoare numerica.


FUNCTII MATEMATICE


Tcl-ul suporta urmatoarele functii matematice:


acos coshypotsinh
asin cosh log sqrt
atan explog10tan
atan2 floor pow tanh
ceil fmod sin

TIPURI DE CONVERSIUNI

Tcl-ul suporta urmatoarele functii de convertire de la reprezentarea unui numar la altul :abs double int round

Exemplu

set X 100;
set Y 256;
set Z [expr '$Y + $X']
set Z_LABEL '$Y plus $X is '

puts '$Z_LABEL $Z'
puts 'The square root of $Y is [expr sqrt($Y)]n'

puts 'Because of the precedence rules '5 + -3 * 4'is: [expr -3 * 4 + 5]'
puts 'Because of the parentheses'(5 + -3) * 4' is: [expr (5 + -3) * 4]'

puts 'n.. more examples of differences between ' and
puts '$Z_LABEL '
puts 'The command to add two numbers is: [expr $a + $b]'



COMPARATORI NUMERICI 101 - IF



Ca in majoritatea limbilor, Tcl-ul o comanda daca este scrisa asa:

if expr1 ?then? body1 elseif expr2 ?then? body2 elseif ?else? ?bodyN?

Cuvintele then si else sunt optionale, cu toate ca in general then este lasat si else este folosit.

Un test al expresiei urmarind if va trebui sa rezulte una din urmatoarele:

fals adevarat

o valuare numerica 0 toate celelalte

yes/no no yes

true/false false true


Daca expresia returneaza "yes"/"no" sau "true"/"false", cazul de returnare nu este verificat. True/FALSE sau YeS/nO, sunt raspunsurile bune.

Daca evaluarea testului este True, atunci body1 va fi executat.

Daca evaluarea testului este False, urmatorul cuvant dupa body1 va fi examinat. Urmatorul cuvant este elseif, atunci urmatoarea expresie a testului va fi testate ca o conditie. Daca urmatorul cuvant este else atunci cuvantul body va fi evaluat ca o comanda.

Expresia testului urmata de cuvantul if este evaluate in aceiasi maniera ca in comanda expr

Expresia testului urmat de if poate cuprinde ghilimele, acolade. Daca este cuprinsa in interiorul acoladelor, o sa fie evaluate in interiorul comenzii if, daca if cuprinde ghilimeleva fi evaluate in tipul fazei de substitutie, si apoi alta repriza de substituiri vor fi facute in interiorul comenzii if.

Exemplu

set x 1
if else
if else
if $x==1
set y x
if '$$y != 1' else

COMPARAREA TEXTULUI - SWITCH


Comanda switch te lasa sa-ti alegicateva optiuni pentru codul tau. Este similara cu switch din C, cu o exceptie ca e mai flexibila, pentru ca poti sa "switch" stringuri, inloc de interger. Stringul va fi comparat cu un set de modele, si daca un model seamana cu acel string, codul asociat cu acel model vor fi evaluate.

E o idée buna sa folosesti comanda switch cand vrei sa potrivesti o variabila impotriva multor valori posibile, sin u vrei sa faci o lunga serie de if.elseif.elseif.

Comanda se scrie asa:

  • switch string pattern1 body1 ?pattern2 body2? ?patternN bodyN?

- sau -

  • switch string

String este stringul pe care doresti sa-l testezi, si pattrn1, pattern2,etc sunt modelelecare stringul le va compara. Daca string se potriveste cu un model, atunci codul din body asociat cu acel model vor fi executate. Valuarea returnata din body va fi returnata ca valoarea returnata din afirmatiile switch. Numai un model se va potrivesti.

Daca ultimul argument pattern este un default string, atunci modelul se va potrivi cu orice string. Aceasta garanteaza ca, cateva din setarile codului vor fi executate indiferent de continutul stringului.

Daca nu este nici un argument default, si nici un model care sa se potriveasca cu acel string, atunci comanda switch va returna un string gol.

Daca folosesti versiunea comenzii cu acolade,nu vor exista substituiri facute in model. Corpul comenzii,totusi, va fi analizat si evaluat la fel ca fie care comanda, si acolo va fi o trecere a substitutiei facute acolo, la fel va fi facuta si in prima sintaxa. Avntajul formei a doua este ca poti sa scrii multiple comenzi pe o singura linie citite cu parantezele patrate.

Nota:   poti folosi acolade pentru a grupa argumentul body cand folosim comenzi cum ar fi switch si if. Aceasta pentru ca aceste comenzi trec argumentul body la interpretul Tcl pentru evaluare. Aceasta evaluare include o trecere a substitutiei asa cum se face pentru cod nu in interiorul comenzii argumentului body.

Exemplu


set x 'ONE'
set y 1
set z 'ONE'

# This is probably the easiest and cleanest form of the command
# to remember:
switch $x
ONE
TWO
THREE
default

switch $x '$z' ONE TWO THREE   default
switch $x 'ONE' 'puts ONE=1' 'TWO' 'puts TWO=2' 'default' 'puts NO_MATCH'
switch $x
'ONE'     'puts ONE=1'
'TWO'    'puts TWO=2'
'default'                  'puts NO_MATCH';



Buclarea 101 - While loop

Tcl include doua comenzi pentru looping, while si for. La fel ca afirmatia if ele evalueaza testul lor exact la fel cum face si expr. In aceasta lectie vom discuta despre comanda while si in lectia urmatoare despre comanda for. In majoritatea circumstantelor unde una din aceste comezi poate fi folosita, si cealalta poate fi folosita de asemenea.

while test body

Comanda while evalueaza textul ca o expresie. Daca test este adevarat, atunci body poate fi executat. Dupa ce codul din body a fost executat, test va fi evaluat din nou.

Afirmatia continue cuprinsa in body va opri executia codului si test va fi reevaluat. Break cuprins in body va intrerupe while bucla. Si executia va continua cu o noua linie a codului dupa body.

In Tcl everything este o comanda, si everything trece prin aceiasi faza de substituire. Pentru un motiv, test trebui trecut intre acolade. Daca test este trecut intre ghilimele, faza de substituire va inlocui orice variabila cu valoare curenta, si va trimite acel test la comanda while pentru evaluare, si de atunci test va avea numai numere, si cu probabil desavarsire va conduce la un final al buclei !

Uitati-va la cele doua bucle din exemplu. Daca nu era o comanda break in a doua bucla, buclarea era continua.

Exemplu

set x 1

# This is a normal way to write a Tcl while loop.

while

puts 'exited first loop with X equal to $xn'

# The next example shows the difference between '..' and
# How many times does the following loop run? Why does it not
# print on each pass?

set x 0
while '$x < 5' break
if '$x > 3' continue
puts 'x is $x'


puts 'exited second loop with X equal to $x'



Buclarea 102 - For si incr


Tcl sustine loop-ul repetat format similar loop-ului for din C. Comanda for din Tcl este formata din patru argumente: o initiere, un test, o crestere si corpul codului de evaluat la fiecare trecere prin loop. Sintaxa pentru comanda for este :

for start test next body

In timpul evaluarii comenzii for,codul start este evaluat o singura data, inaintea evaluarii oricarui alt argument.Dupa ce codul start a fost evaluat, urmeaza evaluarea codului test. Daca test este dovedit a fi adevarat, codul body este evaluat si ,in sfarsit, incepe evaluarea codului next. Dupa evaluarea argumentului next, interpretul se intoarce la test si repeta procesul. Daca testul se dovedeste a fi fals, atunci loop-ul va iesi imediat.



Start este portiunea de initializare a comenzii. De obicei este folosita pentru a porni variabila repatarii,dar care poate contine orice cod pe care doriti sa il porniti inainte de inceperea loop-ului.

Argumentul test este evaluat ca o expresie, la fel ca si in comenzile expr while si if.

Next este o comanda comuna de crestere, dar poate contine orice comanda pe care interpretul Tcl o poate evalua.

Body este corpul codului de executat.

Pentru ca in mod normal nu se doreste ca faza de substituire a interpretului Tcl sa schimbe variabilele la valorile sale curente inainte de a trece controlul pentru comanda for, este normal sa se grupeze argumentele in legaturi ondulate. Cand sunt folosite legaturi pentru grupare, linia noua nu este tratata ca finalul unei comenzi Tcl . Astfel, devine mai simplu sa se foloseasca comenzi din linii multiple. Totusi, legatura de inceput trebuie sa fie pe aceeasi linie cu comanda for sau ,in alt caz interpretul Tcl va considera inchizatura legaturii next ca sfarsitul comenzii si va rezulta o eroare. Asta este diferit fata de alte limbaje ca C sau Pearl unde nu conteaza unde se pun legaturile.

In codul body, comenzile break si continue pot fi folosite ca si comanda while. Cand o comanda break este intalnita, loop-ul iese imediat.Cand o comanda continue apare, evaluarea body-ului stagneaza si test este reevaluat. Pentru ca sporirea variabilei repeterii este asa de comuna, Tcl are si o comanda speciala pentru asta

incr varName ?increment?

Aceasta comanda adauga valoarea in al doilea argument la variabila numita in primul. Daca nu este data nici o valoare celui de-al doilea argument ,totul va scadea la 1.

Exemplu

for

for

puts 'Start'
set i 0
while

set i 0
incr i
# This is equivalent to:
set i [expr $i + 1]



ADAUGANG COMENZI NOI         IN TCL - PROC


In Tcl nu exista nici o distinctie intre comenzi( deseori cunoscute ca "functii" in alte limbi) si "sintaxa". Nu exista cuvinte speciala (ca if sau while), asa cum exista in C, Java, Python, Pearl etc..Cand interpretul Tcl incepe, exista o lista de comenzi pe care acesta le foloseste pentru a analiza o linie. Aceste comenzi includ while, for, set, puts etc..Totusi, exista si niste comenzi Tcl uzuale care raspund acelorasi reguli de sintaxa ca toate comenzile Tcl, ambele construite si cele pe care le creezi chiar tu cu ajutorul comenzii proc.

Comanda proc creeaza alta comanda.Sintaxa pentru comanda proc este:

proc name args body

Cand proc este evaluata, se creeaza o noua comanda cu numele name care presupune argumente args. Cand incepe procedura name, porneste si codul continut de body.

Args este lista argumentelor care vor trece la name. Cand name este invocat, vor fi creeate variabile locale cu aceste nume si variabilele care urmeaza a trece la name vor fi copiate la variabilele locale.

Valoarea pe care body-ul unui proc o returneaza poate fi definitivata cu ajutorul comenzii return. Comanda return va returna argumentul sau la programul initiator. Daca nu exisat nici un raspuns, body-ul se va intoarce la initiator atunci cand ultima comanda a fost executata. Valoare de inapoiere a ultimei comenzi devine valoarea de inapoiere a procedurii.

Example

proc sum ];
return $x

puts ' The sum of 2 + 3 is: [sum 2 3]nn'
proc for
for

Variatii in argumentele proc si valorile de intoarcere

O comanda proc poate fi definita cu ajutorul unui numar scazut de argumente necesare (asa cum s-a intamplat si cu sum in lectiile anterioare) sau poate avea un numar variabil de argumente. De asemenea un argument poate fi definit ca posesorul unei valori lipsa.

Variabilele pot fi definite cu o valoare scazuta prin plasarea numelui variabilei si absenta in interiorul acoladelor cuprinse in arument si predefinitul in legaturi in args. De exemplu:

proc justdoit }

Din moment ce exista argumente predefinite pentru variabilele b si c, procedura poate fi numita in trei modalitati : justdoit 10, care ar fixa a la 10 si ar lasa b la valorea normala de 1 si c la -1. In alt caz, justdoit 10 20 ar seta b la 20 si ar lasa c la valoarea sa normala.

Un proc va accepta un numar variabil de argumente daca ultimul argument notat contine cuvantul args. Daca ultimul argument al unui argument proc este args, atunci oricare argumente care nu sunt deja atribuite unei variabile anterioare vor fi atribuite lui args.

Procedura exemplu de mai jos este definita cu trei argumente. Macar un argument "trebuie" sa fie prezent cand este strigat example. Al doilea argument poate fi exclus, iar in acel caz va scadea la un rand gol. Prin numirea lui args ca ultim argument,example poate avea un numar variabil de argumente.

A se retine ca daca exista o alta variabila in afara lui args dupa o variabila cu o scadere, atunci scaderea nu va fi niciodata folosita. De exemplu, daca numesti un proc asa : proc function  c} , mereu va trebui sa il sustii cu trei argumente.

Tcl atribuie valori unor variabile ale unui proc in ordinea in care sunt aliniate in comanda. Daca dai 2 argumente cand numesti function acestea vor fi atribuite lui a si b, iar Tcl va genera o eroare pentru ca c este nedefinit

You can, however, declare other arguments that may not have values as coming after an argument with a default value. For example, this is valid:

proc example args}

In acest caz, example are nevoie de un singur argument care va fi atribuit variabilei required. Daca exista doua argumente, al doilea ii va fi atribuit lui default1. Daca exista 3 argumente, primul ii va fi atribuit lui required, al doilea lui default1,iar al treilea lui default2. Daca un exemplu este numit cu mai mult de trei argumente, toate argumentele dupa al treilea vor fi atribuite lui args.

Exemplu

proc example args} else else



set count1 [example ONE]
set count2 [example ONE TWO]
set count3 [example ONE TWO THREE ]
set count4 [example ONE TWO THREE FOUR]

puts 'The example was called with $count1, $count2, $count3, and $count4 Arguments'

Variabila scope - global si upvar


Tcl evalueaza un nume variabil din interiorul celor doua domenii: domeniul local din interiorul unui proc si un domeniu global (codul si variabilele din exteriorul unui proc). Ca si C, Tcl defineste numai un singur domeniu global.

The scope in which a variable will be evaluated can be changed with the global or upvar command. Domeniul in care o variabila va fi evaluata poate fi schimbat cu ajutorul omenzilor global si upvar.

Comanda global va cauza evaluarea variabilei in domeniul global in locul celui local.

Comanda upvar are un comportament similar. Upvar asociaza numele unei variabile din domeniul curent cu o variabila dintr-un domeniu diferit. Este o metoda uzuala pentru a simula referinta de trecere la procs.

Sintaxa pentru upvar este:

upvar ?level? otherVar1 myVar1 ?otherVar2 myVar2 ?

Upvar face ca myVar1 sa devina referinta lui otherVar1 si  ca myVar2 sa devina referinta lui otherVar2, etc. Cealalta variabila otherVar este declarata a fi la un nivel relativ la procedura curenta current . Prin scadere nivelul 1 este urmatorul nivel.

Daca un numar est folosit pentru un nivel atunci referintele de nivel se fac la urmatoarele nivele care se aduna dupa nivelul curent.

Daca numarul level-ului este prcedat de simbolul # atunci referinta se face multe scaderi de la domeniul global. Daca level este #0 atunci referirea este la o variabila la un nivel global.

Parerea mea personala este ca folosind un upvar cu orice in afara de #0 sau 1 inseamna creearea unro probleme.

Folosirea globalului este greu de evitat, dar trebuie evitat a avea multe variabile globale. Daca se incepe a avea nevoie de multe globale. Ar trebuie sa fie revizuit designul.

A se observa ca pentru ca exista numai un singur spatiu global este surprinzator de banal faptul ce exista conflicte de nume daca se importeaza codurile altor persoane si acestea nu sunt atente. Este recomandabil a se incepe variabilele globale cu un prefix identificabil pentru a ajuta la evitarea unor conflicte.


Exemplu


proc SetPositive else
return $myvar


SetPositive x 5
SetPositive y -5

puts 'X : $x Y: $yn'

proc two

proc one

one y                             ;# Call one, and output X and Y after the call.

STRUCTURI DE DATE TCL - LISTA


Lista este o structura de baza in Tcl. O lista este pur si simplu o colectie ordonata de lucruri, numere,cuvinte, linii etc. De exemplu, o comanda in Tcleste doar o lista in care prima intrare este numele unui proc, iar urmatorii memebrii din lista sunt argumente la proc.

Listele pot fi creeata prin diferite metode :

prin schimbarea unei variabile intr-o lista de valori


set lst }

with the split command

set lst [split 'item 1.item 2.item 3' '.']

with the list command.

set lst [list 'item 1' 'item 2' 'item 3']

Un membru individual din lista poate fi accesat cu ajutorul comenzii lindex.

Descrierea sumara a acestor comenzi este:

list ?arg1 arg2 ?

makes a list of the arguments

split string ?splitChars?

Divide randul intr-o lista de item la splitChars SplitChars scade pentru a incepe un spatiu nou. A se observa ca daca exista doua splitchars-uri unul dupa altul in randul divizat, atunci fiecare va fi analizat ca marcand o intrare in lista si va crea o intrare goala in lista.. Daca splitchars este un rand, atunci fiecare membru al randului va fi folosit pentru a divide string in membrii ai listei. Ie:

split '1234567' '36']

intr-o lista compusa din .

lindex list index

returneaza itemul index din lista. Primul item este 0.

llength list

Inapoiaza numarul de elemente dintr-o lista.

Itemii listei pot fi repetati folosind comanda foreach.

foreach varname list body

Foreach va executa codul body o singura data pentu fiecare itemi ai listei din list. Piecare pass, varname va contine valoarea urmatorului list item.

Exemplu

set x 'a b c'
puts 'Item 2 of the list is: [lindex $x 2]n'

set y [split 7/4/1776 '/']
puts 'We celebrate on the [lindex $y 1]'th day of the [lindex $y 0]'th monthn'

set z [list puts 'arg 2 is $y' ]
puts 'A command resembles: $zn'

set i 0;
foreach j $x


Adaugarea si stergerea membrolor din lista

Comanda pentru a adauga si a sterge membrii este

concat ?arg1 arg2 argn?

Inlantuie args-urile intr-o singura lista. De asemenea elimina spatiile de inceput si uramtoare din args si adauga un singur spatiu de separare intre agrs .Args-urile  la concat pot fi ori elemente individuale,ori liste. Daca un arg este deja o lista , continutul acelei liste este inlantuit cu celealte args-uri .

lappend listName ?arg1 arg2 argn?

Anexeaza args-urile la lista listName tratand fiecare arg ca un element al listei.

linsert listName index arg1 ?arg2 argn?

Inapoiaza o noua lista cu noi listari inserate chiar inainte de elementul index al listName-ului. Fiecare elememt argument va deveni un element separat al noiii liste. Daca indexul este mai mic sau egal cu zero, atunci noile elemente sunt inserate la inceputul listei. Daca indexul are ultima valoare sau daca este mai mare sau egal cu numarul de elemente din lista, atunci noile elemente sut anexate la lista.

lreplace listName first last ?arg1 argn?

Inapoiaza o noua lista cu N listName elemente inlocuite de args. Daca intaiul este mai putin sau egal cu 0, atunci Ireplace incepe a inlocui inca de la primul element din lista. Daca intaiul este mai mare decat sfarsitul listei sau decat cuvatul sfarsit, atunci Ireplace se comporta ca sectionat. Daca exista mai putini args decat numarul de pozitii dintre prima si ultima, atunci pozitiile pentru care nu exista args sunt sterse.


A se observa codul exemplu si a se oferi o atentie accentuata modului in care grupuri de caractere sunt asezate in liste individuale de elemente.


Exemplu

set b [list a b }]
puts 'Treated as a list: $bn'

set b [split 'a b }']
puts 'Transformed by split: $bn'

set a [concat a b }]
puts 'Concated: $an'

lappend a       ;# Note: is a single element
puts 'After lappending: $an'

set b [linsert $a 3 '1 2 3']                          ;# '1 2 3' is a single element
puts 'After linsert at position 3: $bn'


set b [lreplace $b 3 5 'AA' 'BB']
puts 'After lreplacing 3 positions with 2 values at position 3: $bn'



Mai multe comenzi ale listei - lsearch, lsort, lrange


Listele pot fi cautate cu comande lsearch, sortate cu comanda lsort ,iar un sir de intrari in lista pot si extrase cu ajutorul comenzii lrange.

lsearch list pattern

Cauta in lista o intrare care ii corespunde lui pattern si returneaza indicele pentru prima potrivire sau a-1 daca nu exista corespondenta.

lsort list

Sorteaza lista si inapoiaza o noua lista in ordinea aranjata. Prin scadere aranjeaza lista in ordine alfabetica.

lrange list first last

Returneaza o lista compuse din primul pana la ultima intrare in lista. Daca primul este mai putin sau egal cu 0, el este tratat ca fiind primul element. Daca ultimul este sfarsit sau o valoare mai mare decat numarul de elemente din lista, el este tratat ca fiind sfarsitul. Daca primul este mai mare decat ultimul atunci o lista goala este inapoiata.

Prin scadere lsearch foloseste o metoda sferica de a gasi o corespondenta. Globbing este metoda de wildcard pe care majoritatea shell-urilor de Unix o folosesc.

globbing wildcards sunt:

Potriveste orice cantitate a oricarui element

Potriveste orice intamplare a oricarui caracter

X Backslash-ul trece cu vederea un caracter special la fel cum o face si in substitutiile tcl. Folosirea backslash-ul permite folosirea sferei pentru a potrivi un * sau ?.

Gaseste orice intamplare a oricarui element situat intre paranteze. Un rand de caractere pot fi potrivite folosind un sir dintre paranteze. De exemplu: [a-z] se va potrivi cu orice litera dintr-o grupa mai mica.

Exemplu


set list [list
]

set x [lsearch $list Washington*]
set y [lsearch $list Madison*]
incr x; incr y -1            ;# Set range to be not-inclusive

set subsetlist [lrange $list $x $y]

puts 'The following presidents served between Washington and Madison'
foreach item $subsetlist


set x [lsearch $list Madison*]

set srtlist [lsort $list]
set y [lsearch $srtlist Madison*]

puts 'n$x Presidents came before Madison chronologically'
puts '$y Presidents came before Madison alphabetically'



String Subcommands - length index range


O caracteristica a lui Tcl este ca si comenzile pot avea subcomenzi. String este un astfel de exemplu. Comanda string trateaza primul argument ca fiind o subcomanda. Lectia acopera aceste subcomenzi string:

string length string

Inapoiaza lungimea unui sir

string index string index

Returns the char at the index'th position in string

string range string first last

Inapoiaza un rand compus,de la primul pana la ultimul caracter

Exemplu

set string 'this is my test string'

puts 'There are [string length $string] characters in '$string''

puts '[string index $string 1] is the second character in '$string''

puts ''[string range $string 5 10]' are characters between the 5'th and 10'th'

String comparisons - compare match first last wordend


Exista 6 subcomenzi string care fac potrivire dintre modele si randuri.

string compare string1 string2

Compara string1 cu string2 si rezulta

-1 .. If string1 e mai mica decat string2

0 .. If string1 e egala cu string2

1 .. If string1 e mai mare ca string2

Aceste comparatii sunt facute lexicografic si nu numeric/

string first string1 string2

Inapoiaza index-ul elementului din string1 care incepe prima procedura cu string2 sau -1 daca nu exista potrivire cu string2 in string1

string last string1 string2

Inapoiaza index-ul elementului din string1 care incepe ultima procedura cu string2 sau -1 daca nu exista potrivire cu string2 in string1

string wordend string index

Inapoiaza index-ul unui caracter exact dupa ultimul din cuvant care contine elementul index al unui sir.Un cuvant este oricare set contiguu de litere, numere sau elemente subliniate sau oricare alt element unic.

string wordstart string index

Inapoiaza index-ul unui caracter exact dupa primul din cuvant care contine elementul index al unui sir.Un cuvant este oricare set contiguu de litere, numere sau elemente subliniate sau oricare alt element unic.

string match pattern string

Devine 1 daca pattern se potriveste cu string. Pattern este un model in stil sferic.

Globbing este technica wildcard folosita de shell.

globbing wildcards sunt:


Potriveste orice cantitate a oricarui element

Potriveste orice intamplare a oricarui caracter

X Backslash-ul trece cu vederea un caracter special la fel cum o face si in substitutiile tcl. Folosirea backslash-ul permite folosirea sferei pentru a potrivi un * sau ?.

Gaseste orice intamplare a oricarui element situat intre paranteze. Un rand de caractere poate fi potrivit folosind un sir dintre paranteze. De exemplu: [a-z] se va potrivi cu orice litera dintr-o grupa mai mica.

Exemplu

set fullpath '/usr/home/clif/TCL_STUFF/TclTutor/Lsn.17'
set relativepath 'CVS/Entries'
set directorypath '/usr/bin/'

set paths [list $fullpath $relativepath $directorypath]

foreach path $paths else

# If '/' is not the last character in $path, report the last word.
# else, remove the last '/', and find the next to last '/', and
#report the last word.

incr last
if else

# CVS is a directory created by the CVS source code control system.
#

if

# Compare to 'a' to determine whether the first char is upper or lower case
set comparison [string compare $name 'a']
if else


Modifying Strings - tolower, toupper, trim, format


Acestea sunt comenzile care modifica un rand. A se retine ca nici una dintre acestea nu modifica locul randului. In toate cazurile,un nou rand va rezulta.

tolower string

Rezulta un sir cu toate literele convertite de la partea de sus la cea de jos.

toupper string

Razulta un sir cu toate literele convertite de la partea de jos la cea de sus.

trim string ?trimChars?

Rezulta un sir cu toate intamplarile trimChars indepartate de la ambele capete. Prin scadere trimChars sunt spatii goale (spaces, tabs, newlines)

trimleft string ?trimChars?

Rezulta un sir cu toate intamplarile din trimChars mutate din stanga. Prin scadere trimChars sunt spatii goale (spaces, tabs, newlines)

trimright string ?trimChars?

Rezulta un sir cu toate intamplarile din trimChars mutate din dreapta. Prin scadere trimChars sunt spatii goale (spaces, tabs, newlines)

format formatString ?arg1 arg2 argN?

Rezulta un sir formatat in aceeasi maniera ca si procedura ANSI sprintf. FormatString este o descriere a formatarii de folosit. Definitia intreaga a acestuiu protocol este in pagina format man. Un subset folositor al definitiei este acela ca formatString este alcatuita din cuvinte de tipar, secvente de backslash si campuri% . Campurile % sunt siruri care incep cu % si se termina cu una dintre urmatoarele :

s Data este un sir

d Data este o integrala decimala

x Data este o integrala hexadecimala

o Data este o integrata octala

f Data este numar variabil

% poate fi urmat de

. Stanga justifica data din acest camp

Dreapta justifica data din acest camp

Valoarea de justificare poate fi urmata de un numar dand numarul minim de spatii de folosit pentru data

Exemplu

set upper 'THIS IS A STRING IN UPPER CASE LETTERS'
set lower 'this is a string in lower case letters'
set trailer 'This string has trailing dots .'
set leader '.This string has leading dots'
set both '((this string is nested in parens )))'

puts 'tolower converts this: $upper'
puts ' to this: [string tolower $upper]n'
puts 'toupper converts this: $lower'
puts ' to this: [string toupper $lower]n'
puts 'trimright converts this: $trailer'
puts ' to this: [string trimright $trailer .]n'
puts 'trimleft converts this: $leader'
puts 'to this: [string trimleft $leader .]n'
puts 'trim converts this: $both'
puts ' to this: [string trim $both '()']n'

set labels [format '%-20s %+10s ' 'Item' 'Cost']
set price1 [format '%-20s %10d Cents Each' 'Tomatoes' '30']
set price2 [format '%-20s %10d Cents Each' 'Peppers' '20']
set price3 [format '%-20s %10d Cents Each' 'Onions' '10']
set price4 [format '%-20s %10.2f per Lb.' 'Steak' '3.59997']

puts 'n Example of format:n'
puts '$labels'
puts '$price1'
puts '$price2'
puts '$price3'
puts '$price4'


Expresii regulate 101


Tcl mai suporta si operatiile cu siruri cunoscute ca regular expressions. Cateva comenzi pot accesa aceste metode prinntr-un argument -regexp, a se vedea paginile man pentru care comenzile sustin expresii reglate.

There are also two explicit commands for parsing regular expressions. De asemenea mai exista si doua comenzi clare pentru analizarea expresiilor aranjate.

regexp ?switches? exp string ?matchVar? ?subMatch1 subMatchN?

Cauta in sir expresia reglata exp. Daca este dat un parametru matchVar, atunci subsirul care se potriveste cu expresia reglata este copiat in matchVar. Daca exista variabile subMatchN, atunci partile parantetice ale sirului gasit care sunt copiate variabilelor subMatch, lucrand de la dreapta la.

regsub ?switches? exp string subSpec varName

Cauta in sir subsiruri care se potrivesc cu expresia reglata exp si o inlocuieste cu subpec. Sirul rezultat ste copia in varName.

Expresiile reglate pot fi exprimarte doar cu cateva reguli


se potriveste cu inceputul unui sir


se potriveste cu sfarsitul sirului


se potriveste cu orice element unic


se potriveste cu orice numarare (0-n) a elementului anterior


se potriveste cu orice numarare, but dar macar 1 din elementele anterioare


se potriveste oricarui caracter al unui set de caractere


Se potriveste cu orice element care nu este membru al setului de caractere ce ii urmeaza lui ^


Grupuri de seturi de elemente dintr-un subpec.

Expresiile reglate sunt similare cu globbing-ul care a fost prezentat in lectiile 16 si 18. Principala diferenta este modul in care seturile de caractere asemanatoare sunt In globbing singura modalitate de a selecta seturi de text necunoscut este simbolul *. Aceasta se potriveste cu orice cantitate a oricarui element.

In analizarea expresiilor regulate, simbolul * se potriveste cu 0 sau mai multe intamplari ale elementului precedand imendiat . Spre exemplu a se va potrivi cu a, aaaaa sau un sir gol. Daca elementul chiar dinaintea lui * este un set de elemente aflate intre paranteze drepte, atunci * se va potrivii cantitatii tuturor acestor elemenete. De exemplu, [a-} se va potrivi cu aa, abc, aabcabc sau iar, cu un sir gol.

The + symbol behaves roughly the same as the *, except that it requires at least one character to match. For example, [a-c]+ would match a, abc, or aabcabc, but not an empty string. Simbolul + se comporta sumar ca si *, exceptand faptul ca are nevoie de macar un element asemanator. De exemplu, [a-c] se va potrivi cu a, abc sau aabcabc, dar nu si cu un sir gol.

Analizarea expresiilor reglate este mult mai puternica decat globbing. Cu globbing poti folosi paranteze patrate pentru a inchide un set de elemente dintre care vor fi o potrivire. Analizarea expresiilor reglate include si o metoda de selectare a unui element ce nu se afla in set. Daca primul element dupa [ este simbolul (^), atunci analiza expresiei se va potrivi cu oricare element care nu se afla in setul de caractere dintr parantezele drepte. (^) poate fi inclus in setul de elemente care se potrivesc (sau nu) prin plasarea lui in oricare alta pozitie decat prima.

Comanda regexp este similara comenzii strig meci in faptul ca potriveste un exp de un sir. Este diferita pentru ca poate potrivi o portiune din sir in loc de tot sirul si va pozitiona caracterele gasite intr-o variabila matchVar.



Daca este gasita o asemanare portiunii expresieri reglate aflate intre paranteze, regexp va copia subsetul de caractere asemanatoare in argumentul subSpec. Asta poate fi folosita pentru a analiza siruri simple.

Regsub va copia unei noi variabile continutul sirului, substituind elementele care se potrivesc cu exp cu elementele  din subSpec. Daca subSpec contine un & sau 0, atunci acelste elemente vor fi inlocuite cu elementele care s-au potrivit cu exp. Daca numarul ce urmeaza unui backslash este 1-9, atunci secventa backslash va fi inlocuita cu o portiune convenabila a exp care este inchisa intre paranteze.

A se observa ca argumentul exp to regexp or regsub este procesat de pass-ul de substituire al Tcl. Asa ca destul de des expresia este pusa intre acolade pentru a preveni orice procesare speciala facuta de Tcl.

Exemplu

set sample 'Where there is a will, There is a way.'


# Match the first substring with lowercase letters only

set result [regexp $sample match]
puts 'Result: $result match: $match'


# Match the first two words, the first one allows uppercase
set result [regexp $sample match sub1 sub2 ]
puts 'Result: $result Match: $match 1: $sub1 2: $sub2'


# Replace a word

regsub 'way' $sample 'lawsuit' sample2
puts 'New: $sample2'


# Use the -all option to count the number of 'words'

puts 'Number of words: [regexp -all $sample]'



MAI MULTE EXEMPLE DE EXPRESII REGULATE


Expresiile regulate furnizeaza o metoda puternica in definirea modelului, dar ele sunt un pik neindemanatice la intelegere si in folosinta propiu-zisa. Asa ca haideti sa examinam cateva exemple in detalii.

Vom incepe inca cu un simplu exemplu non-trivial: gasimt floating-points intr-o linie a textului. Nu va faceti griji vom tine problema simpla decat este in plina generalitate.vom considera numere numai 1.0 si nu 1.00e + 01.

Cum vom studia expresiile noastre regulate in aceasta problema? Examinand exemple caracteristice cu stringuri care vrem sa se potriveasca:

Numere valide :

1.0, .02, +0., 1, +1, -0.0120

Numere invalide:

-, +., 0.0.1, 0..2, ++1

Numere discutabile:

+0000 and 0001

Le vom accepta - pentru ca ele sunt acceptate normal si pentru ca excluderea lor face modelul nostru sa fie mai complicat.

Un model incepe sa apara:

Un numar poate incepe cu un semn (+ sau -) sau cu numar. Acesta poate fi capturat cu o expresie [-+] ? , care se potriveste unic "-", si un unic "+" sau nimic.

Un numar poate poate avea zero si mai multe unitati in fata perioadei (.) si poate avea zero si alte unitati dupa perioada. Probabil [0-9]*.[0-9]* va face .

Un numar poate sa nu contina o perioada deloc. Revedeti expresia precedenta: [0-9]*.?[0-9]*

Expresia totala este:

[-+]?[0-9]*.?[0-9]*

In momentul acesta putem face trei lucruri:

1.           Vom incerca expresia cu          mai multe exemple precum cele de mai sus si sa vedem daca cea adecvata se potriveste si care nu.

2.           Incercam sa sa arate cat mai bine, inainte de testare. Ca exemplu clasa de caratere "[0-9]" este asa de cunoscuta incat are si o scurtatura "d". Deci, am putea so aranjam asa:

[-+]?d*.?d*

in loc. Sau am putea decide ca vrem sa capturam unitatile inainte sau dupa perioada pentru un proces mai special:

[-+]?([0-9])*.?([0-9]*)

3. Este o strategie buna in generalputem sa examinam modeulul cu mare atentie inainte de a il folosi.

Vedeti este o problema cu modelul de deasupra: toate partile sunt optionale, asta inseamna ca fiecare parte se poate potrivi cu un string nul - nici un semn , nici o unitate inainte de perioada, nici o perioada, nici o unitate dupa perioada. In alte cuvinte: Modelul nostru se potriveste cu un string gol!

Numere discutabile ca "+000" vor fi perfect acceptate si noi (in sila)le vom accepta. Dar mai surprinzator sunt stringurile "--1" si "A1B2" vor fi acceptate si ele. De ce? Pentru ca modelul incepe cu un string, si se poate potrivi cu substringurile "-1" si respectiv "1".

Trebuie sa reconsideram modelul nostru - este prea simplu si prea permitator:

Caracterul din fata minusului sau a plusului, daca sunt, numai poate fi inca o cifra, o perioada un minus sau un plus. Sa facem un spatiu un salt sau inceputul unui string: ^ | [ t ]: s-ar putea sa vi se para un pic ciudat dar ceea ce scrie acolo este: fiecare inceput de string ( ^ in afara parantezelor patrate ) sau ( bara verticala ) un spatiu sau un salt ( retineti: "t" reprezinta caracterul care face salt ).

Orice secventa a unei cifre inaintea perioadei ( in caz de este una ), este permis: [0-9]+.?

S-ar putea intampla ca sa fie zero cifre in fata perioadei, dar dupa aia va trebui sa aiba cel putin una dupa perioada: .[0-9]+

Si normal cifre in fata sau in spatele perioadei: [0-9]+ . [0-9]+

Caracterul dupa string ( in caz de este ) nu poate fi "." , "-" sau "+" pentru ca ne-ar baga intr-un numar neacceptabil $ | [ + - . ] ( Semnul dolarului semnifica sfarsitul stringului ).

Inainte de a scrie expresia regulata completa, sa vedem ce forme diferite avem:

Nu avem perioada: [-+]?[0-9]+

O perioada fara cifre inaintea ei: [-+]?.[0-9]+

Cifre inaintea perioadei, si posibil dupa: [-+]?[0-9]+.[0-9]*

Si acum sinteza:

(^|[ t])([-+]?([0-9]+|.[0-9]+|[0-9]+.[0-9]*))($|[^+-.])

sau

(^|[ t])([-+]?(d+|.d+|d+.d*))($|[^+-.])

Este nevoie de paranteze pentru a putea deosebi alternativele introduse de bara verticala si capturarea unui substring pe care il vrem sa-l avem. Fiecare set de paranteze defineste de asemenea un substring si acesta poate fi pus intr-o variabila separata.

regexp $line whole char_before number nosign char_after


# Or simply only the recognised number (x's as placeholders, the
# last can be left out

regexp $line x x number

Nota: pentru a identifica un substring, numarati parantezele deschise de la stanga la dreapta.

Daca il punem la un test:

set pattern
set examples
foreach e $examples else


rezultatul este:

>>1.0<<: 1.0 (1.0)
>> .02<<: .02 ( .02)
>> +0.<<: +0. ( +0.)
>>1<<: 1 (1)
>>+1<<: +1 (+1)
>> -0.0120<<: -0.0120 ( -0.0120)
>>+0000<<: +0000 (+0000)
>> - <<: Does not contain a valid number
>>+.<<: Does not contain a valid number
>>0001<<: 0001 (0001)
>>0..2<<: Does not contain a valid number
>>++1<<: Does not contain a valid number
>>A1.0B<<: Does not contain a valid number
>>A1<<: Does not contain a valid number

Deci modelul nostru accepta corect stringurile menite pentru a fi recunoscute ca numere si ca respengerea altora.

Hai sa ne intoarcem la alte modele acum:

Textul cuprins intr-un string: Acesta este un "text citat". Daca stim ingradirea caracterului in avantaj (ghilimele , " in acest caz), apoi " ( [ ^ " ] ) * " va cuprinde textul in interiorul ghilimelelor.

Sa presupunem ca nu stim ingradirea unui character ( poate fi " sau ' ). Apoi:

regexp $string enclosed_string

il va face: - acest 1 este asa-numit raport-sprijin la primul substring capturat.

Puteti sa folositi tehnica asta pentru a vedea daca un cuvant se aplica de doua ori in aceiasi linie:

set string 'Again and again and again '
if $string => word] }

( Modelul y se potriveste la inceputul sau sfarsitul unui cuvant si w+ indica ca vrem cel putin un caracter ).

Sa presupunem ca trebuie sa verificam parantezele cu expresii matematicale: (1+a)/(1-b*x) de exemplu. O simgura verificare numara toate parantezele deschise sau inchise.

#
# Use the return value of [regexp] to count the number of
# parentheses

if $string] != [regexp -all $string] }

Bineinteles, aceasta este doar o verificare ordinara. Una mai buna este sa vedem daca               la fiecare punct cat timp scaneaza stringul acolo sunt mai multe paranteze inchise decat paranteze deschise. Putem foarte simplu sa extragem parantezele si sa le punem intr-o lista ( optiunea inline face asta ).

set parens [regexp -inline -all $string]
set balance 0
set change('(') 1;# This technique saves an if-block :)
set change(')') -1
foreach p $parens

Final: expresiile regulate sunt foarte puternice, dare le au o anumita limita teoretica. Una din aceste limite este aceea ca ele nu sunt potrivite pentru analiza arbitrara nested text.


More Quoting Hell - Regular Expressions 102


regexp ?switches? exp string ?matchVar? ?subMatch1 subMatchN?

Cauta stringul pt expresia regulata exp.Daca este dat un parametru <matchVar>, atunci substringul care se portriveste expresiei regulate,este copiata in <matchVar>. Daca exista variabile <subMatchN> ,atunci partile din paranteze ale stringului pereche sunt copiate in variabilele <subMatch> lucrand de la stanga la dreapta.

regsub ?switches? exp string subSpec varName


Cauta string pt substringul care se potriveste expresiei regulate exp si le inlocuieste cu subSpec.Stringul rezultat este copiat in varName.

Expresia regulata (exp) din a doua expresie analizand comenzile este evaluata de analizatorul Tcl in timpul fazei de substitutie Tcl. Acest lucru poate furniza multa putere dar in acelasi timp necesita o mare atentie.

Aceste exemple dezvaluie unele din cele mai inselatoare aspecte ale evaluarii expresiei regulate.Domeniile din fiecare exemplu sunt discutate in detaliu amanuntit si la cel mai complicat nivel.

Punctele de care trebuie tinut cont in timp ce citesti exemplele sunt :

* Paranteza patrata deschisa ( [ ) are rol in faza de substitutie si in analizarea expresiei regulate.

* O pereche de paranteze , semnul plus si stelutza au rol in analizarea expresiei regulate dar nu si in faza de substitutie Tcl.

* Secventa backslash (n,t, etc) are rol in faza de substitutie Tcl ,dar nu si in analizarea expresiei regulate.

* Caracterul backslash ([) nu are nici  o semnificatie atat pentru faza de substitutie Tcl cat si pt analiza expresiei regulate.

Faza in care un caracter are influente semnificative,multe pauze sunt necesare pt a potrivi caracterul dorit. O  pauza ar putea ori inchide expresia in acolade, ori ar putea pune un backslash inaintea caracterului eliminat.

Pentru a trece paranteza stanga in analizarea expresiei regulate pt a fi evaluata la rangul de caracter necesita 1 pauza. Pentru ca analiza unei expresii regulate sa se potriveasca literal in stanga parantezei trebuie doua pauze(una in faza de substitutie Tcl si una in analiza expresiei regulate). Daca stringul este plasat intre ghilimele atunci un backslash pasat analizei regulate trebuie deasemenea eliminat cu un backslash.

Exemplu



# Examine an overview of UNIX/Linux disks

set list1 [list





foreach line $list1 $line match size mounted;
puts '$mounted is $size blocks'



# Extracting a hexadecimal value

set line
regexp '[^t]+t[[0-9]+(0x([0-9a-fA-F]+))]' $line match hexval
puts 'Hex Default is: 0x$hexval'


# Matching the special characters as if they were ordinary

set str2 'abc^def'
regexp '[^a-f]*def' $str2 match
puts 'using [^a-f] the match is: $match'

regexp '[a-f^]*def' $str2 match
puts 'using [a-f^] the match is: $match'

regsub $str2 ' is followed by: ' str3
puts '$str2 with the ^ substituted is: '$str3''

regsub '([a-f]+)^([a-f]+)' $str2 '2 follows 1' str3
puts '$str2 is converted to '$str3''


Associative arrays

Limbaje precum C,BASIC,FORTRAIN si Java sustin arrays in care valoarea indexului este o integer.Tcl,precum majoritatea limbajelor de scripiting (Perl ,Python,PHP,etc)sustin arrays asociabile (cunoscute si ca 'hash tables')

in care valoarea indexului este un string.

Sintaxa pt arrays asociabile este punerea indexului intre paranteze.

set name(first) 'Mary'
set name(last) 'Poppins'

puts 'Full name: $name(first) $name(last)'

Exista cateva comenzi array prin simpla accesare si creare de arrays care vor fi discutate in lectia aceasta si urmatoarea.

array exists arrayName Returneaza 1 daca arrayName este o  variabila array.Returneaza 0 daca arrayName este o variabila scalara,procedura,ori nu exista.

array names arrayName?pattern. Returneaza o lista de indici pentru array asociative arrayName. Daca pattern este furnizat atunci doar acei indici care se potrivesc pattern sunt returnate. Perechea este facuta folosind tehnica globala a perechii stringului.

array size arrayName. Returneaza numarul de elemente din arrayName.

array get arrayName. Returneaza o lista in care fiecare element ciudat/in plus este un index in arrayul asociat.Lista de elemente, urmarind un nume/o mentionare ,este valoarea acelui membru array.

array set arrayName datalist. Transforma o lista intr-un array asociativ. DataList este o lista in formatul a ceea ce returneaza array get.Fiecare element ciudat/in plus este un index pentru arrayul asociat, iar lista de elemente, ce urmeaza asta,este valoarea acelui membru array.

Cand un nume array asociativ este dat ca un argument pt comanda globala,toate elementele acelui array asociativ devin disponibile acelei proceduri.Din acest motiv, Brent Welch recomanda (in programarea reala Tcl si Tk) folosirea unui array asociativ pentru o categorie,structurat intr-un pachet.

Alta folosire obisnuita pt arrays este stocarea datelor in tabel.In exemplul de mai jos folosim un array pt simpla stocare a unei baze de date cu nume.

Exemplu

proc addname


# Initialise the array and add a few names

global name
set name(ID) 0

addname Mary Poppins
addname Uriah Heep
addname Rene Descartes
addname Leonardo 'da Vinci'


# Check the contents of our database
# The parray command is a quick way to
# print it

parray name


# Some array commands

array set array1 [list


]

puts 'Array1 has [array size array1] entriesn'

puts 'Array1 has the following entries: n [array names array1] n'

puts 'ID Number 123 belongs to $array1(123)n'

if else

if else


More Array Commands - Iterating and use in procedures


Deseori vezi vrea sa buclati prin continutul unu asociativ array - fara a specifica elementele explicite. Pentru aceste array names si array get comenzile sunt foarte utile. Cu amandoua poti da un (glob-style) model pentru a selecta ce elemente ai nevoie:

foreach name [array names mydata]


# Get names and values directly

foreach [array get mydata]

Nota, oricum, elementele nu vor fi returnate intr-o oridine previzibila: aceasta are de a face cu sublinierea "Hash table". Daca vrei o orine particulara (alfabetica de exemplu) poti folosi acest cod:

foreach name [lsort [array names mydata]]

Cat timp array-urile sunt bune pentru facilitatea inmagazinata pentru cateva scopuri, ele sunt un pic inselatoare cand vrei sa treci cu ele la o procedura: ele sunt defapt colectii ale variabilelor. Aceasta nu va merge:

proc print12

set array(1) 'A'
set array(2) 'B'

print12 $array

Motivul este simplu: un array nu are valoare. In schimb codul de mai sus ar trebui sa fie:

proc print12

set array(1) 'A'
set array(2) 'B'

print12 array

Deci, in loc sa trecem o "valoare" pentru un array, vei trece name. Aceasta primeste numele (via comanda upvar ) la o variabila locala (care se poarta ca un array original). Poti face schimbi in array-ul original in aceasta forma.

Exemplu


# The example of the previous lesson revisited - to get a
# more general 'database'


proc addname

proc report $n id


# Store in a temporary array:
# an 'inverse' map of last name to ID)

set last $name($n)
set tmp($last) $id



# Now we can easily print the names in the order we want!

foreach last [lsort [array names tmp]]



# Initialise the array and add a few names

set fictional_name(ID) 0
set historical_name(ID) 0

addname fictional_name Mary Poppins
addname fictional_name Uriah Heep
addname fictional_name Frodo Baggins

addname historical_name Rene Descartes
addname historical_name Richard Lionheart
addname historical_name Leonardo 'da Vinci'
addname historical_name Charles Baudelaire
addname historical_name Julius Caesar


# Some simple reporting

puts 'Fictional characters:'
report fictional_name
puts 'Historical characters:'
report historical_name

File access 101

Tcl furnizeaza cateva metode de citie si scriere aflate pe disk. Cea mai simpla metoda de a accesa un fisier este via gets si puts. Cand sunt multe date de citit, oricum, cateodata este mai eficient sa folositi comanda read pentru a incarca intregul fisier, si pentru a aniliza fisierul pe linii folositi comanda split.

Aceste metode pot fi folosite si in comunicarea peste sockets sau peste pipes. Este chiar posibil , via asa-zise-i virtual file system pentru a folosi fisiere stocate in memorie decat cele de pe disk. Tcl furnizeaza o interfata uniforma la aceste resurse diferite, deci in general nu trebuie sa te ingrijorezi cu detalii.

open fileName ?access? ?permission?

Deschide un fisier si returneaza un indiciu ca sa fie folosit cand este acceseaza un fisier via gets, puts, close, etc.

FileName este numele fisierului care trebuie deschis.

access este modul de acces al fisierului.

o         rDeschide fisierul pentru citire. Fisierul trebuie sa existe.

o         r+.Deschide fisierul pentru citire si scriere. Fisierul trebuie sa existe.

o         wDeschide fisierul pentru scriere. Creati fisierul daca nu exista, sau setati lungimea la zero in caz de nu exista.

o         w+.Deschide fisierul pentru scriere si citire. Creati fisierul daca nu exista, sau setati lungimea la zero in caz de nu exista.

o         a..Deschide fisierul pentru scriere. Fisierul trebuie sa existe. Setati locatia curenta la sfarsitul fisierului.

o         a+Deschide fisierul pentru scriere. Daca fisierul nu exista creati-l. Setati locatia curenta la sfarsitul fisierului.

permission este un interger folosit sa seteze pemisiunea la fiserul acces. Lispa rw-rw-rw- (0666). Puteti sa-l folositi in setarea unui fisier al proprietarului, grupul el/ea apartine tuturor celorlati useri. Pentru mai multe aplicatii absenata este buna.


Modularization - source

Comanda source va incarca un fisier si il va executa. Asta perimte unui program sa fie impartit in mai multe fisiere cu fiecare procedura de clarificare a fisierelor si variabile pentru o anumita arie de functionalitate. Spre exemplu, se poate avea un fisier numit database.tcl care sa se contina toate procedurile pentru a avea de aface cu o baza de date sau cu un fisier numit gui.tcl care se ocupa cu creearea unei interfate grafice a userului cu tk. Scriptul principal poate pur si simplu sa includa fiecare fisier folosind comanda source. Tehnici mult mai puternice pentru modularizarea programului sunt aduse in discutie in urmatoarea lectie despre pachete.

Comanda poate fi folosita ca sa:

Separe un program in fisiere multiple.

Sa creeze un fisier care sa contina tooate procs-urile pentru un anumit set de functii.

Sa configureze programe.

Sa incarce fisiere data.

source fileName

Citeste scriptul din filename si il executa. Daca scriptul executa cu succes, source inapoiaza valoarea ultimulei expuneri din script.

Daca exista vreo greseala in script, source va arata acea eroare.

Daca exista o intoarcere (in afara de aceea din definitia proc) atunci source se va intoarce imediat, fara sa execute restul scriptului.

Daca filename incepe cu o tilda (~) atunci $env(HOME) va fi substitut pentru acea tilda ca si in comanda file.

Exemplu

sourcedata.tcl:

# Example data file to be sourced
set scr [info script]
proc testproc
set abc 1
return
set aaaa 1

sourcemain.tcl:

set filename 'sourcedata.tcl'
puts 'Global variables visible before sourcing $filename:'
puts '[lsort [info globals]]n'

if

puts 'nNow executing testproc'
testproc

puts 'Global variables visible after sourcing $filename:'
puts '[lsort [info globals]]n'

AICI TREBUIE 31.

Creating Commands - eval

O diferenta dintre Tcl si majoritatea adunatorilor este ca Tcl va da voie unui program executant sa creeze noi comenzi si le execute in timpul rularii.

O comanda tcl este definita ca fiind o lista de siruri in care primul sir este o comanda sau un proc. Orice sir sau lista care indeplineste acest criteriu poate sa fie evaluat si executat.

Comanda eval va evalua o lista de siruri ca si cand ar fi comenzi scrise la prompt-ul % sau cu sursa intr-un fisier. In mod normal comanda eval va rezulta valoarea finala a comenzii aflata in evaluare. Daca, comenzile de evaluat dau o eroare (de exemplu, daca exista o eroare de sintaxa intr-unul din siruri), atunci eval va da o eroare.

A se nota ca oricare: concat sau list pot fi folosite la creearea sirului de comanda,dar aceste doua comenzi vor creea siruri de comanda putin mai diferite.

eval arg1 ??arg2?? ??argn??

Evalueaza arg1 - argn ca una sau mai multe comenzi Tcl. The args sunt inlantuite intr-un sir si trecute la tcl_Eval pentru evaluare si executie.

Eval returneaza rezultatul (sau codul de eroare) evaluarii.

Exemplu



set cmd
puts 'CMD IS: $cmd'
eval $cmd



if {
puts 'nDefining newProcA for this invocation'
set num 0;
set cmd 'proc newProcA '
set cmd [concat $cmd ' ']
eval $cmd


puts 'nThe body of newProcA is: n[info body newProcA]n'

puts 'newProcA returns: [newProcA]'
puts 'newProcA returns: [newProcA]'


# Defind a proc using lists


if {
puts 'nDefining newProcB for this invocation'
set cmd 'proc newProcB '
lappend cmd
lappend cmd

eval $cmd


puts 'nThe body of newProcB is: n[info body newProcB]n'
puts 'newProcB returns: [newProcB]'



More command construction - format, list


Ar putea exista cateva rezultate neasteptate cand se incearca o creeare a sirurilor de comanda pentru eval

De exemplu:

eval puts OK

va printa sirul OK. totusi,


eval puts Not OK

va genera o eroare.

Motivul pentru care a doua comanda genereaza o eroare este acela ca eval foloseste concat pentru a-si imbina argumentele intr-un sir de comanda. Aceasta cauzeaza ca cele doua cuvinte NOT OK sa fie tratate ca doua argumente la puts. Daca exista mai mult de un argument la puts, primul argument trebuie sa fie un indicator de fisiere.

Moduri corecte de a scrie a doua comanda sunt acestea:


eval [list puts ]

eval [list puts 'Not OK']

set cmd 'puts' ; lappend cmd ; eval $cmd

Atata timp cat se inregistreaza cum sunt grupate argumentele prezentate lui eval, se pot cauza multe metode de formare a sirurilor pentru eval, incluzand comanda string si fornat.

Metodele recomandate de a construi comenzi pentru eval sunt de a folosi comenzile list si lappend. Aceste comenzi devin dificil de folosit daca trebuie folosite paranteze drepte in comanda, asa cum a fost facut in lectia anterioara.

Exemplul de la lectia anterioara este re-implementat in codul exemplu, folosind lappend.

Intregimea unei comenzi poate fi verificata cu info complete. Info complete poate fi folosit si intr-un program interactiv care sa determine daca linia tastata este o comanda completa sau doar introdusa de user pentru a forma comanda mai bine.



info complete string

Daca string nu are paranteze asemanatoare,acolade sau paranteze drepte atunci valoarea lui 1 este returnata,altfel rezulta 0.



Exemplu


set cmd 'OK'
eval puts $cmd


set cmd 'puts' ; lappend cmd ; eval $cmd




set cmd 'NOT OK'
eval puts $cmd

eval [format puts 'Even This Works']

set cmd 'And even this can be made to work'

eval [format puts $cmd ]

set tmpFileNum 0;



set cmd
lappend cmd ''
lappend cmd 'global num; incr num; return '/tmp/TMP.[pid].$num''
eval $cmd

puts 'nThis is the body of the proc definition:'
puts '[info body tempFileName]n'



set cmd

if else
puts 'a and b with one pass of substitution: $a $$b'
puts 'a and b with subst in braces: [subst ]'
puts 'a and b with subst in quotes: [subst '$a $$b']n'

puts 'format with no subst [format $b]'
puts 'format with subst: [subst [format $b]]'
eval 'puts 'eval after format: [format $b]''

set num 0;
set cmd 'proc tempFileName '
set cmd [format '%s $cmd [pid] ]
set cmd [format '%s }' $cmd ]
eval $cmd

puts '[info body tempFileName]'

set a arrayname
set b index
set c newvalue
eval [format 'set %s(%s) %s' $a $b $c]

puts 'Index: $b of $a was set to: $arrayname(index)'


Changing Working Directory - cd, pwd



Tcl sustine si comenzi care schimba si arata directorul in care se lucreaza in acel moment.

Acestea sunt:

cd ?dirName?

. Schimba directorul curent in dirName (daca dirName este dat sau directorului $HOME daca dirName nu este dat). Daca dirname este o tilda (~, cd schimba directorul de lucru cu directorul home al userilor. Daca dirname incepe cu o tilda, atunci restul elementelor sunt tratate ca un id de logat si cd schimba directorul in care se lucreaza cu $HOME al userului.

pwd

Reface directorul curent.

Example

set dirs [list TEMPDIR]


puts '[format '%-15s %-20s ' 'FILE' 'DIRECTORY']'

foreach dir $dirs
set c_files [glob -nocomplain c*]

foreach name $c_files

More Debugging - trace



Cand se deviruseaza un program. Este cateodata util sa se stie cand o variabila se schimba. Interpretul Tcl sustine o metoda pentru a urmari cand si cum o variabila este accesata. Cu comanda trace o porcedura poate fi definita pentru fi executata oricand este citita,scrisa nesetata o variabila.Cu aceasta comanda se poate determina proc-ul modificarea unei variabile, in ce a fost schimbata valoarea si ce variabile au fost in timpul ala.

Comanda trace executa la acelasi nivel al grupului asa cum o face si accesul variabilei. Proc-ul invocat de trace se afla cu un nivel mai jos. Altfel cu comanda uplevel o procedura chemata prin trace poate raporta conditiile puse cand a fost accesata o variabila.

trace variable variableName operation procname

Plaseaza o investigatie asupra variabilei lui variableName. Cand o variablename este accesata pentru operatiunea specificata in operatia argument, procedura procname va fi adusa in discutie.

Operatiunea este una de :

r Citit

w . Scris

u Nesetat

O variabila poate fi nesetata ori explicit cu comanda unset ori implicit cand o procedura se intoarce si taoite variabilele locale sunt eliberate.

Cand este accesat variableName, procname va fi numit cu trei argumente: variableName, elementName si operation. Daca variabila accesata este aranjata asociativ atunc elementName va contine numele elementului accesat. Daca variableName este o simpla variabila, atunci elementName va fi un sir gol. Operation este operatia care a fost facuta pe variablename ca sa fie invocata actiunea trace.

trace vdelete variableName operation procname

Anuleaza actiunea de gasire pentru operarea pe variableName.

trace vinfo variableName

Reface informatia despre urmele aplicate lui variableName.

Exemplu


proc traceproc else

if else


proc testProc

trace variable i1 w traceproc
trace variable i2 r traceproc
trace variable i2 w traceproc

set i2 'testvalue'

puts 'ncall testProc'
testProc i1 i2

puts 'nTraces on i1: [trace vinfo i1]'
puts 'Traces on i2: [trace vinfo i2]n'

trace vdelete i2 r traceproc
puts 'Traces on i2 after vdelete: [trace vinfo i2]'

puts 'ncall testProc again'
testProc i1 i2



Command line arguments and environment strings

Scripturile sunt mult mai utile daca pot fi denumite cu valori diferite in linia de comanda.

De exemplu, un script care extrage o valoare speciala dintr-un dosar poate fi scris astfel incat sa caute, sa citeasca numele documentului si sa extraga datele. Sau poate fi scris ca sa treaca printre atatea fisiere cate sunt in linia de comanda si sa extraga datele din fiecare si sa printeze data si numele fisierului.

A doua metoda de a scrie programul poate fi foarte usor folosita de la alte scripturi. Asta face totul mai util.

Numarul argumentelor comenzilor de sir ale unui script Tcl este trecut ca fiind variabila globala argc. Numele unui script Tcl este dat scriptului ca variabila globala argv0 si restul argumentelor comenzilor de sir sunt trecute ca o lista in argv.

Alta metoda de a trece informatiile printr-un script este cu ajutorul variabilelor de imprejurimi. De exemplu, a se presupune scrierea unui program in care userul prevede un fel de comentariu pentru a fi inregistrat. Ar fi bine sa se permita userului sa editeze comentraiile lor in editorul preferat. Daca userul a specificat un editor variabil la imprejurimi, atunci se poate invoca editorul pe care il pot folosi.

Sub supusele sisteme de operare Posix, variabilele de imprejurari sunt trecute intr-un script Tcl intr-o ordine env global asociativa. Indicele din env este numele variabilei imprejurimilor. Comanda puts '$env(PATH)' va printa continutul variabilei de imprejurimi PATH.


Example

puts 'There are $argc arguments to this script'
puts 'The name of this script is $argv0'
if

puts 'You have these environment variables set:'
foreach index [array names env]


Leftovers - time, unset


Cea mai simpla metoda de a face un script sa mearga mai repede este de a cumpara un procesor mai rapind. Din pacate. Asta nu este intotdeauna o optiune. Poate sa fie necesara optimizarea scriptului pentru a merge mai repede. Asta este dificil daca nu se poate masura timpul cat dureaza sa ruleze portiunea scriptului care se doreste optimizat.

Comanda time este solutia la aceasta problema. Time va masura cat dureaza executarea unui script. Apoi se poate modifica scriptul, reporni si observa cat a fost imbunatatit.

Mai poate fi necesar sa se optimizeze memoria folosita de script sau sa se curete variabile dupa fiecare trecere printr-un loop. Comanda unset va sterge o variabila din locul unde trebuie sa fie numele interpretului.

Dupa ce a fost rulat exemplul, jucati-va cu marimea contrapartidelor rutei in timetst1 si timetst2. Daca contrapartida interioara este 5 sau mai putin, poate dura mai mult executarea lui timetst2 decat a lui timest1. Asta pentru ca ia mai mult timp sa se calculeze si sa se repartizeze variabila k si daca loop-ul interior este prea mic, atunci castigul in a nu face inmultirea in interiorul loop-ului este pierduta in timpul care ia sa se calculeze loop-ul extern.

time script ?count?

Rezulta cate milisecunde a durat sa execute scriptul. Daca count este specificat, atunci va porni script count times si va rezulta media. Timpul este timpul trecut,nu timpul CPU.

unset variableName1 ?variableName2 ?

Sterge variableName din spatiul numelui interpretului. daca variableName este un nume aranjat, atunci intregul aranjament va fi sters. Daca variableName este un element dintrun aranjament, atunci numai acelasi element va fi sters. If any of the variables to delete do not exist, then unset will return an error, and any variables after the non-existent variable will not be deleted.

Exemplu

proc timetst1

proc timetst2

# Make a long list and a large array.

for

puts 'Time for list search: [ time 10]'
puts 'Time for array index: [ time 10]'

proc existence else


set x 1
set y 2
for

puts 'ntesting unsetting a simple variable'
;# Confirm that x exists.
existence x
;# Unset x
puts 'x has been unset'
unset x
;# Confirm that x no longer exists.
existence x

puts 'ntesting unsetting a member of an array'
existence a(0);
puts 'a0 has been unset'
unset a(0);
existence a(0);


puts 'ntesting unsetting several members of an array, with an error'
existence a(3);
existence a(4);
catch
puts 'nAfter attempting to delete a(3), a(0) and a(4)'
existence a(3);
existence a(4);

puts 'ntesting unsetting an array'
existence a;
puts 'a has been unset'
unset a;
existence a;


Channel I/O: socket, fileevent, vwait



Tcl I/O se bazeaza pe un canal. Un canal este conceptual asemanator lui FILE * in C sau un val in programarea unui shell. Diferenta este ca un canal poate fi ori un mijloc de curent ca un document, un tape drive sau tty sau o conexiune orientata construita ca un port.

Un canal baza pe un sir este format prin comanda open,asa cum a fost discutat si in lectia 26. Un canal bazat pe porturi este format printr-o comanda socket. Un port poate fi deschis fie ca un client TCO sau ca un server.

Daca un canal este deschis ca un server, atunci programul tcl va "urmari" pe acelasi canal o alta sarcina in incercarea de a se conecta cu ea. Cand asta se intampla, un nou canal este creeat pentru linku-ul acela (server-> new client) si programul tcl continua sa urmareasca legaturi pe numarul original al portului. In acest mod, un server unic Tcl ar putea interactiona cu mai multi cilenti.

Cand exista un canal,un handler poate fi definitivat cand va fi invocat atunci cand canalul este liber pentru citit sau scris. Acest handler este definit cu ajutorul comenzii fileevent. Cand o procedura tcl indeplineste gets sau puts unui procedeu de bloca si procedeul nu este pregatit pentru I/O, programul va fi blocat pana este gata planul. Ar putea dura mult pana cand celalalt sfarsit al canalului I/O trece offline. Folosind comanda fileevent, programul poate accesa numai canalul I/O cand este gata sa mute date.

In sfarsit, exista o comanda ca sa astepte pana se intampla un eveniment. Comanda vwair va astepta pana este setata o variabila. Aceasta poate fi folosita pentru a crea un stil functional semnalant pentru interactiunea dintre client si server si sa anunte procedura dominanta ca a avut loc un eveniment.

A se observa exemplul:comanda socket este folosita ca si client si server si comenzile fileevent si vwait folosite de catre client si server pentru a controlaI/O dintre client si server.

A se nota ca in particular comenzile flush sunt folosite. Ca si un canal care este deschis ca un conductor la comanda nu se trimit date decat atunci cand un flush este invocat sau este umplut un amortizor, canalele bazate pe porturi nu trimit automat date.

socket -server command ?options? port

Comanda socket impreuna cu -server flah deschid o conexiune pe server sau un port. Cand o conexiune se intampla la port, comanda proc este chemata cu argumente:

channel . . . .Canalul pentru clientul nou

address . . . . Adresa de IP a acestiu client

port. . . . . . . . Portul dat clientului

socket ?options? host port

Comanda socket fara optiunea -server deschide o conexiune clinet sistemului cu adresa de IP host si cu adresa portului port. Adresa Ip-ului poate fi data ca un sir numeric sau ca o adresa calificata de domeniu.

Pentru conectarea la host trebuie folosita adresa 127.0.0.1 (adresa loopback).

fileevent channelId readable ?script?

fileevent channelId writeable ?script?

comanda fileevent defineste o invocare a unui handler atunci cand are loc un eveniment care invoca scriptul cand o data este pregatita a fi citita pe un channelId si writeable cand channelID este pregatit sa primeasca date.

vwait varName

Comanda vwait opreste executia scriptului pana cand actiunea de fundal seteaza valoarea lui vartName.O actiun de fundal poate fi un proc invocat printr-o fileevent sau o conexiune priza sau un eveniment de la un widget tk.

Exemplu



proc serverOpen

proc readLine {
fileevent $channel readable
after idle 'close $channel;set out 1'
} else


set connected 0;
# catch server
set server [socket -server serverOpen 33000]

after 100 update;

set sock [socket -async 127.0.0.1 33000]
vwait connected

puts $sock 'A Test Line'
flush $sock
vwait didRead
set len [gets $sock line]
puts 'Return line: $len -- $line'

catch
vwait out
close $server

Time and Date - clock

Comanda clock prevede acces functiilor datelor si timpului in Tcl. In functie de subcomenzile invocate poate sa procure ora curenta sau sa se converteasca intre diferite reprezentari de timp si data.

Comanda clock este o metoda platforma independenta de a procura expunerea functionalitatii comenzii unix date si de a procura acces valorilor rezulate de o accesare gettime unix

clock seconds

Comanda clock seconds da timpul in secunde de cand a inceput epoca. Data epocii variaza pentru diferitele sisteme de operare astfel incat valoarea este importanta pentru scopuri de comparare sau ca input pentru comanda clock format.

clock format clockValue ?-gmt boolean? ?-format string?

Subcomanda format formeaza clockvalue(asa cum este rezultat de clock clicks intr-un sir uman lizibi)l.

Ca un argument secund, intrerupatorul -gmt foloseste boolean. Daca boolean este 1 sau Adevarat, atunci timpul va fi format dupa Greenwich Mean Time, in alt caz va fi format ca timp local.

Optiunea -format controleaza in ce format va fi rezultatul.Continutul unui argument string la format are continutul asemanator ca si expunerea format(asa cum a fost discutat in lectiile 19,33.34).In plus mai exista mai multi descriptori % care pot fi utilizati pentru a descrie output-ul.

Acestea includ:

%a . . . . Numele abreviat al unei zile(Mon, Tue, etc.)

%A . . . . Numele complet al unei zile (Monday, Tuesday, etc.)

%b . . . . Numele abreviat al lunii (Jan, Feb, etc.)

%B . . . . Numele complet al lunii (January, February, etc.)

%d. . . . . O zi a lunii

%j . . . . . Julian day of year

%m . . . . Numarul lunii (01-12)

%y. . . . . Anul din secol

%Y . . . . An cu 4 cifre

%H . . . . Ora (00-23)

%I . . . . . Ora (00-12)

%M . . . . Minute (00-59)

%S . . . . . Secunde(00-59)

%p . . . . . PM sau AM

%D . . . . Data ca %m/%d/%y

%r. . . . . Ora ca %I:%M:%S %p

%R . . . . Time as %I:%M

%T . . . . Time as %I:%M:%S

%Z . . . . Time Zone Name

clock scan dateString

Subcomanda scan schimba un sir uman lizibil intr-o valoare al ceasului de sistem si ar fi returnat de clock seconds.

Argumentul dateString contine siruri in aceste forme:

time

O perioada de zi intr-unul din formatele de mai jos. Meridian poate fi AM sau PM sau o varianta de capitulare. Daca nu este specificat atunci ora (hh)este interpretata ca un ceas de 24 de ore. Zona poate fi o descriere e trei litere a unei zone de timp,EST,PDT, etc.

hh:mm:ss ?meridian? ?zone?

hhmm ?meridian? ?zone?

date

O data apare ca in in exemplele de mai jos.

mm/dd/yy

mm/dd

monthname dd, yy

monthname dd

dd monthname yy

dd monthname

day, dd monthname yy

Exemplu


set systemTime [clock seconds]


puts 'The time is: [clock format $systemTime -format %H:%M:%S]'


puts 'The date is: [clock format $systemTime -format %D]'


puts [clock format $systemTime -format ]


puts 'n the default format for the time is: [clock format $systemTime]n'





set halBirthBook 'Jan 12, 1997'
set halBirthMovie 'Jan 12, 1992'
set bookSeconds [clock scan $halBirthBook]
set movieSeconds [clock scan $halBirthMovie]

puts 'The book and movie versions of '2001, A Space Oddysey' had a'
puts 'discrepency of [expr $bookSeconds - $movieSeconds] seconds in how'
puts 'soon we would have sentient computers like the HAL 9000'

More channel I/O - fblocked & fconfigure

Lectiile anterioare au aratat cum se utilizeaza canale cu documente si blocari de prize. Tcl mai sustine si citiri si scrieri care antiblocare si permite coinfigurarea marimilor amortizoarelor I/O si cum sunt terminate sirurile.

O citire sau o scriere anti-blocare inseamna ca in loc de o chemare gets in asteptare pana cand data este valabila se va intoarce imediat. Daca ar fi informatii valabile,vor fi citite,daca nici o data nu este valabila chemarea gets va rezulta o lungime 0.

Daca exista canale care trebuie verificate pentru input, se poate folosi comanda fileevent pentru a impiedica citiri pe canal si apoi sa se utilizeze comanda fblocked pentru a determina cand sunt citite toate informatiile.

Comenzile fblocked si configure dau mai control asupa comportamentului unui canal.

Comanda fblocked verifica daca un canal a rezultat toate input-urile valabile. Este util atunci cand se lucreaza cu un canal care a fost setat la un mod de non-blocare si este nevoie sa se determine daca exista informatii valabile sau daca un canal a fost inchis din partea cealalta.

Comanda fconfigure are multe optiuni care permit sa se chestioneze sau sa se acorde comportamentul unui canal, incluzand si daca acesta blocheaza sau nu,marimea amortizorului si sfarsitul elementului linie.

fconfigure channel ?param1? ?value1? ?param2? ?value2?

Configureaza comportamentul unui canal. Daca nici o valoare param esre data, o lista a parametrilor valizi configurati si valorile lor e returnata.

Daca este dat numai un singur parametru pe linia de comanda, valoarea parametrului este returnata.

Daca sunt date una sau mai multe perechi de param/value,acei parametrii sunt setati la valoarea ceruta.

Parametrii care pot fi setati include:

-blocking . . . Determina daca atunci cand informatia nu poate fi mutata pe un canal,comanda va bloca.(i.e. daca nu este valabila nici o informatie la o citire sau daca amortizorul este plin la scriere).

-buffersize . . . Numarul bitilor care vor fi amortizati inainte de trimiterea informatiei sau inainte de a fi citita atunci cand este primita. Valoarea trebuie sa fie un numar intreg intre 10 si 1000000.

Seteaza cum Tcl va termina o linie cand este produsa. Prin scadere, liniile sunt sterse cu o linie noua, rezultatul transportului sau un sir nou/transport rezultat care este specific sistemului in care ruleaza interpretul.

Asta poate fi configurat sa fie:

o        auto . . . Trateaza linia noua, rezultatul transportului sau un sir nou/transport rezultat ca un sfarsit al unui marcaj. Produce terminatia liniara corecta pentru actuala platforma.

o        binary . . Comporta sirurile noi ca sfarsitul marcajelor liniare. Nu adauga nici o terminatie linara sirurilor produse.

o        cr . . . .Trateaza rezultatele transportului ca sfarsitul marcajului(si le traduce inter in linii noi).Liniile produse sunt delimitate cu un transport rezultat. Este standardul pentru Macintosh.

o        crlf . . . Trateaza perechile cr/lf ca sfarsitul marcajului liniilor si sfarseste liniile produse cu un rezultat al transportului/combinatie linefeed. Este standardul pentru Windows.

o        lf . . . . Comporta linefeed-ruile ca sfarsitul marcajului sirurilor si termina producerea liniilor cu un linefeed. Este standardul pentru Unix.

Exemplul este asemanator cu exemplul lectiei 40 cu un client si un port de server in acelasi script. Arata canalul unui server care este configurat sa nu blocheze si care foloseste stilul de amortizare in scadere - data nu este facuta valabila scriptului pana la aparitia unei noi linii sau pana amortizorul nu a completat.

Cand primul scrie: puts -nonewline $sock 'A Test Line' este gata, comanda fileevent ingreuneaza citirea,dar gets nu poate citii caracterele pentru ca nu exista sir nou. Gets rezulta un -1,iar fblocked un 1. Cand o linie noua este trimisa, informatia din amortizorul input va deveni valabila si gets rezulta 18,iar fblocked 0.

Exemplu

proc serverOpen

proc readLine else
} else
incr didRead;


set server [socket -server serverOpen 33000]

after 120 update;  # This kicks MS-Windows machines for this application

set sock [socket 127.0.0.1 33000]

set bl [fconfigure $sock -blocking]
set bu [fconfigure $sock -buffersize]
puts 'Original setting for sock: Sock blocking: $bl buffersize: $bu'

fconfigure $sock -blocking No
fconfigure $sock -buffersize 8;

set bl [fconfigure $sock -blocking]
set bu [fconfigure $sock -buffersize]
puts 'Modified setting for sock: Sock blocking: $bl buffersize: $bun'

# Send a line to the server -- NOTE flush

set didRead 0
puts -nonewline $sock 'A Test Line'
flush $sock;

# Loop until two reads have been done.

while


set len [gets $sock line]
puts 'Return line: $len -- $line'
close $sock
vwait didRead
catch

Child interpreters

Pentru majoritatea aplicatiilor, un singur interpret si subrutine sunt suficiente.Totusi,daca se construieste un sistem cilent-server se poate avea nevoie de mai multi interpreti care sa vorbeasca cu clienti diferiti si sa le mentina starea. Asta se poate face cu variabilele de stare, numind conventii sau schimband satrea la si de la disc,devenind incurcat.

Comanda interp creeaza un nou copilk interpret intr-un interpret deja existent. Copiii interpreti au propriile lor seturi de variabile si documente sau li se poate da acces la unele elemente din interpretul parinte.

Daca este creeat cu comanda -safe, copilul nu va putea accesa documentul de sistem sau sa va strice sistemul. Aceasta caracteristica permite unui script sa evalueze un cod de la un site necunoscut si de neicredere.

Numele copiilor interpreti sunt o lista iererhica. Daca interpretul foo este copilul intrepretului bar,atunci poate fi accesat de interpretul toplevel ca .

Interpretul primar (ceea ce rezulta cand tastati tclsh)este lista goala .

Comanda interp are mai multe subcomenzi si optiuni. Un subset important este:

interp create ?-safe? ?name?

Creeaza un nou interpret si rezulta un nume., Daca optiunea -safe este folosita, noul interpret nu va fi apt sa acceseze anumite facilitati periculoase ale sistemului.

interp delete name

copilul interpret selectat.

interp eval args

Este asemanator unei comenzi eval normale in afara faptului ca evalueaza scriptul in copilul interpret,in loc de interpretul primar.Comanda interp eval concentreaza args-urile intr-un sir si trimite linia respectiva copilului interpret pentru evaluare.

interp alias srcPath srcCmd targetPath targetCmd ?arg arg?

Comanda interp alias permite unui script sa imparta procedurile intre copiii interpreti sau intre un copil si un iterpret primar.

A se nota ca interpretii comandati au un status si namespace separate.dar nu au loop-uri de caz diferite. Acestea nu sunt fire si nu vor executa singure. Daca un interpret subordonat esrte oprit de o cerere de blocare I/O nici un alt interpret nu o va procesa pana nu este deblocata.

Exemplul de mai jos arata creearea a doi copii interpreti cu ajutorul interpretului primar . Fiecaruia dintre acesti interpreti ii este dat un nume variabil care sa contina numele interpretului.

A se observa ca, comanda alias cauzeaza evaluarea procedurii in interpretul in care procedura a fost definita si nu interpretul in care a fost evaluata. Daca este necesara existenta procedurii in interpret, atunic o comanda proc trebuie interp eval in interiorul interpretului. Daca doriti ca interpretul sa fie apt sa recheme interpretul primar(sau alt interpret)atunci se poate folosi comanda interp alias.

Exemplu

set i1 [interp create firstChild]
set i2 [interp create secondChild]

puts 'first child interp: $i1'
puts 'second child interp: $i2n'

# Set a variable 'name' in each child interp, and
# create a procedure within each interp
# to return that value

foreach int [list $i1 $i2] {
interp eval $int [list set name $int]
interp eval $int {proc nameis }
}

foreach int [list $i1 $i2]


# A short program to return the value of 'name'

proc rtnName


# Alias that procedure to a proc in $i1

interp alias $i1 rtnName rtnName

puts ''

# This is an error. The alias causes the evaluation
# to happen in the interpreter, where name is
# not defined.

puts 'firstChild reports [interp eval $i1 rtnName]'