2009-10-20 41 views
11

Cách kinh điển để chuyển danh sách sang quy trình Tcl là gì?Danh sách chuyển tới thủ tục Tcl

Tôi thực sự thích nếu tôi có thể lấy nó để danh sách được tự động mở rộng thành số lượng đối số thay đổi.

Vì vậy mà cái gì đó như:

set a {b c} 
myprocedure option1 option2 $a 

myprocedure option1 option2 b c 

là tương đương.

Tôi chắc chắn rằng tôi đã thấy điều này trước đây, nhưng tôi không thể tìm thấy nó ở bất cứ nơi nào trực tuyến. Bất kỳ trợ giúp nào (và mã) để làm cho cả hai trường hợp tương đương sẽ được đánh giá cao.

Đây có phải là một quy ước Tcl tiêu chuẩn hay không. Hay tôi thậm chí còn sủa cây sai?

+0

Bạn có thêm từ "unwrap" (tốt nhất là trong "đối số unwrap") ở đâu đó trong câu hỏi tuyệt vời của bạn không? Tôi đã có một thời gian khó tìm kiếm nó :-) – cfi

Trả lời

14

Nó phụ thuộc vào phiên bản của Tcl bạn đang sử dụng, nhưng: Đối 8,5:

set mylist {a b c} 
myprocedure option1 option2 {*}$mylist 

Đối với 8,4 và dưới đây:

set mylist {a b c} 
eval myprocedure option1 option2 $mylist 
# or, if option1 and 2 are variables 
eval myprocedure [list $option1] [list $option2] $mylist 
# or, as Bryan prefers 
eval myprocedure \$option1 \$option2 $mylist 
+1

... mặc dù cá nhân tôi tìm thấy \ $ option1 \ $ option2 thích hợp hơn để [danh sách $ option1] [danh sách $ optio2]. Nó hiển thị chặt chẽ hơn ý định - mục đích của bạn không phải là tạo danh sách một phần tử, mục đích của bạn là ngăn chặn (hoặc bảo vệ chống lại) thêm một vòng thay thế cho các biến đó. –

+0

Cách kinh điển để làm điều này cho 8.4 và dưới đây là: 'eval [linsert $ mylist 0 myprocedure options1 option2]' –

+2

Tôi không đồng ý đó là kinh điển (nhưng có lẽ chúng ta có các loại khác nhau?). Nó được cho là an toàn nhất nhưng nó ít có thể đọc được hơn \ $ option1 \ $ option2 và một lần nữa phần nào che khuất những gì bạn đang thực sự cố gắng thực hiện. –

0

Để mở rộng về câu trả lời RHSeeger, bạn sẽ mã myprocedure với đối số đặc biệt args như sau:

proc myprocedure {opt1 opt2 args} { 
    puts "opt1=$opt1" 
    puts "opt2=$opt2" 
    puts "args=[list $args]" ;# just use [list] for output formatting 
    puts "args has [llength $args] elements" 
} 
+0

Tôi không đồng ý rằng bạn nhất thiết phải mã myprocedure để có một số lượng đối số thay đổi (ví dụ: sử dụng "args"). Cho dù bạn làm như vậy phụ thuộc hoàn toàn vào việc bạn có cần nó để lấy một số lượng đầu vào thay đổi hay không, không phải về cách một người gọi cụ thể xảy ra để có đầu vào của nó có sẵn cho nó. – RHSeeger

0

Nó có thể là hữu ích để lưu ý rằng thông qua lệnh của bạn để catch cũng sẽ giải quyết vấn đề này:

set a {b c} 
if [catch "myprocedure option1 option2 $a"] { 
    # handle errors 
} 

này nên có lẽ chỉ được sử dụng nếu bạn muốn xử lý những sai sót trong myprocedure vào thời điểm này trong mã của bạn để bạn don' t phải lo lắng về việc làm lại bất kỳ lỗi nào bị bắt.

Các vấn đề liên quan