Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overloading a standard Tcl command

Tags:

tcl

Small query related scope of the procedure

proc lappend {args} {
   set a $args
   lappend a testing ;# want to call the inbuilt tcl lappend command
   puts "$a"
}

set list {new to tcl}
lappend $list
like image 534
made_in_india Avatar asked Aug 06 '26 21:08

made_in_india


1 Answers

If you just do that, it won't work. It'll replace the standard lappend and you'll get an infinite recursion (well, you'll hit a stack-depth check). There are several ways to get around this.

Putting your code in a namespace

If your code is in a namespace, it will resolve the lappend within that namespace first and only use the global namespace if that local search fails. You can use this like this:

namespace eval myNS {
    proc lappend {args} {
        set a $args
        ::lappend a testing ;# Force the use of the global lappend command
        puts "$a"
    }

    set list {new to tcl}
    lappend $list
}

There are variations on that possible, namespace eval myNS {source example.tcl} (with your code being almost verbatim in that sourced file) being one if the more interesting ones as it allows the code to be mostly agnostic to the namespace.

Renaming the global lappend command

You can also move the standard command out of the way like this:

rename lappend lappend_original
proc lappend {args} {
   set a $args
   lappend_original a testing
   puts "$a"
}

set list {new to tcl}
lappend $list

This technique works just fine, so long as you don't have too much code warring over who has the actual original command. It's been used by many Tcl scripts over the years.

Real problem's solution: execution tracing

Of course, the lappend command isn't one that you really want to replace as it is heavily used in much Tcl library code. For the problem of figuring out where a piece of code is actually calling lappend and what arguments are being passed in, it's far better to be using an execution trace. (The link there is to the Tcl 8.6 documentation, but this API has been in place since Tcl 8.4 so you should have it available.)

proc runningLappend {cmdAndArgs operation} {
    puts [lrange $cmdAndArgs 1 end]
}
trace add execution lappend enter runningLappend
like image 60
Donal Fellows Avatar answered Aug 08 '26 11:08

Donal Fellows