在Python,Ruby 2.0,Perl 6和一些硬件描述语言中,可以使用命名参数。见example。这使得代码更易读,易于维护等。有没有办法在TCL 8.6中完成/扩展,而不是使用字典作为解决方法?
答案 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 #457,TIP #479)目前为8.7,但我不确定是否真的获得了牵引力。 (从我的角度来看,问题是额外的运行时成本必须由不志愿支持命名参数的代码承担。可能还有其他问题,例如对首选语法的分歧; I我没有那么多地关注它,因为我仍在为一段相当热的代码中的性能影响而烦恼。)
答案 1 :(得分:0)
tcler维基上有一整页讨论了命名参数:http://wiki.tcl.tk/10702
你可以通过一点创造力自己做。有几种机制可以让你这样做:
args
参数而不是位置参数,并手动处理参数列表uplevel
upvar
等
我不确定我是否列出了所有可能的机制。
我个人对这个想法的实现是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}}被处理。有很多方法可以做到这一点,但我的首选工具是[]
。
除了两件事之外,这与唐纳德的答案相似:
我没有将string map
转换为args
,而是手动处理dict
并在循环中声明每个局部变量。
这是一个元解决方案。我没有处理args而是创建了另一个函数(语法)来创建一个处理args的函数。
用法(从唐纳德的答案中偷来的)将是:
args
但请注意,我的解决方案不是唯一的解决方案。有很多方法可以做到这一点仅限于创造力。