2017-10-19 89 views
1

我寫了下面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 
} 

回答

2

x {return true}一個字符串,列表,字典或(對於匿名PROC正確的名稱),一個lambda項?

事實是,它可能是他們的所有;這是正確的說它是一個價值是任何提到的類型的成員。你需要更準確和明確地描述你的意圖,而不是將它隱藏在某種類型的魔法中。通過使用諸如-s之類的選項或不同的主命令名稱可以獲得更高的精確度,但它仍然是必需的。你無法正確而安全地做你想做的事。


在更深入一點...

所有的Tcl值的字符串有效。

列表有一個定義的語法,並適當亞型的字符串。 (它們在內部以不同的方式實現,但您應該忽略這些細節。)

字典的語法等同於包含偶數個元素的列表,其中偶數索引處的元素彼此都是唯一的。

lambda項是具有兩個或三個元件(第三元件是上下文命名空間的名稱,缺省爲,如果它不存在全局命名空間)列表。列表的第一個元素也需要是一個有效的列表。

的兩元素列表匹配上述所有的要求。在Tcl的實際類型邏輯中,它同時是以上所有的。值的特定實例可能具有覆蓋下一個特定的實現表示,但這是不反映真實類型的值的瞬間的事情。

Tcl的類型系統是許多其他語言的不同。

+0

好吧,我想知道是否有人有說一個lambda項有這個的一個聰明的辦法,但列表/字典/字符串沒有。我看到的唯一可能的區別是,一個lambda LEN = 2或3。如果是3,我可以承擔的λ,因爲我真的只接受字典或字符串。但是如果它的len = 2,我唯一能想到的就是看第一個組件(args),並檢查它是否大於1,如果是的話,它最有可能是一個lambda或一個有空格的dict鍵。最終,我得出了同樣的結論,但想看看是否有人更聰明... –