Переменные Tcl $argc и $argv

Я новичок в tcl, но мне нужно написать процедуру, которая выглядит так:

proc TestVerb { Data Data_txt } {
VERBATIM [format "// Data: $Data - $Data_txt"]
if { $argc == 2} {
    VERBATIM {// SUCCESS //}
else {
    exit 1
}

Я вызываю процедуру так: TestVerb Switch"This is used for..."

Процедура находится в другом файле, а вызов процедуры — в другом. Они кажутся правильными, потому что я получаю желаемый результат, если не использую $argc, но как только я использую $argv или $argc, я получаю следующую ошибку компиляции: Не могу прочитать $argv/$argc нет такой переменной

Если я буду ссылаться на эти переменные с помощью $::argc и $::argv, результат будет неправильным. $argv пусто, а $argc равно 0


person Flaxter    schedule 28.01.2015    source источник


Ответы (3)


Похоже, вы делаете здесь два неверных предположения:

  • Если процедура не использует специальный аргумент args в своем определении (дополнительную информацию см. ниже), она принимает только фиксированное количество аргументов, точно соответствующее количеству параметров, используемых в ее определении. Каждый вызов проверяется интерпретатором, и любой вызов с недопустимым количеством параметров завершится ошибкой до того, как будет достигнут код самой процедуры.

    Посмотреть на себя:

    % proc foo {a b c} {}
    % foo
    wrong # args: should be "foo a b c"
    % foo 1
    wrong # args: should be "foo a b c"
    % foo 1 2 3 4
    wrong # args: should be "foo a b c"
    % foo 1 2 3
    %
    

    Другими словами, просто не пытайтесь проверить количество аргументов, переданных вашему proc: оно уже проверено интерпретатором к моменту вызова вашей процедуры.

  • Глобальные переменные argc и argv управляют тем, что передается из операционной системы в программу интерпретатора Tcl, которая выполняет ваш сценарий Tcl.

    То есть, когда вы вызываете что-то вроде

    $ tclsh myscript.tcl foo bar
    

    Переменная с именем argc будет содержать 2, а argv будет установлен в список, содержащий две строки "foo" и "bar".

    Другими словами, эти переменные не имеют ничего общего с отдельными процедурами.


Относительно специального аргумента args: если процедура использует слово "args" для последнего из своих аргументов или имеет его в качестве единственного аргумента, то этот аргумент превращается в список, который использует любое число (включая ноль) фактических аргументов.

Так что вы можете сделать

proc foo {a b args} {}

и тогда ваша процедура foo может быть вызвана как foo 1 2, так и foo 1 2 3 4 5 6, но не как foo x (поскольку для формального аргумента b нет значения).

Внутри такого процесса вы используете обычные команды списка (такие как llength и lindex) для проверки того, что содержится в args. Например, вызов foo 1 2 3 4 5 6 установит для args то же значение, которое вы получите, вызвав [list 3 4 5 6].

person kostix    schedule 28.01.2015

Переменные argc и argv являются глобальными переменными (если они имеют особое значение). Внутри процедуры они совсем не являются особенными, если только вы не скажете:

global argc argv

или используйте полноценные версии.

С вашей процедурой вы получите сообщение об ошибке (сгенерированное механизмом вызова процедуры), если вы не передадите правильное количество аргументов. Вам не нужно проверять себя (если только вы не используете формальные параметры со значениями по умолчанию или специальную переменную args — обратите внимание на правописание — в конце формальных параметров).

Чтобы получить точный список аргументов, переданных вашей процедуре, используйте:

set allArguments [info level 0]

Обычно он вам не нужен. Вам определенно это не нужно при объявлении вашей процедуры, например:

proc TestVerb { Data Data_txt } {
    ...
}
person Donal Fellows    schedule 28.01.2015
comment
Здравствуйте, спасибо за быстрый ответ. Дело в том, что proc будет использоваться другими людьми, и мне нужно проверить количество аргументов, которые они ему дали, и, если они неверны, выйти; Я уже пытался использовать глобальный argv argc, но все равно получаю неверный вывод: argv ‹blank› argc 0 - person Flaxter; 28.01.2015

Как уже упоминалось выше, argv и argc не относятся к аргументам локальной процедуры. По умолчанию количество аргументов в процедуре Tcl фиксировано. Если вы хотите использовать список переменных, вы можете написать args:

proc TestVerb {args} {}

args можно рассматривать как обычный список. Если вы хотите проверить количество аргументов, вы можете использовать llength и использовать lassign для разделения списка аргументов:

proc TestVerb {args} {
    if {[llength $args] != 2} {
        message
        return
    }
    lassign $args Data Data_txt
    ....
}
person HanT    schedule 16.01.2019