Call TCL proc with named arguments
Asked Answered
O

3

5

Given this proc:

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

Is it possible to call proc foo and only pass a value for cc? Also, is it possible to pass a value to cc explicitly by name?

Everything I see suggests that all arguments must be passed by position.

Oolite answered 19/3, 2015 at 16:57 Comment(1)
Similar to this question: https://mcmap.net/q/1601937/-how-can-i-safely-deal-with-optional-parameters/7552Joyous
J
8

I would do something like Tk does:

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"
}

then

% 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
Joyous answered 19/3, 2015 at 19:23 Comment(1)
I'd use two array sets like this: array set optional {-aa "default a" -bb "default b"}; array set optional $argsCalie
A
1

You can use type shimmering to avoid constructing the dict..and this gives an interestingly simple and intuitive call. Pass the list representation of the dict to the proc e.g.:

  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}
Acidophil answered 5/10, 2015 at 17:50 Comment(0)
B
0

Arguments to procedures are passed by position. The use of two element lists as a component of the argument list, e.g. {aa a}, is to supply a default value. However as the manual says:

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

So, most people design their procedure interfaces to place the arguments that supply a default value at the end of the argument list.

One way to simulate named arguments is to design the procedure to take a single argument that is a dictionary value where the keys of the dictionary are the names of the parameters. For example,

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

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

If you don't mind the tedium of determining which optional parameters are supplied and the tedium of building a dictionary to invoke the procedure, then you can simulate named arguments this way and achieve some flexibility in supplying arguments to procedures. I don't use this technique very often myself. I find it easier to design the procedure interfaces more carefully. But sometimes the circumstances warrant all sorts of things.

Benitez answered 19/3, 2015 at 17:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.