Version 8 of Alternative Namespaces

Updated 2006-02-15 19:44:15

MJ - I was reading the page at [L1 ] and decided to try to implement some of the described behaviour using Tcl. The nice thing about the way namespaces work in the example below is that simply executing the namespace name (e.g. [win32]) displays all the methods in that namespace. This would be great for IDE autocompletion.

Note that because of the usage of {expand} this code requires at least Tcl 8.5 to run.


 # this code creates 3 namespaces: {win32}, {win32 media} and {string} 

 proc {win32 ping} {host} {
         puts "Sending ping to host $host"
 }


 proc {win32} {args} {
   set namespace [lindex [info level 0] 0]
         if { [llength $args]==0 } {
                 puts "[info procs [concat $namespace *]]"
         } else {
            "$namespace [lindex $args 0]" {expand}[lrange $args 1 end]
         }
 }

 proc {win32 media play} {song} {
   puts "playing song $song"
 }

 proc {win32 media beep} {length} {
         puts "beeping for $length"        
 }

 proc {win32 media} {args} {
   set namespace [lindex [info level 0] 0]
         if { [llength $args]==0 } {
                 puts "[info procs [concat $namespace *]]"
         } else {
            "$namespace [lindex $args 0]" {expand}[lrange $args 1 end]
         }
 }

 # do some tests with string
 rename string _string

 proc {string bytelength} {args} {
   _string bytelength {expand}$args
 }

 proc {string compare} {args} {
   _string compare {expand}$args
 }


 proc {string equal} {args} {
   _string equal {expand}$args
 }


 proc {string first} {args} {
   _string first {expand}$args
 }


 proc {string index} {args} {
   _string index {expand}$args
 }


 proc {string is} {args} {
   _string is {expand}$args
 }

 proc {string last} {args} {
   _string last {expand}$args
 }

 proc {string length} {string} {
   _string length $string
 }

 proc {string map} {args} {
   _string map {expand}$args
 }

 proc {string match} {args} {
   _string match {expand}$args
 }

 #range repeat replace tolower toupper totitle trim trimleft trimright wordend wordstart 

 proc {string} {args} {
   # puts "called string $args"
   set namespace [lindex [info level 0] 0]
         if { [llength $args]==0 } {
                 puts "[info procs [concat $namespace *]]"
         } else {
            "$namespace [lindex $args 0]" {expand}[lrange $args 1 end]
         }
 }


 puts [string length 12]

 # show all commands in the win32 namespace
 puts [win32]

NEM: See also namespace ensemble command (added in 8.5) that layers similar functionality over existing namespaces. The main differences are that procs in an ensemble are created using traditional

 proc foo::bar ...

syntax rather than the

 proc {foo bar} ...

use above. Also calling a namespace ensemble with no arguments produces an error, rather than a list of commands in that namespace. I quite like the idea of producing a list of commands (perhaps it can be done with one of the namespace ensemble options?). Note that you could also extend the syntax of proc in a backwards compatible way to support the following:

 proc foo bar {args} { ... }

This would then naturally extend to creating lambdas:

 set myfunc [proc {a b} { expr {$a + $b} }]

[MJ] - Note that after some consideration executing a command to determine its subcommands/namespace doesn't seem like a too bright of an idea, because you don't know up front if there are any subcommands and therefore you might actually execute a command that doesn't need any parameters. Imagine the surprise if an idea gets the bright idea to find subcommands for the command {system hardisk format}. The way to resolve this is of course to only execute namespaces. Which quickly leads to a subcommand that displays procs or namespaces and doesn't have any side-effects (like executing a command).

escargo - I have become more fond of object systems where you can query an object to determine what methods it understands. This is just basic introspection. One of the early suggestions I made to Snit was that types and methods should be able to respond to info commands. In that view, a command should be able to respond to info commands (or info methods) with the appropriate responses.

NEM - Yes, an info subcommand is also a good way to go. Conventions for such introspection could be formalised with, for instance Peter DeRijk's interface proposal.


[ Category Discussion ?? ]