Поиск…


замечания

Другим преимуществом использования строчных строк выражения является то, что байтовый компилятор обычно может генерировать более эффективный код (5 - 10 раз быстрее) от них.

Проблемы с несвязанными выражениями

Хорошей практикой является предоставление аргументов строки выражения в виде скобок. В заголовке «Двойная замена» излагаются важные причины.

Команда expr оценивает строку выражения на основе оператора для вычисления значения. Эта строка построена из аргументов в вызове.

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

Эти три вызова эквивалентны, и строка выражения такая же.

Команды if , for и while используют один и тот же код оценщика для аргументов условия:

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

Основное отличие состоит в том, что строка выражения условия всегда должна быть единственным аргументом.

Как и в каждом аргументе в вызове команды в Tcl, содержимое может быть или не быть заменено, в зависимости от того, как они цитируются / экранируются:

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}

Существует разница в третьем и четвертом случаях, так как обратная косая черта / скобки препятствуют замещению. Результат все тот же, так как оценщик внутри expr может сам выполнять подстановку переменных Tcl и преобразовывать строку в {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!

Здесь мы столкнулись с трудностями в аргументе: когда оценщик в expr выполняет подстановки, строка выражения уже была проанализирована на операторы и операнды, поэтому то, что видит оценщик, представляет собой строку, состоящую из двух операндов без оператора между ними. (Сообщение об ошибке « missing operator at _@_ in expression "$a _@_$b" ».)

В этом случае замена переменных перед expr предотвращала ошибку. Прикрепление аргумента предотвращало замену переменных до оценки выражения, что вызвало ошибку.

Такие ситуации могут возникать, чаще всего, когда выражение для оценки передается как переменная или параметр. В этих случаях нет другого выбора, кроме как оставить аргумент без аргументов, чтобы позволить оценщику аргументов «распаковать» строку выражения для доставки в expr .

Однако в большинстве других случаев фиксация выражения не наносит вреда и действительно может предотвратить множество проблем. Некоторые примеры этого:

Двойная замена

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

Незакрепленная форма будет выполнять подстановку команд, которая представляет собой команду, которая каким-то образом разрушает компьютер (или шифрует или форматирует жесткий диск или что у вас есть). Скошенная форма будет выполнять подстановку переменных, а затем попытаться (и не выполнить) сделать что-то из строки «[exec make computer go boom]». Бедствие было предотвращено.

Бесконечные петли

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

Эта проблема влияет как for while так и на while . Хотя кажется, что этот цикл будет отсчитываться до 0 и выйти, аргумент условия для while на самом деле всегда равен 10>0 потому что это то, что был оценен аргументом while активации команды while . Когда аргумент скопирован, он передается команде while виде $i>0 , и переменная будет заменена один раз для каждой итерации. Используйте это вместо этого:

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

Общая оценка

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

Каково значение a после запуска этого кода? Поскольку оператор && оценивает только правый операнд, если левый операнд равен true, значение должно быть равно 1. Но на самом деле это равно 2. Это потому, что оценщик аргументов уже выполнил все переменные и подстановки команд к тому времени, когда строка выражения оценены. Используйте это вместо этого:

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

Некоторые операторы (логические связки || и && и условный оператор ?: :) Определены так, чтобы не оценивать все их операнды, но они могут работать только в том случае, если строка выражения привязана.

Умножение переменной на 17

set myVariable [expr { $myVariable * 17 }]

Это показывает, как вы можете использовать простое выражение для обновления переменной. Команда expr не обновляет переменную для вас; вам нужно взять его результат и записать его в переменную с set .

Обратите внимание, что новые строки не важны на маленьком языке, понятном expr , и добавление их может сделать более длинные выражения намного проще для чтения.

set myVariable [expr {
    $myVariable * 17
}]

Это делает точно то же самое , хотя.

Вызов команды Tcl из выражения

Иногда вам нужно вызвать команду Tcl из вашего выражения. Например, предположим, что вам нужна длина строки. Для этого вы просто используете последовательность [...] в выражении:

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

Вы можете вызвать любую команду Tcl таким образом, но если вы сами вызываете expr , остановитесь! и подумайте, действительно ли вам нужен этот дополнительный звонок. Обычно вы можете делать это просто, помещая внутреннее выражение в круглые скобки.

Недопустимая ошибка

В самом Tcl строка, состоящая из одного слова, не обязательно должна указываться. На языке строк выражения, которые expr оценивает, все операнды должны иметь идентифицируемый тип.

Числовые операнды написаны без каких-либо украшений:

expr {455682 / 1.96e4}

Булевы константы:

expr {true && !false}

Синтаксис подстановки переменных Tcl распознается: операнд будет установлен на значение переменной:

expr {2 * $alpha}

То же самое касается замены команд:

expr {[llength $alpha] > 0}

Операнды также могут быть математическими вызовами функций с разделенным запятыми списком операндов в круглых скобках:

expr {sin($alpha)}

Операндом может быть строка с двумя кавычками или скобками. Строка с двойными кавычками подлежит замене, как в командной строке.

expr {"abc" < {def}}

Если операнд не является одним из вышеперечисленных, это незаконно. Поскольку нет никакого намека на то, что это за слово, expr сигнализирует об ошибке.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow