使用命名参数调用 TCL proc

Call TCL proc with named arguments

给定这个过程:

proc foo {{aa "a"} {bb "b"} cc} {
  echo $cc
}

是否可以调用 proc foo 并只传递 cc 的值?另外,是否可以通过名称明确地将值传递给 cc

我看到的一切都表明所有参数都必须按位置传递。

过程的参数按位置传递。使用两个元素列表作为参数列表的组成部分,例如{aa a},就是提供一个默认值。然而,正如手册所说:

Arguments with default values that are followed by non-defaulted arguments become required arguments. In 8.6 this will be considered an error.

因此,大多数人在设计过程接口时将提供默认值的参数放在参数列表的末尾。

模拟命名参数的一种方法是将过程设计为采用单个参数,该参数是一个字典值,其中字典的键是参数的名称。例如,

proc foo {a} {
    if {[dict exists $a cc]} {
        puts [dict get $a cc]
    }
}

foo [dict create cc "this is the cc argument value"]

如果您不介意确定提供哪些可选参数的单调乏味以及构建字典以调用过程的单调乏味,那么您可以通过这种方式模拟命名参数,并在为过程提供参数时实现一些灵活性。我自己并不经常使用这种技术。我发现更仔细地设计过程接口更容易。但有时情况需要各种各样的事情。

我会像 Tk 那样做:

proc foo {cc args} {
    # following will error if $args is an odd-length list
    array set optional [list -aa "default a" -bb "default b" {*}$args]
    set aa $optional(-aa)
    set bb $optional(-bb)

    puts "aa: $aa"
    puts "bb: $bb"
    puts "cc: $cc"
}

然后

% foo
wrong # args: should be "foo cc ..."
% foo bar
aa: default a
bb: default b
cc: bar
% foo bar -bb hello -aa world
aa: world
bb: hello
cc: bar

您可以使用类型闪烁来避免构造 dict..这提供了一个有趣的简单直观的调用。将 dict 的列表表示传递给 proc 例如:

  proc foo {a} {
      if {[dict exists $a cc]} {
          puts [dict get $a cc]
      }
  }

  foo {cc "this is the cc argument value" dd "this is the value of dd}