2010-02-26 44 views
6

我正在寫一個proc來在輸出文件中創建一個頭文件。我怎樣才能安全地處理可選參數

目前它需要一個可選參數,這是一個可能的標題註釋。

我已經結束了編碼這是一個可選參數

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

,但想知道怎樣才能達到使用ARGS相同

proc dump_header { test description args } 

這是很容易檢查ARGS是一個空白參數($ args ==「」),但如果傳遞多個參數則不能很好地處理 - 而且我仍然需要負面檢查。

+0

如果你的proc被超過3個參數調用,你想要做什麼:dump_header mytest mydesc {One comment} somethingelse?把somethingelse作爲另一種評論,以其他方式處理? – 2010-02-26 12:58:36

+0

將$ args與空字符串進行比較是錯誤的。參數是一個列表,而不是一個字符串。 – 2010-02-26 18:16:12

+0

好吧,它本身並沒有錯,因爲它會創建一個字符串表示,但是如果您要將它作爲列表反正 – 2010-03-01 11:29:26

回答

13

您的proc定義不正確(您會收到錯誤消息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與名稱 - 值對(a la 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 
+0

謝謝,這可能是不必要的。 對於其他情況,我認爲我更喜歡名稱 - 值對......但在這種情況下,我想您的答案將轉換爲「處理所有您必須視爲數組的情況」。這很好。 – itj 2010-03-01 13:39:13

5

我使用tcllibcmdline庫來做選項解析。

這是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

應該明確提到args是Tcl中的一個特殊詞,它在參數列表的末尾使用時包含所有其餘參數的列表。如果沒有給出args,則不會產生錯誤(與任何其他變量名稱不同,後者將被視爲必需參數)。

我一直在尋找工作的好聽點是(類似格倫的最後一個例子)的方式也有類似的Python的kwargs(可選的鍵值對參數)的功能,以及東西:

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. 

一個潛在的不利因素(如我目前實現了它)是,如果用戶通過未經批准的鍵值選項,沒有錯誤。