【发布时间】:2017-10-19 21:06:12
【问题描述】:
我编写了以下 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,但是在大多数情况下,无论参数类型如何,参数都会通过该测试。
有谁知道可靠的测试方法吗?我知道我可以保留它或更改 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 _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
}
【问题讨论】:
标签: tcl