command

Difference between version 42 and 43 - Previous - Next
A '''command''' is a sequence of '''[word%|%words]''' in a [script].



** See Also **

   [Dodekalogue]:   The rules of Tcl.

   [Tcl Commands%|%Tcl commands]:   

   [Command prefix%|%command prefix]:   

   [Command variety%|%command variety]:   



** Description **

When an [interpreter] encounters a command, it finds the [routine] associated
with the command and calls it with the arguments given in the command.

The first in a command is the name of the command, and the remaining words are
arguments.  Many things that have dedicated syntax in other languages are just
commands in Tcl.  Examples include [control structure%|%control structures],
like `[if]`, `[while]`, and `[for]`, declarations like `[global]`, `[proc]`,
and `[variable]`.  Even `[return]` is just another command.

The names of all commands available from the current [namespace] are returned
by

======
info commands
======

They may have come from several sources:

   * [C]-implemented commands
   * Tcl-implemented [proc%|%procs], listed in `[info procs]`
   * Aliases for other commands, listed in `[interp aliases] {}`
   * [Tk] [widget%|%widgets] use their pathname as command; you can test whether a string is a widget command with `[winfo exists] $name`
   * [image%|%images] also use their name as command name, listed in `[image names]`
   * [object orientation%|%object] systems like [incr Tcl] also use object names in the command position

The following proc returns the type of a command, or an empty string if the name is not a command:

======
proc command'type2 name {
    foreach {result condition} {
         unsourced {[info commands $name] eq {}
                    && [info exists ::auto_index($name)]}
         {}        {[info command $name] eq {}}
         proc      {[info procs $name] eq $name}
         alias     {[lsearch [interp aliases {}] $name] >= 0}
         image     {[lsearch [image names] $name] >= 0}
         widget    {[winfo exists $name]}
         command   1
    } {if $condition {return $result}}
} ;# RS
======

To introspect commands in other than the current namespace, walk the tree with
`[namespace children]`.

`[info procs]` and `[info commands]` behave differently. As the above piece of
code demonstrates, there are independent uses for the two.


----

[Cameron Laird] pointed out:

The succinct `command'type2` definition is slightly nonrobust in the face of,
for example,

======
proc tcl* args {}
======

It's far from alone in that minor weakness, of course

And there is a way to fix this: while [[info proc]] gets disturbed by the
asterisk (and returns a number of proc names that start with ''tcl''), other
subcommands like [[info args]] don't do glob matching, so replacing the "proc"
case above with

======none
proc {![catch {info args $name}]}
======

fixes the problem. Thank you! ([RS])

CL responds with a couple of observations:

1.  This is minor stuff.  There are applications in production
that have far bigger robustness problems, yet have been satisfying
end-users for years.  I can't even bring myself to call this a
problem--it's more of a footnote.

2.  On the other hand, it interests and entertains me how often
programs admit minor transformations that are strictly superior
in the sense that they're as readable and succinct, while being
"more correct" (satisfying over a wider input space, for example).
I salute Richard for so quickly finding such a transformation in
this case.

----

[LV] 2008-06-26: `command'type2` has a requirement that [Tk] be loaded before
you use it.  Judious use of `[catch]` probably could handle the issue...

[Lars H]: Another problem is that alias names aren't normalized — `[interp
alias]` faithfully records exactly the string used when creating the alias, but
the `$name` used for the command can be very different. For example, if you do

======
foreach ns {:: bar ::baz} {
    interp alias {} ${ns}::foo {} ::foopkg::dispatch $ns {some more data}
}
======

then `[interp aliases]` will faithfully `[return]`

======
::::foo bar::foo ::baz::foo
======

and it is ''only'' these strings you can use with `[interp alias]` if you want
to look up what the alias points to.

----[JMN] rename also makes aliases hard to introspect.
e.g rename somealias newalias

somealias will still show as a result in `[interp aliases]` and is still the name used to lookup the target - but it's no longer a command. 

This makes it difficult for any code to work out what 'newalias' actually is.  Is there any way?
----

[SS] 2006-06-30: [schlenk] just produced this procedure to check if a given
command exists, it is in theory trivial but in pratice to get it right is not
too simple, so maybe it's a good idea to put the proc here:

======
proc cmd_exists cmd {
    string equal {} [namespace eval :: [list namespace which $cmd]]
}
======

This above checks if the command is fully qualified basically (callable from
the global namespace with the given name), and could be used for a callback. If
you just want to see the fully qualified name, use a simple [namespace which]. 

----

Can't you just use `[info]`?

======
$ tclsh
% info command info
info
% info command nonsense
%
======

[schlenk]: Not if you have funny command names that are glob patterns like a
proc named `*` or `info*`, as info command does not have an -exact switch.

[LV]: well, technically you can:

======
$ tclsh
% proc info* {args} {return}
% info command info*
info info*
% info command {info*}
info info*
======

However, the info command returns _all_ the matching names in this case, so you
have to be ready to deal with that.  That's a bit annoying.

[Lars H]: It is perfectly possible to do an exact search by escaping all glob
metacharacters in the string, e.g.

======
proc cmd_exists_2 {cmd} {
    llength [info commands [string map {\\ \\\\ * \\* ? \\? [ \\[ ] \\]} $cmd]]
}
======

Then whether this would be any faster than the `[namespace which]` form is
another matter... I suspect it could be that they don't do exactly the same
thing when it comes to not-fully-qualified names, and that depending on the
problem one might want one or the other.

[escargo] 2005-07-01:  Maybe there is some argument for making '''all''' the
commands that use `[glob]` matching by default also accept `-exact` (and maybe
even `-regexp`).  Using `[glob]` matching by default is a convenience, but more
specific behavior should be allowed.

Making commands more uniform (by ensuring uniform matching behavior) seems like
it would make the language more regular and easier to understand.

[Lars H]: Well, that sounds like a short summary of [TIP]
[http://tip.tcl.tk/246.html%|%246].

[NEM]: You can always use either:

======
expr {$cmd in [info commands]}
lsearch -exact [info commands] $cmd
======

----

[DKF] 2012-10-20: I'm working on a project to [List of Tcl commands by bytecode
status%|%identify] what commands ''should'' be bytecode-compiled (and what are
and aren't).


** Page Authors **

    [Richard Suchenwirth]:   

    [PYK]:   





<<categories>> Glossary