是否有任何处理命名参数的Tcl包/附加组件?

时间:2018-01-22 10:18:00

标签: tcl parameter-passing

在Python,Ruby 2.0,Perl 6和一些硬件描述语言中,可以使用命名参数。见example。这使得代码更易读,易于维护等。有没有办法在TCL 8.6中完成/扩展,而不是使用字典作为解决方法?

2 个答案:

答案 0 :(得分:2)

在8.6中,使用从args解析的字典。 dict merge命令可以提供帮助:

proc example args {
    if {[llength $args] % 2} {
        return -code error "wrong # args: should be \"example ?-abc abc? ?-def def?\""
    }
    set defaults {
        -abc 123
        -def 456
    }
    set args [dict merge $defaults $args]
    set abc [dict get $args -abc]
    set def [dict get $args -def]
    puts "abc=$abc, def=$def"
}

example;                       # abc=123, def=456
example -abc 789;              # abc=789, def=456
example -def 789;              # abc=123, def=789
example -def 246 -abc 135;     # abc=135, def=246

你可以通过验证(tcl::prefix命令可以提供帮助)更进一步,但是它的工作要多得多,并且不会在生产代码中为你买更多东西。不是那个stopped people from trying

有两个提议可以添加完整的命名参数处理 (TIP #457TIP #479)目前为8.7,但我不确定是否真的获得了牵引力。 (从我的角度来看,问题是额外的运行时成本必须由志愿支持命名参数的代码承担。可能还有其他问题,例如对首选语法的分歧; I我没有那么多地关注它,因为我仍在为一段相当热的代码中的性能影响而烦恼。)

答案 1 :(得分:0)

tcler维基上有一整页讨论了命名参数:http://wiki.tcl.tk/10702

你可以通过一点创造力自己做。有几种机制可以让你这样做:

  1. procs可以定义其他过程
  2. proc的行为就像一个proc(函数定义系统不是语法,它是一个函数调用)
  3. procs可以使用args参数而不是位置参数,并手动处理参数列表
  4. 您可以使用uplevel
  5. 在任何父堆栈框架中执行代码
  6. 您可以使用upvar
  7. 从任何父堆栈框架中提取变量
  8. 一切都是字符串!
  9. 我不确定我是否列出了所有可能的机制。

    我个人对这个想法的实现是optproc:http://wiki.tcl.tk/20066

    实现本身很简单:

    proc optproc {name args script} {
        proc $name args [
            string map [list ARGS $args SCRIPT $script] {
                foreach var {ARGS} {
                    set [lindex $var 0] [lindex $var 1]
                }
                foreach {var val} $args {
                    set [string trim $var -] $val
                }
                SCRIPT
            }
        ]
    }
    

    我基本上使用字符串操作(string map)直接将函数体($script)插入到定义的函数中而没有任何替换等。这是为了避免任何$或{{ 1}}被处理。有很多方法可以做到这一点,但我的首选工具是[]

    除了两件事之外,这与唐纳德的答案相似:

    1. 我没有将string map转换为args,而是手动处理dict并在循环中声明每个局部变量。

    2. 这是一个元解决方案。我没有处理args而是创建了另一个函数(语法)来创建一个处理args的函数。

    3. 用法(从唐纳德的答案中偷来的)将是:

      args

      但请注意,我的解决方案不是唯一的解决方案。有很多方法可以做到这一点仅限于创造力。