我寫了下面PROC,模擬在Lodash過濾功能(JavaScript庫)(https://lodash.com/docs/4.17.4#filter)。你可以用3.5個基本格式來調用它,見例子部分。對於後面三種呼叫選項,我希望擺脫發送-s(速記)的要求。爲了做到這一點,我需要區分anonymous proc和list/dict/string。的Tcl - 列表/字典和匿名之間PROC區分
我試圖尋找string is
,但沒有一個字符串PROC。在研究這裏:http://wiki.tcl.tk/10166我發現他們推薦info complete
,但是在大多數情況下,無論參數的類型如何,參數都會通過該測試。
有沒有人知道一個可靠的測試方法呢?我知道我可以離開它或改變proc的定義,但我想盡可能保持Lodash的真實。
例子:
set users [list \
[dict create user barney age 36 active true] \
[dict create user fred age 40 active false] \
]
1. set result [_filter [list 1 2 3 4] {x {return true}}]
2. set result [_filter $users -s [dict create age 36 active true]]
3. set result [_filter $users -s [list age 36]]
4. set result [_filter $users -s "active"]
PROC代碼:
proc _filter {collection predicate args} {
# They want to use shorthand syntax
if {$predicate=="-s"} {
# They passed a list/dict
if {[_dictIs {*}$args]} {
set predicate {x {
upvar args args
set truthy 1
dict for {k v} {*}$args {
if {[dict get $x $k]!=$v} {
set truthy false
break
}
}
return $truthy
}}
# They passed just an individual string
} else {
set predicate {x {
upvar args args;
if {[dict get $x $args]} {
return true;
}
return false;
}}
}
}
# Start the result list and the index (which may not be used)
set result {}
set i -1
# For each item in collection apply the iteratee.
# Dynamically pass the correct parameters.
set paramLen [llength [lindex $predicate 0]]
foreach item $collection {
set param [list $item]
if {$paramLen>=2} {lappend param [incr i];}
if {$paramLen>=3} {lappend param $collection;}
if {[apply $predicate {*}$param]} {
lappend result $item
}
}
return $result
}
好吧,我想知道是否有人有說一個lambda項有這個的一個聰明的辦法,但列表/字典/字符串沒有。我看到的唯一可能的區別是,一個lambda LEN = 2或3。如果是3,我可以承擔的λ,因爲我真的只接受字典或字符串。但是如果它的len = 2,我唯一能想到的就是看第一個組件(args),並檢查它是否大於1,如果是的話,它最有可能是一個lambda或一個有空格的dict鍵。最終,我得出了同樣的結論,但想看看是否有人更聰明... –