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