我编写了以下proc,它模拟了Lodash(javascript库)(https://lodash.com/docs/4.17.4#filter)中的过滤功能。您可以在3.5基本格式中调用它,如示例部分所示。对于后三种调用选项,我想摆脱以-s(简写)发送的要求。为了做到这一点,我需要区分匿名proc和list / dict / string。
我试着查看string is
,但是没有字符串是proc。在此处进行研究:http://wiki.tcl.tk/10166我发现他们推荐info complete
,但在大多数情况下,无论参数类型如何,参数都会通过该测试。
有谁知道可靠的测试方法吗?我知道我可以离开它或改变过程定义,但我试图尽可能保持对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 Code:
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
}
答案 0 :(得分:2)
x {return true}
是字符串,列表,字典还是lambda术语(匿名proc的正确名称)?
事实是它可能所有;说这是一个值是任何上述类型的成员是正确的。你需要更精确和明确地描述你的意图,而不是把它隐藏在某种类型的魔法中。通过使用-s
之类的选项或不同的主命令名称可以实现更高的精度,但仍然需要这两种方式。你无法正确安全地做你想做的事。
更深入一点......
所有Tcl值都作为字符串有效。
列表具有已定义的语法,并且是字符串的正确子类型。 (他们在内部以不同的方式实施,但你应该忽略这些细节。)
字典的语法等同于具有偶数个元素的列表,其中偶数索引处的元素彼此都是唯一的。
Lambda术语是包含两个或三个元素的列表(第三个元素是上下文命名空间的名称,如果不存在,则默认为全局命名空间)。列表的第一个元素也必须是有效列表。
两元素列表符合上述所有要求。在Tcl的实际类型逻辑中,它同时是 all 。值的特定实例化可能在封面下具有特定的实现表示,但这是一个不能反映值的真实类型的瞬态事物。
Tcl的类型系统与许多其他语言不同。