TIP:		196
Title:		Tcl Commands as Values
Version:	$Revision: 1.2 $
Author:		Robert Suetterlin <robert@mpe.mpg.de>
State:		Withdrawn
Type:		Project
Tcl-Version:	8.5
Vote:		Pending
Created:	11-May-2004
Post-History:	

~ Abstract

This TIP proposes making command procedures first-class values in Tcl.
It also changes the command binding scheme to recognize these values
before performing old-style name lookup indirection.

~ Rationale

A Tcl script is a string containing one or more commands separated by
semicolons or newlines.  The evaluation of the script breaks these
commands into words.  Currently the string value of the first such
word is used to lookup a command procedure (effectively a function
pointer) and some clientData (per-command instance state).  These will
then be used by the virtual machine.

For example, in the case of pure Tcl procedures created with
'''proc''' command, this is ''TclProcInterpProc'' with an associated
''procPtr'' that basically references the procedure body (as a string)
and its formal argument list.

Because of the name lookup indirection, Tcl does not support anonymous
commands.  (There is quite some interest in using such with Tcl,
please compare [187] and [194].  Several other languages (even C)
support anonymous commands.  They seem to be quite useful, just
compare their use in Tcl's C code.)

This can be changed by allowing for a new kind of word (i.e. a new
'''Tcl_Obj''' ''commandObject'') that can be immediately interpreted
as a command.  ([187] proposes the use of special Tcl lists, but this
is too limiting for the scope of this document.)  The evaluation
checks if the first word is a ''commandObject'', if not it does the
old style name lookup (with '''unknown''' fallback).

A ''commandObject'' should store information equivalent to what is
provided with the '''Tcl_CreateCommand()''' API and stored in the
global name lookup table.  Thus it can reference any command procedure
and any clientData, allowing the creation of arbitrary anonymous
commands in C extensions for example.

Having such ''commandObject''s available will allow for '''proc''' to
return these instead of an empty string and to skip registration of a
command when its name is provided as the empty string.

~ Examples

This will allow to reproduce all of the features of [187].  Compare
this example with the one in [187]:

|proc filter {list proc} {
|    set res {}
|    foreach e $list {
|        if {![$proc $e]} {
|            lappend res $e
|        }
|    }
|}
|
|set a [list 1 10 100 4 5]
|set b [filter $a [proc x {expr $x<10}]]

This sets the variable b to the list {''10 100''}.

In addition this TIP still allows:

|proc {list lambda x {body}} {var} {puts $var} 

if we really want to.

And we can use ''commandObject''s that have not been created by
'''proc''' in the first place - think OOP for example.

These ''commandObject''s could also be used as data structure for the
command namespace, which would then become a dictionary, if I recall
correctly.  Allowing for registering an anonymous command with a name
(via '''rename''') by putting the name and the commandObject into the
dictionary.

~ Specification

This document proposes at least the following changes to the Tcl core:

 1. Include a new ''Tcl_Obj'' '''commandObj''' that contains
    information equivalent to the arguments ''proc'', ''clientData''
    and ''deleteProc'' to '''Tcl_CreateObjCommand()'''.  (Maybe interp
    is necessary, too.  But I don't understand the byte compiler and
    execute stuff good enough to judge.)

 2. Change '''Tcl_GetCommandFromObj()''' to check if ''objPtr''
    references a ''commandObj'' first, otherwise check if it finds a
    named command.

 3. Have the '''proc''' command return a ''commandObj'' that is
    equivalent to the '''Tcl_Create(Obj)Command()''' calls in
    '''Tcl_ProcObjCmd()'''.  i.e. the ''proc'' is equal to
    '''Tcl(Obj)InterpProc()''' and the ''clientData'' is the
    ''procPtr''.

~ Copyright

This document is in the public domain.
