的Tcl - 列表/字典和匿名之间PROC区分

问题描述:

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

x {return true}一个字符串,列表,字典或(对于匿名PROC正确的名称),一个lambda项?

事实是,它可能是他们的所有;这是正确的说它是一个价值是任何提到的类型的成员。你需要更准确和明确地描述你的意图,而不是将它隐藏在某种类型的魔法中。通过使用诸如-s之类的选项或不同的主命令名称可以获得更高的精确度,但它仍然是必需的。你无法正确而安全地做你想做的事。


在更深入一点...

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

列表有一个定义的语法,并适当亚型的字符串。 (它们在内部以不同的方式实现,但您应该忽略这些细节。)

字典的语法等同于包含偶数个元素的列表,其中偶数索引处的元素彼此都是唯一的。

lambda项是具有两个或三个元件(第三元件是上下文命名空间的名称,缺省为,如果它不存在全局命名空间)列表。列表的第一个元素也需要是一个有效的列表。

的两元素列表匹配上述所有的要求。在Tcl的实际类型逻辑中,它同时是以上所有的。值的特定实例可能具有覆盖下一个特定的实现表示,但这是不反映真实类型的值的瞬间的事情。

Tcl的类型系统是许多其他语言的不同。

+0

好吧,我想知道是否有人有说一个lambda项有这个的一个聪明的办法,但列表/字典/字符串没有。我看到的唯一可能的区别是,一个lambda LEN = 2或3。如果是3,我可以承担的λ,因为我真的只接受字典或字符串。但是如果它的len = 2,我唯一能想到的就是看第一个组件(args),并检查它是否大于1,如果是的话,它最有可能是一个lambda或一个有空格的dict键。最终,我得出了同样的结论,但想看看是否有人更聪明... –