Как я могу безопасно иметь дело с дополнительными параметрами - PullRequest
6 голосов
/ 26 февраля 2010

Я пишу процедуру для создания заголовка в выходном файле.

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

Я закончил кодировать это как один необязательный параметр

proc dump_header { test description {comment = ""}}

но хотел бы знать, как я могу добиться того же, используя args

proc dump_header { test description args }

Довольно просто проверить, что аргументы являются одним пустым параметром ($ args == ""), но плохо справляются с передачей нескольких параметров - и мне все равно нужна отрицательная проверка.

Ответы [ 3 ]

13 голосов
/ 26 февраля 2010

Ваше определение процедуры неверно (вы получите сообщение об ошибке too many fields in argument specifier "comment = """). Должно быть:

proc dump_header { test description {comment ""}} {
    puts $comment
}

Если вы хотите использовать args, вы можете проверить llength этого:

proc dump_header {test desc args} {
    switch -exact [llength $args] {
        0 {puts "no comment"}
        1 {puts "the comment is: $args"}
        default {
            puts "the comment is: [lindex $args 0]"
            puts "the other args are: [lrange $args 1 end]"
        }
    }
}

Возможно, вы также захотите передать пары имя-значение в списке:

proc dump_header {test desc options} {
    # following will error if $options is an odd-length list
    array set opts $options

    if {[info exists opts(comment)]} {
        puts "the comment is: $opts(comment)"
    }
    puts "here are all the options given:"
    parray opts
}
dump_header "test" "description" {comment "a comment" arg1 foo arg2 bar}

Некоторые предпочитают комбинацию args и пар имя-значение (а-ля Tk)

proc dump_header {test desc args} {
    # following will error if $args is an odd-length list
    array set opts $args
    if {[info exists opts(-comment)]} {
        puts "the comment is: $opts(-comment)"
    }
    parray opts
}
dump_header "test" "description" -comment "a comment" -arg1 foo -arg2 bar
5 голосов
/ 26 февраля 2010

Я использую библиотеку tcllib * cmdline для анализа параметров.

Это пример из документации cmdline:

set options {
    {a          "set the atime only"}
    {m          "set the mtime only"}
    {c          "do not create non-existent files"}
    {r.arg  ""  "use time from ref_file"}
    {t.arg  -1  "use specified time"}
}
set usage ": MyCommandName \[options] filename ...\noptions:"
array set params [::cmdline::getoptions argv $options $usage]

if {  $params(a) } { set set_atime "true" }
set has_t [expr {$params(t) != -1}]
set has_r [expr {[string length $params(r)] > 0}]
if {$has_t && $has_r} {
    return -code error "Cannot specify both -r and -t"
} elseif {$has_t} {
    ...
}

Итак, в вашем случае вы просто использовали бы args вместо argv в приведенном выше примере.

1 голос
/ 23 августа 2016

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

Я искал способ получить функциональность, аналогичную kwargs (необязательные аргументы пары ключ-значение) в python, и что-то, что хорошо работает (аналогично последнему примеру Гленна):

proc my_proc {positional_required1 {positional_optional1 "a_string"} args} {
    # Two optional arguments can be given: "opt1" and "opt2"
    if {![string equal $args ""]} {
        # If one or more args is given, parse them or assign defaults.
        array set opts $args
        if {[info exists opts(opt1)]} { set opt1 $opts(opt1) } else { set opt1 0 } 
        if {[info exists opts(op2)]} { set opt2 $opts(opt2) } else { set opt2 -1 }
    } else {
        # If no args are given, assign default values. 
        set op1 0
        set op2 -1
    }   
    # DO STUFF HERE
}

И можно назвать как:

my_proc "positional_required1_argument" 
# OR
my_proc "positional_required1_argument" "a_string"
# OR
my_proc "positional_required1_argument" "a_string" opt1 7
# OR
my_proc "positional_required1_argument" "a_string" opt1 7 opt2 50
# etc.

Потенциальным недостатком (как я сейчас это реализовал) является то, что если пользователь пропустит неподтвержденную опцию ключ-значение, ошибки не будет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...