【问题标题】:Tcl - Differentiate between list/dict and anonymous procTcl - 区分列表/字典和匿名过程
【发布时间】: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


    【解决方案1】:

    x {return true} 是字符串、列表、字典还是 lambda 术语(匿名过程的正确名称)?

    事实是它可能是全部;说它是任何上述类型的成员是正确的。您需要更准确、更明确地描述您的意图,而不是将其隐藏在某种类型的魔法中。可以通过使用-s 之类的选项或不同的主命令名称来实现更高的精度,但无论哪种方式,它仍然是必要的。你不能正确和安全地做你想做的事。


    再深入一点……

    所有 Tcl 值都作为字符串有效。

    列表具有定义的语法,并且是字符串的正确子类型。 (它们在内部的实现方式不同,但您应该忽略这些细节。)

    字典的语法相当于具有偶数个元素的列表,其中偶数索引处的元素彼此都是唯一的。

    Lambda 术语是包含两个或三个元素的列表(第三个元素是上下文命名空间的名称,如果不存在则默认为全局命名空间)。列表的第一个元素也必须是有效的列表。

    二元素列表符合上述所有要求。在 Tcl 的实际类型逻辑中,它同时是上述的all。值的特定实例化可能在幕后具有特定的实现表示,但这是暂时的,不能反映值的真实类型。

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

    【讨论】:

    • 对,我想知道是否有人有一个聪明的方式来说 lambda 术语有这个,但 list/dict/string 没有。我看到的唯一潜在区别是 lambda len=2 或 3。如果它是 3,我可以假设 lambda,因为我真的只接受 dict 或字符串。但是如果它的 len=2 我唯一能想到的就是查看第一个组件(args),并检查它是否大于 1,如果是,它很可能是一个 lambda 或一个有空格的 dict 键。最终,我得出了同样的结论,但想看看是否有人更聪明......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-12
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    相关资源
    最近更新 更多