我想重新定義TCL的foreach
,因爲foreach的多個應用程序打破了一些代碼。重新定義TCL foreach
詳細的問題描述
在碼符發生在Vivado,使用TCL腳本編寫的程序的實際情況。他們提供了一個指定get_<someObject>
方法的API,該方法返回對象列表(實際上其行爲與列表類似,但由xilinx實現,用於緩存/打印有點不同)。要處理這些列表,我使用foreach
。當我第一次使用列表中的foreach
時,我在循環變量中得到<objects>
。
但是,如果我在一個對象上應用foreach
,則該對象將轉換爲表示其名稱的字符串。問題是,API函數get_property
需要一個對象。
在應用foreach
兩次時,似乎沒有道理,如果您編寫兩個函數來獲取對象列表並對其進行操作,則可能會發生這種情況。
即
proc a {obj} {
puts "logging [llength $obj] objects:"
foreach o $obj {
puts "$o has column index [get_property COLUMN_INDEX $o]"
}
}
proc b {obj} {
foreach o $obj {
a $o
puts "working on $o"
get_property COLUMN_INDEX $o
}
}
如果我們現在調用這些函數如下
a [get_clock_regions X0Y0] # ok (the list is turned into single objects in foreach)
b [get_clock_regions X0Y0] # crashes inside a (the list from get_clock_regions is
# turned into objects by the foreach in b
# a is then called with a single object,
# the foreach now turns the object into a string
# representing the name, but get_property
# does not work on strings => error
我問,如果行爲可以被固定在這個question on the Xilinx Forums,但是我正在尋找的同時解決方法。
我所試圖做的
我想落實的同時解決方法。雖然我可以做
a [list $o]
內B,我認爲這將是更好,如果我可以重新定義foreach
不會打破上述情況。這樣,如果賽靈思可以解決這個問題,我可以簡單地放棄我對foreach
的重新定義。 (我期望foreach
工作相同,無論我有一個元素或單個元素的列表,據我的理解,這是在TCL相同)。
我與重新定義的foreach問題是:
- 我怎麼知道,如果
foreach
被稱爲foreach {varA varB} {valueList} {...}
foreach {varA varB} {valueList1 valueList2} {...}
- 有沒有一種方法來測試,如果我有一個對象或一個包含一個對象的列表?想法是兩個檢測,如果它只是一個對象,如果這樣包裝成一個列表,然後可以打開回正常的foreach對象,但我不知道如何檢測這種情況。
大綱代碼我會喜歡寫:
proc safeForeach {varnames valueLists body} {
if { thereAreMultiple valueLists } { # this issue no 1
foreach valueList $valueLists {
if {wouldDecayToString $valueLists} { # this is issue no 2
set valueLists [list $valueLists]
}
}
} else {
if {wouldDecayToString $valueLists} { # this is issue no 2 again
set valueLists [list $valueLists]
}
}
#the next line should be wraped in `uplevel`
foreach $varnames $valueLists $body
}
雖然我認爲你是部分正確的,但你必須明白,我不能改變對象或其行爲(阻止它衰減成字符串)。這讓我改變了另一端的代碼:雖然你聲稱一個對象和一個對象的列表是不同的東西,但我要求部分區別。在沒有空格或數字的字符串的情況下,我看不出有什麼不同。 ('if {1 == [list 1]} {puts {where is the difference}}'),我查看帶有空格的字符串作爲* multiple *字符串的列表,可以通過'foreach'拆除。 ... – ted
...然而,無論你經常通過'foreach'('foreach a「string」{foreach b $ a {foreach c $ b {puts $ c} }}''仍然會'puts'字符串''。如果它們實際上不同,我會很高興能夠學會一種方法來檢測差異。我很抱歉在這方面有點頭疼,但是我發現找到了這個問題相當令人沮喪,因爲'puts'並沒有真正的幫助(我仍然看到相同的輸出),並且希望找到一種解決方法,這並不需要將來的程序員不需要關於這個細節。 – ted
我明白你的沮喪。我們所有人都遇到過一些意想不到的結果,但這是由於嵌入式空白字符串作爲列表處理時,與不含內嵌空白字符串的字符串轉換的結果不同,這只是一個「細節「的列表是特殊格式的字符串和列表元素包含空格需要謹慎處理。我通常的解決方案是謹慎對待簡單的價值觀和名單之間的區別,以及對後面的人進行大量有用的評論。 –