Zoeken…


Opmerkingen

Een ander voordeel van het gebruik van accolades is dat de byte-compiler meestal efficiëntere code (5 - 10x sneller) kan genereren.

De problemen met niet-gescheiden uitdrukkingen

Het is een goede gewoonte om expressiereeksargumenten op te geven als accolades. De kop "Dubbele substitutie" schetst belangrijke redenen achter hetzelfde.

De opdracht expr evalueert een op operator gebaseerde expressiereeks om een waarde te berekenen. Deze string is opgebouwd uit de argumenten in de aanroep.

expr 1 + 2    ; # three arguments
expr "1 + 2"  ; # one argument
expr {1 + 2}  ; # one argument

Deze drie aanroepen zijn equivalent en de uitdrukkingstring is hetzelfde.

De opdrachten if , for en while gebruiken dezelfde evaluatiecode voor hun voorwaardeargumenten:

if {$x > 0} ...
for ... {$x > 0} ... ...
while {$x > 0} ...

Het belangrijkste verschil is dat de tekenreeks van de voorwaarde-expressie altijd een enkel argument moet zijn.

Zoals bij elk argument in een commando-aanroep in Tcl, kan de inhoud al dan niet worden vervangen, afhankelijk van hoe ze worden aangehaald / ontsnapt:

set a 1
set b 2
expr $a + $b   ; # expression string is {1 + 2}
expr "$a + $b" ; # expression string is {1 + 2}
expr \$a + \$b ; # expression string is {$a + $b}
expr {$a + $b} ; # expression string is {$a + $b}

Er is een verschil in het derde en vierde geval omdat de backslashes / accolades substitutie voorkomen. Het resultaat is nog steeds hetzelfde, omdat de evaluator in expr zelf de vervanging van de variabele Tcl kan uitvoeren en de string kan transformeren naar {1 + 2} .

set a 1
set b "+ 2"
expr $a $b   ; # expression string is {1 + 2}
expr "$a $b" ; # expression string is {1 + 2}
expr {$a $b} ; # expression string is {$a $b}: FAIL!

Hier komen we in de problemen met het argument tussen haakjes: wanneer de evaluator in expr substituties uitvoert, is de expressiereeks al ontleed in operatoren en operanden, dus wat de evaluator ziet is een tekenreeks die bestaat uit twee operanden zonder daartussen. (Het foutbericht is " missing operator at _@_ in expression "$a _@_$b" ".)

In dit geval heeft variabele vervanging vóór expr een fout voorkomen. Bracing het argument voorkwam variabele substitutie tot expressie evaluatie, wat een fout veroorzaakte.

Dit soort situaties kunnen zich voordoen, meestal wanneer een te evalueren uitdrukking wordt doorgegeven als een variabele of parameter. In die gevallen is er geen andere keuze dan het argument ongeschoorde het argument evaluator naar "uitpakken" de uitdrukking string voor de levering te laten vertrekken expr .

In de meeste andere gevallen is het echter niet schadelijk om de uitdrukking te schrappen en kan het inderdaad veel problemen voorkomen. Enkele voorbeelden hiervan:

Dubbele vervanging

set a {[exec make computer go boom]}
expr $a      ; # expression string is {[exec make computer go boom]}
expr {$a}    ; # expression string is {$a}

De niet-gecorrigeerde vorm voert de opdrachtvervanging uit, wat een opdracht is die de computer op de een of andere manier vernietigt (of de harde schijf versleutelt of formatteert, of wat dan ook). De vastgezette vorm zal een variabele vervanging uitvoeren en vervolgens proberen (en falen) om iets van de string "[exec make computer go boom]" te maken. Ramp afgewend.

Eindeloze lussen

set i 10
while "$i > 0" {puts [incr i -1]}

Dit probleem treft zowel for als while . Hoewel het lijkt dat deze lus zou aftellen tot 0 en zou afsluiten, is het voorwaardeargument tot while eigenlijk altijd 10>0 omdat dat argument werd geëvalueerd toen het while commando werd geactiveerd. Wanneer het argument wordt geschoord, wordt het doorgegeven aan de while opdracht als $i>0 , en de variabele wordt eenmaal vervangen voor elke iteratie. Gebruik dit in plaats daarvan:

while {$i > 0} {puts [incr i -1]}

Totale evaluatie

set a 1
if "$a == 0 && [incr a]" {puts abc}

Wat is de waarde van a na het uitvoeren van deze code? Aangezien de operator && alleen de rechteroperand evalueert als de linkeroperand waar is, moet de waarde nog steeds 1 zijn. Maar eigenlijk is het 2. Dit komt omdat de argumentevaluator al alle variabelen- en opdrachtvervangingen heeft uitgevoerd tegen de tijd dat de expressiereeks is geëvalueerd. Gebruik dit in plaats daarvan:

if {$a == 0 && [incr a]} {puts abc}

Verschillende operatoren (de logische verbindingen || en && , en de voorwaardelijke operator ?: && Zijn gedefinieerd om niet al hun operanden te evalueren, maar ze kunnen alleen werken zoals ontworpen als de tekenreeks string wordt gebruikt.

Een variabele met 17 vermenigvuldigen

set myVariable [expr { $myVariable * 17 }]

Dit laat zien hoe u een eenvoudige uitdrukking kunt gebruiken om een variabele bij te werken. De opdracht expr werkt de variabele niet voor u bij; je moet het resultaat nemen en het naar de variabele met set .

Merk op dat nieuwe regels niet belangrijk zijn in de kleine taal die expr begrijpt, en het toevoegen ervan kan langere uitdrukkingen veel gemakkelijker te lezen maken.

set myVariable [expr {
    $myVariable * 17
}]

Dit doet echter precies hetzelfde.

Een Tcl-opdracht aanroepen vanuit een uitdrukking

Soms moet u vanuit uw uitdrukking een Tcl-commando aanroepen. Stel bijvoorbeeld dat u de lengte van een string erin nodig hebt. Om dat te doen, gebruikt u gewoon een [...] reeks in de uitdrukking:

set halfTheStringLength [expr { [string length $theString] / 2 }]

Je kunt elk Tcl-commando op deze manier aanroepen, maar als je expr dat je expr zelf belt, stop dan! en bedenk of je echt dat extra telefoontje nodig hebt. Je kunt het meestal prima doen door de innerlijke uitdrukking tussen haakjes te plaatsen.

Ongeldige bareword-fout

In Tcl zelf hoeft een string die uit een enkel woord bestaat niet te worden geciteerd. In de taal van meningsuiting strings die expr evalueert, moeten alle operanden een herkenbare type hebben.

Numerieke operanden worden zonder decoratie geschreven:

expr {455682 / 1.96e4}

Zo zijn booleaanse constanten:

expr {true && !false}

Vervangende syntaxis van Tcl-variabele wordt herkend: de operand wordt ingesteld op de waarde van de variabele:

expr {2 * $alpha}

Hetzelfde geldt voor opdrachtvervanging:

expr {[llength $alpha] > 0}

Operanden kunnen ook wiskundige functie-aanroepen zijn, met een door komma's gescheiden lijst van operanden tussen haakjes:

expr {sin($alpha)}

Een operand kan een string tussen dubbele aanhalingstekens of een accolade zijn. Een string met dubbele aanhalingstekens kan worden vervangen, net als in een opdrachtregel.

expr {"abc" < {def}}

Als een operand niet een van de bovenstaande is, is het illegaal. Aangezien er geen hint is die laat zien wat voor woord het is, geeft expr een bareword-fout aan.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow