TIP 288: Allow "args" Anywhere in Procedure Formal Arguments

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Author:         Peter Spjuth <[email protected]>
Author:         Andreas Leitgeb <[email protected]>
State:          Draft
Type:           Project
Vote:           In progress
Created:        03-Oct-2006
Post-History:   
Keywords:       Tcl,proc
Tcl-Branch:     aspect-tip288
Tcl-Version:    9.0

Abstract

This TIP proposes to make args have its special meaning as a formal procedure argument anywhere in the argument list. It also expands how required and optional arguments can be mixed.

Rationale

Many commands, specially many of Tcl's built in commands, have their variadic arguments in the beginning of the argument list and their required arguments at the end. An example is [lsearch ?options? list string].

Writing tcl procedures in that style is currently a bit cumbersome since you need to do you own argument counting and assignment to variables from "args".

If "args" had its special meaning at any location in the argument list, it would help with such a task, and it would make things more consistent.

Specification

At most one proc argument may be named "args" and can be anywhere in the argument list. Arguments just before and after "args" may be optional. Required arguments may be in the beginning and end of the argument list. Arguments are assigned in the following order:

  1. Required arguments to the left are assigned from the left. Required arguments to the right are assigned from the right. Order does not really matter since there must be enough arguments for all of them.
  2. Assign optional arguments left of "args" from the left.
  3. Assign optional arguments right of "args" from the right.
  4. Any remaining arguments are assigned to "args". If there are remaining arguments and no "args", it is an error like before.

Compatibility

Currently "args" is allowed anywhere in the argument list, and becomes a normal variable if not last. Most scripts probably don't use this since it would be rather confusing, but it might exist.

Interleaving required arguments with optional arguments was legal, but pointless. The current documentation mentions and discourages this use. A construct like this will now be an error:

proc z {a {b x} c args} { ... }

All such occurrences would need to be fixed. Detecting such scripts in an automated way would be simple and fixing them is trivial.

Examples

New style for an lsearch style proc:

proc lgurka {args list item} {
    array set opts {-apa 1 -bepa "" -cepa 0}
    foreach {arg val} $args {
        set opts([prefix match {-apa -bepa -cepa} $arg]) $val
    }
    # Do real stuff
}

Old style:

proc lgurka {args} {
    if {[llength $args] < 2} {
        return -code error "wrong # args: should be \"lgurka ?args? list item\""
    }
    set item [lindex $args end]
    set list [lindex $args end-1]
    set args [lrange $args 0 end-2]

    array set opts {-apa 1 -bepa "" -cepa 0}
    foreach {arg val} $args {
        set opts([prefix match {-apa -bepa -cepa} $arg]) $val
    }
    # Do real stuff
 }

Other examples:

proc x {a args b} { puts "a=$a, args=$args, b=$b" }

x 1 2   ;# ->  a=1, args=, b=2
x 1 2 3 ;# ->  a=1, args=2, b=3
x 1     ;# ->  error: wrong # args: should be "x a ?arg ...? b"

proc y {a {b x} args c} { ... }

y 1 2 3 ;# ->  a=1 b=2 c=3  args is empty
y 1 2   ;# ->  a=1 b=x c=2  args is empty

proc z {a {b x} c args} { ... }
->  error: required arg may not be in the middle

Implementation

See branch aspect-tip288.

Copyright

This document has been placed in the public domain.