Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Type Safe Tcl/Radical Language Modification

24 views
Skip to first unread message

George Peter Staplin

unread,
Jun 30, 2002, 3:10:31 PM6/30/02
to

Saturday night I decided to add type safety to Tcl. My experiment was a
success, and it seems interesting. It would probably be easy to
overload set to do something like this (much slower however), but the
initial goal was to overload the C functions, because it's trivial to
do.

I'm sure some purists will not like it, but...

It might be useful to make Tcl 9.0 optionally type safe, and after going
through so much of the code in tclVar.c I think I could implement it.

Variables must be declared before being used when MachTcl_TypeSafe 1 is
called, and an error will occur if a variable is set that isn't
declared. This is pretty much like C.

A demo package can be downloaded from here:
http://www.xmission.com/~georgeps/machtcl/
The latest as of this message is MachTcl-3.tgz

Consider this example script:
MachTcl_TypeSafe 1
int myInt
double myDouble
str myStr
byteArray myBA
int theInt 203

puts $myStr
puts $theInt

puts "BEGIN tests"
puts "setting myDouble to ABC should cause an error"
catch {set myDouble ABC} res
puts $res
puts "----"

puts "setting myInt to def should cause an error"
catch {set myInt def} res
puts $res
puts "----"


Now for the main.c that does it:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <tcl.h>

/*You probably know what to modify here:*/
#define LIB_TCL "/usr/local/lib/libtcl83.so.1.0"
#define OBJ_CMD_ARGS (ClientData clientData, Tcl_Interp *interp, int
objc, Tcl_Obj *CONST objv[])

enum {
MACHTCL_INT = 1,
MACHTCL_DOUBLE,
MACHTCL_STRING,
MACHTCL_LONG,
MACHTCL_BOOL,
MACHTCL_BYTEARRAY
};

static Tcl_HashTable MachTcl_Variables;

int MachTcl_HashTableReady;
int MachTcl_TypeSafe;

typedef Tcl_Obj *(*oldTcl_ObjSetVar2) (Tcl_Interp * interp, Tcl_Obj *
part1Ptr, Tcl_Obj * part2Ptr, \
Tcl_Obj * newValuePtr, int flags
);

oldTcl_ObjSetVar2 oldTcl_ObjSetVar2Ptr;

int MachTcl_GetVarType (char *varName, int *type) {
Tcl_HashEntry *hashEntryPtr;

if (MachTcl_HashTableReady != 1) {
return 0;
}
hashEntryPtr = Tcl_FindHashEntry (&MachTcl_Variables, varName);
if (hashEntryPtr == NULL) {
return 0;
}
*type = (int) Tcl_GetHashValue (hashEntryPtr);
return 1;
}

/*This takes an object of unknown type and trys to convert it.
*If the conversion was succesful then resObj points to a newly created
object
*that is used to set the variable. I tried using the Tcl_ObjType that
is within
*the object, but it seems to be NULL often.
*/
int MachTcl_ObjTypeIsValid (Tcl_Interp *interp, Tcl_Obj *objPtr, char
*varName, Tcl_Obj **resObj) {
int type = 0;

if (!MachTcl_GetVarType (varName, &type)) {
return 0;
}

if (objPtr == NULL) {
return 0;
}

switch (type) {
case MACHTCL_INT:
{
int i;
if (Tcl_GetIntFromObj (interp, objPtr, &i) != TCL_OK) {
return 0;
}
*resObj = Tcl_NewIntObj (i);
}
break;

case MACHTCL_DOUBLE:
{
double d;
if (Tcl_GetDoubleFromObj (interp, objPtr, &d) != TCL_OK) {
return 0;
}
*resObj = Tcl_NewDoubleObj (d);
}
break;

case MACHTCL_STRING:
{
int len;
char *str;
if ((str = Tcl_GetStringFromObj (objPtr, &len)) == NULL) {
return 0;
}
*resObj = Tcl_NewStringObj (str, len);
}
break;

case MACHTCL_LONG:
{
long l;
if (Tcl_GetLongFromObj (interp, objPtr, &l) != TCL_OK) {
return 0;
}
*resObj = Tcl_NewLongObj (l);
}
break;

case MACHTCL_BOOL:
{
int bo;

if (Tcl_GetBooleanFromObj (interp, objPtr, &bo) != TCL_OK) {
return 0;
}
*resObj = Tcl_NewBooleanObj (bo);
}
break;

/*This may be problematic if someone is setting a variable to a
blank value*/
case MACHTCL_BYTEARRAY:
{
int len;
unsigned char *ba = NULL;
ba = Tcl_GetByteArrayFromObj (objPtr, &len);
if (ba == NULL) {
return 0;
}
*resObj = Tcl_NewByteArrayObj (ba, len);
}
break;

default:
return 0;
break;
}
return 1;
}


void MachTcl_LoadOldTcl_ObjSetVar2 () {
void *libHandle;

libHandle = dlopen (LIB_TCL, RTLD_LAZY);

if (libHandle == NULL) {
fprintf (stderr, "libHandle dlerror: %s", dlerror ());
exit (1);
}

oldTcl_ObjSetVar2Ptr = (oldTcl_ObjSetVar2) dlsym (libHandle,
"_Tcl_ObjSetVar2");

if (oldTcl_ObjSetVar2Ptr == NULL) {
perror ("unable to load _Tcl_ObjSetVar2 symbol exiting...");
exit (1);
}
}

Tcl_Obj *Tcl_ObjSetVar2 (Tcl_Interp * interp, Tcl_Obj * part1Ptr,
Tcl_Obj * part2Ptr, \
Tcl_Obj *newValuePtr, int flags) {
Tcl_Obj *result;

if (oldTcl_ObjSetVar2Ptr == NULL) {
MachTcl_LoadOldTcl_ObjSetVar2 ();
}

if (MachTcl_TypeSafe) {
char *varName = Tcl_GetString (part1Ptr);
Tcl_Obj *newValueObj = NULL;

/*MachTcl_ObjTypeIsValid sets the interp result on error*/
if (MachTcl_ObjTypeIsValid (interp, newValuePtr, varName,
&newValueObj)) {
result = (*oldTcl_ObjSetVar2Ptr) (interp, part1Ptr, part2Ptr,
newValueObj, flags);
Tcl_DecrRefCount (newValuePtr);
return result;
}

Tcl_AppendResult (interp, " or variable not declared", NULL);
return NULL;
}

return (*oldTcl_ObjSetVar2Ptr) (interp, part1Ptr, part2Ptr,
newValuePtr, flags);
}

/*C binds too early I think, but it's fast.*/
/*Do this little trick to make Tcl update the function address called by
set*/
/*This is code from Tcl 8.3.4*/
int Tcl_SetObjCmd(dummy, interp, objc, objv)
ClientData dummy;
register Tcl_Interp *interp;
int objc;
Tcl_Obj *CONST objv[];
{
Tcl_Obj *varValueObj;

if (objc == 2) {
varValueObj = Tcl_ObjGetVar2 (interp, objv[1], NULL,
TCL_LEAVE_ERR_MSG);
if (varValueObj == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, varValueObj);
return TCL_OK;
} else if (objc == 3) {
varValueObj = Tcl_ObjSetVar2 (interp, objv[1], NULL, objv[2],
TCL_LEAVE_ERR_MSG);
if (varValueObj == NULL) {
return TCL_ERROR;
}
Tcl_SetObjResult(interp, varValueObj);
return TCL_OK;
} else {
Tcl_WrongNumArgs(interp, 1, objv, "varName ?newValue?");
return TCL_ERROR;
}
}


int MachTcl_TypeCmd OBJ_CMD_ARGS {
char *varName;
Tcl_Obj *result;
int isNewEntry;
Tcl_HashEntry *hashEntryPtr;
Tcl_Obj *varValue;


if (objc < 2 || objc > 3) {
Tcl_WrongNumArgs (interp, 1, objv, "give 2 or 3 arguments, no more,
no less\n");
return TCL_ERROR;
}

if (objc == 2) {
varValue = Tcl_NewObj ();
} else {
varValue = objv[2];
}

varName = Tcl_GetString (objv[1]);

hashEntryPtr = Tcl_CreateHashEntry (&MachTcl_Variables, varName,
&isNewEntry);

if (hashEntryPtr == NULL) {
Tcl_SetResult (interp, "unable to create hash entry", TCL_STATIC);
return TCL_ERROR;
}
Tcl_SetHashValue (hashEntryPtr, clientData);

result = Tcl_SetVar2Ex (interp, varName, NULL, varValue,
TCL_LEAVE_ERR_MSG);

if (result == NULL) {
return TCL_ERROR;
}

if (objc == 3) {
Tcl_SetObjResult (interp, result);
} else {
Tcl_ResetResult (interp);
}

return TCL_OK;
}

int MachTcl_TypeSafeCmd OBJ_CMD_ARGS {
if (objc != 2) {
Tcl_WrongNumArgs (interp, 1, objv, "with one arg\n");
return TCL_ERROR;
}

if (Tcl_GetIntFromObj (interp, objv[1], &MachTcl_TypeSafe) != TCL_OK)
{
Tcl_SetResult (interp, "bad arg\n", TCL_STATIC);
return TCL_ERROR;
}
return TCL_OK;
}

int MachTcl_Init (Tcl_Interp *interp) {
#define OBJ_CMD(name, clientData) Tcl_CreateObjCommand(interp, name,
MachTcl_TypeCmd, \
(ClientData) clientData, (Tcl_CmdDeleteProc *) NULL)

Tcl_InitHashTable (&MachTcl_Variables, TCL_STRING_KEYS);

MachTcl_HashTableReady = 1;
MachTcl_TypeSafe = 0;

Tcl_CreateObjCommand (interp, "MachTcl_TypeSafe", MachTcl_TypeSafeCmd,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL
);

Tcl_DeleteCommand (interp, "set");

Tcl_CreateObjCommand (interp, "set", Tcl_SetObjCmd,
(ClientData) NULL, (Tcl_CmdDeleteProc *) NULL
);

OBJ_CMD ("int", MACHTCL_INT);
OBJ_CMD ("double", MACHTCL_DOUBLE);
OBJ_CMD ("str", MACHTCL_STRING );
OBJ_CMD ("long", MACHTCL_LONG);
OBJ_CMD ("bool", MACHTCL_BOOL);
OBJ_CMD ("byteArray", MACHTCL_BYTEARRAY);

#undef OBJ_CMD

return TCL_OK;
}

int main (int argc, char *argv[]) {
Tcl_Interp *interp;

Tcl_FindExecutable (argv[0]);

interp = Tcl_CreateInterp ();

if (MachTcl_Init (interp) != TCL_OK) {
fprintf (stderr, "MachTcl_Init error %s\n", Tcl_GetStringResult
(interp));
exit (1);
}

if (Tcl_Init (interp) != TCL_OK) {
fprintf (stderr, "Tcl_Init error %s\n", Tcl_GetStringResult
(interp));
exit (1);
}

if (Tcl_EvalFile (interp, "./main.tcl") != TCL_OK) {
fprintf (stderr, "main.tcl error %s\n", Tcl_GetStringResult
(interp));
exit (1);
}

return 0;
}


Comments?


Enjoy,

George

Marc Spitzer

unread,
Jun 30, 2002, 10:15:39 PM6/30/02
to
In article <3D1F57A7...@XMission.com>, George Peter Staplin wrote:
>
> Saturday night I decided to add type safety to Tcl. My experiment was a
> success, and it seems interesting. It would probably be easy to
> overload set to do something like this (much slower however), but the
> initial goal was to overload the C functions, because it's trivial to
> do.
>
> I'm sure some purists will not like it, but...
>
> It might be useful to make Tcl 9.0 optionally type safe, and after going
> through so much of the code in tclVar.c I think I could implement it.

Just as long as it does not turn mandatory.

happy hacking

marc

Bryan Oakley

unread,
Jun 30, 2002, 11:08:52 PM6/30/02
to
George Peter Staplin wrote:
> Saturday night I decided to add type safety to Tcl. My experiment was a
> success, and it seems interesting. It would probably be easy to
> overload set to do something like this (much slower however), but the
> initial goal was to overload the C functions, because it's trivial to
> do.
>
> I'm sure some purists will not like it, but...
[snip]
> Comments?
>

This obviously makes Tcl different. I'd be interested to know why you
think it makes Tcl _better_. Do you feel type safety make Tcl
programmers more productive, and make Tcl applications better?

Type safety certainly has its place, but I'm not convinced it belongs in
Tcl, considering Tcl's "everything is a string" heritage (which I
consider to be possibly its greatest asset). Plus, making something as
fundamental as set "much slower" seems to be a very large step in the
wrong direction.


George Peter Staplin

unread,
Jul 1, 2002, 12:17:41 AM7/1/02
to

"Bryan Oakley" <oak...@bardo.clearlight.com> wrote in message
news:3D1FC7C...@bardo.clearlight.com...

> George Peter Staplin wrote:
> > Saturday night I decided to add type safety to Tcl. My experiment was a
> > success, and it seems interesting. It would probably be easy to
> > overload set to do something like this (much slower however), but the
> > initial goal was to overload the C functions, because it's trivial to
> > do.
> >
> > I'm sure some purists will not like it, but...
> [snip]
> > Comments?
> >
>
> This obviously makes Tcl different. I'd be interested to know why you
> think it makes Tcl _better_. Do you feel type safety make Tcl
> programmers more productive, and make Tcl applications better?

I think that type safety makes Tcl better, because it would give Tcl more
structure. You would have to declare a variable and its type before you use
it if you enabled type safety. This would also make it easier to check code
automatically for bugs. Ousterhout saw Tcl as a simple language with most
of the code in an application being in C, because I believe he said
something to the affect that C is more structured and better suited for
large programs. He has even expressed amazement that people have developed
80K+ LOC systems with Tcl.

Tcl didn't have namespaces originally, and they were placed in Tcl with some
reservation...

> Type safety certainly has its place, but I'm not convinced it belongs in
> Tcl, considering Tcl's "everything is a string" heritage (which I
> consider to be possibly its greatest asset). Plus, making something as
> fundamental as set "much slower" seems to be a very large step in the
> wrong direction.

I'm not convinced it belongs in Tcl either. I'm not even certain that my
reasons for believing that it improves Tcl are valid. Having a layout like
I proposed would help my code, but it might hurt the code of others. I
mainly implemented it to keep boredom away, and the TV programs on at the
time were boring (as usual). I probably should have just read a book. ;^)

At the C level it's pretty fast, and if I modified the tclVar.c code
directly it probably wouldn't be a problem. I may check the difference with
[time] later tonight to see if any apparent slowdowns show up.

Regards,

George


Donal K. Fellows

unread,
Jul 1, 2002, 6:36:28 AM7/1/02
to
George Peter Staplin wrote:
> I think that type safety makes Tcl better, because it would give Tcl more
> structure. You would have to declare a variable and its type before you use
> it if you enabled type safety. This would also make it easier to check code
> automatically for bugs.

You should allow people to declare that a variable may contain any value (i.e.
to say that typechecking should be turned off for a particular variable.)

> I'm not convinced it belongs in Tcl either. I'm not even certain that my
> reasons for believing that it improves Tcl are valid. Having a layout like
> I proposed would help my code, but it might hurt the code of others. I
> mainly implemented it to keep boredom away, and the TV programs on at the
> time were boring (as usual). I probably should have just read a book. ;^)

I think it is interesting. Please keep on trying to push the bounds; even
unsuccessful experiments allow people to make discoveries...

Donal.
--
Donal K. Fellows http://www.cs.man.ac.uk/~fellowsd/ fell...@cs.man.ac.uk
make: *** No rule to make target `war'. Stop.

Frank Pilhofer

unread,
Jul 1, 2002, 7:32:38 AM7/1/02
to
George Peter Staplin <Geor...@XMission.com> wrote:
>
> Saturday night I decided to add type safety to Tcl. My experiment was a
> success, and it seems interesting.
>

Yes, a type safe Tcl is indeed interesting.

However, the problem goes deeper than having type safety for basic types
like strings, integers and floating points. There's also lists (which then
contain a mixture of types), and, most importantly, code.

Note that a clean solution here would also solve the problem with reference-
counted "command objects" that TclBlend, Combat, and a lot of other packages
have - as these problems are caused by code contained in a string.

>
> Variables must be declared before being used when MachTcl_TypeSafe 1 is
> called, and an error will occur if a variable is set that isn't
> declared. This is pretty much like C.
>

I don't like declaring variables, however. IMHO that has no place in a
scripting language.

Frank


--
Frank Pilhofer ........................................... f...@fpx.de
Life is what happens to you while you're busy making future plans.
- Alfred E. Neuman

Pascal Scheffers

unread,
Jul 1, 2002, 10:21:35 AM7/1/02
to
On Mon, 01 Jul 2002 13:32:38 +0200, Frank Pilhofer wrote:

> George Peter Staplin <Geor...@XMission.com> wrote:
>> Variables must be declared before being used when MachTcl_TypeSafe 1 is
>> called, and an error will occur if a variable is set that isn't
>> declared. This is pretty much like C.
>>
>>
> I don't like declaring variables, however. IMHO that has no place in a
> scripting language.

Good point. For a quick script, having to declare a variable can be a
hassle and is unneeded most of the time. If it could be restricted to
namespace variables, that would extend the existing trend to have complex
structures/packages in namespaces and do the actual 'scripting' in the
global namespace.

- Pascal.

Bruce Stephens

unread,
Jul 1, 2002, 11:55:18 AM7/1/02
to
Bryan Oakley <oak...@bardo.clearlight.com> writes:

[...]

> Type safety certainly has its place, but I'm not convinced it
> belongs in Tcl, considering Tcl's "everything is a string" heritage
> (which I consider to be possibly its greatest asset). Plus, making
> something as fundamental as set "much slower" seems to be a very
> large step in the wrong direction.

I think it's an idea worth pursuing, but not in this way. The
problems we've encountered in writing lots of Tcl programs haven't
(mostly) been about strings vs integers vs bytearrays. They've been
almost always scalars vs lists. (Someone writes a proc taking a list
argument, but processing it using string manipulation, presuming that
list elements won't include spaces. That kind of thing, generally
being fuzzy about which things are strings and which are lists.)

So if an incompatible change were to be made, I think I'd like it to
be some more explicit distinction between lists and scalars, rather
than between different kinds of scalars.

Larry Smith

unread,
Jul 1, 2002, 1:43:06 PM7/1/02
to
Frank Pilhofer wrote:

> I don't like declaring variables, however. IMHO that has no place in a
> scripting language.

On the other hand, this idea goes a long way toward
making Tcl statically compilable. Would it not be
nice to be able to step out of Tcl and call a proc
compiled with a new front to gcc - implementing Tcl?
Would it not be cool to have Tcl self-hosted?

It would not be unreasonable to assume that any un-
declared variable is a string and to treat it as Tcl
always has. But when people are willing to declare
variables for the sake of efficiency or type safety,
or to help compilation, it seems resonable to me to
take advantage of it.

--
.-. .-. .---. .---. .-..-. | Wild Open Source Inc.
| |__ / | \| |-< | |-< > / | "Making the bazaar just a
`----'`-^-'`-'`-'`-'`-' `-' | little more commonplace."
home: www.smith-house.org | work: www.wildopensource.com

Bob Techentin

unread,
Jul 1, 2002, 1:50:18 PM7/1/02
to
"George Peter Staplin" <Geor...@XMission.com> wrote
>
> "Bryan Oakley" <oak...@bardo.clearlight.com> wrote

> >
> > This obviously makes Tcl different. I'd be interested to know why
you
> > think it makes Tcl _better_. Do you feel type safety make Tcl
> > programmers more productive, and make Tcl applications better?
>
> I think that type safety makes Tcl better, because it would give Tcl
more
> structure. You would have to declare a variable and its type before
you use
> it if you enabled type safety. This would also make it easier to
check code
> automatically for bugs. Ousterhout saw Tcl as a simple language
with most
> of the code in an application being in C, because I believe he said
> something to the affect that C is more structured and better suited
for
> large programs. He has even expressed amazement that people have
developed
> 80K+ LOC systems with Tcl.

Interesting ideas, but I would like to offer an alternative
suggestion. I have had some success with type checking implemented on
command parameters.

In my case, I've got C/C++ code for computationally intensive
simulations, wrapped with SWIG, and integrated into tclsh/wish as an
extension. The simulator main, and even the model files, are Tcl
scripts. I'm not too worried about the contents of the Tcl variables,
as long as I can ensure that I'm getting the right data at the C++
level.

Fortunately, SWIG provides a nice mechanism for including extra
classes and typedefs in the interface file, and custom code to convert
each type of value (typemaps.) At the C/C++ level, I can define a
function that accepts 'float' parameters, but I can be more specific
in my SWIG interface, requiring arguments of type 'Length' or 'Time'.
The typemap code can automatically call the units conversion code,
which will generate an error if the script supplies the wrong kind of
(string) parameter. It's pretty cool when engineers can specify
values like "20 milliseconds" or "0.02 minutes", and I don' t have to
do any extra coding. :-)

Perhaps it would be as straight forward to consider a type-safety
feature at the command parameter level. Come to think of it, don't
some of the option processing packages provide that capability?

Bob
--
Bob Techentin techenti...@mayo.edu
Mayo Foundation (507) 538-5495
200 First St. SW FAX (507) 284-9171
Rochester MN, 55901 USA http://www.mayo.edu/sppdg/


Bryan Oakley

unread,
Jul 1, 2002, 2:43:27 PM7/1/02
to
Larry Smith wrote:
>
> It would not be unreasonable to assume that any un-
> declared variable is a string and to treat it as Tcl
> always has. But when people are willing to declare
> variables for the sake of efficiency or type safety,
> or to help compilation, it seems resonable to me to
> take advantage of it.
>

Yes. This could be useful. Tcl variables are treated as per tradition
unless one makes a specific variable type safe by doing something like
"declare float floatVar". This would make it completely
backwards-compatible, wouldn't it? (not taking into account, for the
moment, whether we call it "declare" or "typesafe" or "typedvar" or
whatever).

And this could be extended to include lists vs scalars (and even arrays?)

Just brainstorming here a bit...

declare float floatVariable
declare int intVariable
declare float floatList -type list

set floatVariable "bugger!"
=> invalid float value "bugger"

set floatVariable floatList
=> scalar variable may not be given a list value

set intVariable $floatVariable
=> float value cannot be assigned to an int variable

We could fake multdimensional arrays for those who can't quite grasp
arrays-as-hash-tables:

declare string stringArray -dimension 2
set stringArray(1,2) "ok"
set stringArray(1, 2) "bad"
=> invalid array index "1, 2"

It could do this by having enforcing a simple regexp for array indices
(eg: there must be N-1 commas, and there must be no spaces. Or something
like that. I'd personally never use that, but people coming from
languages that have "real" arrays might find it helps in the transition.

If you wanted to turn off all type checking, you could simply redefined
"declare" to be a no-op at the top of a script.

proc declare {args} {#no-op}

I could live with that, assuming total backwards compatibility with
undeclared variables. Though I'd be just as happy leaving things as they
are today. Adding optional typed variables arguably makes the language
more complex, as we'd end up answering questions like "when do I want to
declare varibles and when do I not"? from newbies. Sometimes too many
spices spoil the brew.


Darren New

unread,
Jul 1, 2002, 2:57:35 PM7/1/02
to
Bryan Oakley wrote:
> more complex, as we'd end up answering questions like "when do I want to
> declare varibles and when do I not"? from newbies.

There would also be a host of interactions with things like [upvar], [info],
variables inside [expr], and etc. Not that it's insoluble, but it certainly
makes things far more complex.

--
Darren New
San Diego, CA, USA (PST). Cryptokeys on demand.
** http://home.san.rr.com/dnew/DNResume.html **
** http://images.fbrtech.com/dnew/ **

Proud to live in a country where "fashionable"
is cheap cloth, faded, with holes.

Andreas Leitgeb

unread,
Jul 1, 2002, 3:20:17 PM7/1/02
to
Bryan Oakley <oak...@bardo.clearlight.com> wrote:
> Just brainstorming here a bit...
joining into brainstorm...

> declare int intVariable
One would likely be tempted to use an int for all kinds of indices,
but then there is also "end", "end-1", ... ;-/

perhaps a special index-type that enhances int by these special
values, (including those used by various tk-widgets ...)

> [ multidimensional arrays ]


> declare string stringArray -dimension 2

That would conflict with a more desirable possibility to declare
more variables of same type in one statement:
declare int i1 i2 i3

also, the arguments could be initialized at declaration-time
(similar to default-arguments for proc's) :
declare int {i1 0} {i2 2} {{varname with spaces} -1} i4

> If you wanted to turn off all type checking, you could simply redefined
> "declare" to be a no-op at the top of a script.
> proc declare {args} {#no-op}

well the noop-part would be a little more complicated with
initialisation-values...


> I could live with that, assuming total backwards compatibility with
> undeclared variables. Though I'd be just as happy leaving things as they
> are today. Adding optional typed variables arguably makes the language
> more complex, as we'd end up answering questions like "when do I want to
> declare varibles and when do I not"? from newbies. Sometimes too many
> spices spoil the brew.

100% agree.


--
Newsflash: Sproingy made it to the ground !
read more ... <http://avl.enemy.org/sproingy/>

Bob Techentin

unread,
Jul 1, 2002, 4:15:11 PM7/1/02
to
"Bryan Oakley" <oak...@bardo.clearlight.com> wrote

>
> Just brainstorming here a bit...
>
> declare float floatVariable
> declare int intVariable
> declare float floatList -type list
>
> set floatVariable "bugger!"
> => invalid float value "bugger"
>

Couldn't this kind of functionality be easily implemented in a proc
which set the variable and some traces? Here's a rather un-robust
example.

proc declareFloat { vName } {
upvar $vName v ;
set v "" ;
trace variable v w enforceFloat
}

proc enforceFloat { name1 name2 op } {
upvar $name1 v ;
if { ! [string is double $v] } {
error "invalid Float value '$v'"
}
}

declareFloat floatVariable
set floatVariable bugger!
can't set "floatVariable": invalid Float value 'bugger!'

Bryan Oakley

unread,
Jul 1, 2002, 4:43:07 PM7/1/02
to
Bob Techentin wrote:
> "Bryan Oakley" <oak...@bardo.clearlight.com> wrote
>
>>Just brainstorming here a bit...
>>
>> declare float floatVariable
>> declare int intVariable
>> declare float floatList -type list
>>
>> set floatVariable "bugger!"
>> => invalid float value "bugger"
>>
>
>
> Couldn't this kind of functionality be easily implemented in a proc
> which set the variable and some traces?

I would think that is highly probable. I haven't tried it, but perhaps
if someone really wanted this behavior in the core, the TIP author could
do a pure tcl version as a proof of concept (assuming it can be done).

Enforcing lists vs. scalars might be hard to do since at the tcl level
it's not possible to determine if something is a "pure" list (ie: a list
representation with no string representation). For example, Ideally the
following should throw an error:

declare string foo
declare string bar -type list

set foo "this is a scalar string"
set bar $foo

In a pure tcl implementation there is no way to know that bar is being
assigned a value from a scalar variable, and the code has no way to
distinguish between a string that looks like "this is a scalar string"
from a list that looks like {this is a scalar string}.

Bruce Stephens

unread,
Jul 1, 2002, 5:52:19 PM7/1/02
to
Bryan Oakley <oak...@bardo.clearlight.com> writes:

[...]

> Enforcing lists vs. scalars might be hard to do since at the tcl level


> it's not possible to determine if something is a "pure" list (ie: a
> list representation with no string representation). For example,
> Ideally the following should throw an error:
>
> declare string foo
> declare string bar -type list
>
> set foo "this is a scalar string"
> set bar $foo
>
> In a pure tcl implementation there is no way to know that bar is
> being assigned a value from a scalar variable, and the code has no
> way to distinguish between a string that looks like "this is a
> scalar string" from a list that looks like {this is a scalar
> string}.

True, but mostly the important things happen at procedure
boundaries. (Or at least, that's what seemed to be so for us.) It's
presumably possible at the C level to determine whether something is a
pure list or not, so it would be a useful little extension to provide
commands which would allow things like:

assert_list $bar

and

assert_scalar $foo

which would (mostly) be used on proc parameters. (Actually
assert_scalar probably isn't that useful. Mostly we found problems
with strings being passed around when they should have been lists;
mostly we didn't notice initially, because mostly the elements were
filenames or other things which (normally) didn't have spaces. But
then things went wrong, subtly and in ways that were horribly hard to
track down.)

Chang Li

unread,
Jul 1, 2002, 7:37:33 PM7/1/02
to
Bryan Oakley <oak...@bardo.clearlight.com> wrote in message news:<3D20A2CC...@bardo.clearlight.com>...

>
> Yes. This could be useful. Tcl variables are treated as per tradition
> unless one makes a specific variable type safe by doing something like
> "declare float floatVar". This would make it completely
> backwards-compatible, wouldn't it? (not taking into account, for the
> moment, whether we call it "declare" or "typesafe" or "typedvar" or
> whatever).
>
> And this could be extended to include lists vs scalars (and even arrays?)
>
> Just brainstorming here a bit...
>
> declare float floatVariable
> declare int intVariable
> declare float floatList -type list

I like the idea of declare. For me it could be used to declare a struct.

declare struct myStruct {int size double x double y double z}

so I do not need to added a new struct and other commands in the global space.

Chang

ulis

unread,
Jul 2, 2002, 3:30:08 AM7/2/02
to
> In a pure tcl implementation there is no way to know that bar is being
> assigned a value from a scalar variable, and the code has no way to
> distinguish between a string that looks like "this is a scalar string"
> from a list that looks like {this is a scalar string}.

I dreamed that Tcl allows me to declare a true string and a true list...
And a true script.

ulis

Donal K. Fellows

unread,
Jul 2, 2002, 6:17:26 AM7/2/02
to
ulis wrote:
> I dreamed that Tcl allows me to declare a true string and a true list...
> And a true script.

But:
puts {hello sailor}
is all three. This is a Good Thing.-

-- What's the reason of long discussions, if at the end someone says, "we have
not yet thought about it..." -- Andreas Leitgeb <a...@pc7499.gud.siemens.at>

Juan C. Gil

unread,
Jul 2, 2002, 6:49:51 AM7/2/02
to
"Bob Techentin" <techenti...@mayo.edu> wrote in message news:<afq4op$c2k$1...@tribune.mayo.edu>...

>
> Perhaps it would be as straight forward to consider a type-safety
> feature at the command parameter level. Come to think of it, don't
> some of the option processing packages provide that capability?
>
Yes, they do.

The Simple Library at http://simplelib.bobsville.com provides
typing for command arguments (SimpleProc):

------------------------------------------------------------
# Install the package
package require SimplePackage
::Simple::Package::require-and-install SimpleProc

# Enable arguments run-time type checking
::Simple::Proc::configure -checktype true

# Create a procedure which takes an
# optional flag and a required integer
proc-ext {
zero
} {
{-zero boolflag {Zero flag}}
{ integer integer {Integer}}
} {
if {$zero} {
puts 0
} else {
puts $integer
}
}

# Get some info about the procedure
# This displays the following:
# 0
# ?-zero? integer
# Zero flag
puts [::Simple::Proc::information issubcommand zero]
puts [::Simple::Proc::information usage zero]
puts [::Simple::Proc::information description zero -zero]

# Valid calls
# This displays the following:
# 23
# 0
# 0
zero 23
zero 0
zero -zero 23

# Invalid call
# This displays the following:
# invalid value "foo" for "integer" of type "integer"
catch {zero foo} result
puts $result
------------------------------------------------------------


and also for non-local variables (SimpleTypedVar):

------------------------------------------------------------
# Install the package
package require SimplePackage
::Simple::Package::require-and-install SimpleTypedVar

# Create a typed variable and monitor its value
::Simple::TypedVar::create foobar -description {may contain foo or bar only}\
-monitortype true -type choice -choices {foo bar}
#
# Get some information about the just created variable
# This displays the following:
# Type: "choice"
# Description: "may contain foo or bar only"
puts "Type: \"[::Simple::TypedVar::information type foobar]\""
puts "Description: \"[::Simple::TypedVar::information description foobar]\""

# Set the variable to a valid value
# This displays the following:
# bar
set foobar bar
puts $foobar

# Set the variable to an invalid value
# This throws an error:
# can't set "foobar": invalid value "gee" for variable
# "::foobar" of type "choice": must be foo or bar
set foobar gee
------------------------------------------------------------


Juan Carlos---

Kristoffer Lawson

unread,
Jul 2, 2002, 8:31:31 AM7/2/02
to
Bryan Oakley <oak...@bardo.clearlight.com> wrote:
>
> Yes. This could be useful. Tcl variables are treated as per tradition
> unless one makes a specific variable type safe by doing something like
> "declare float floatVar". This would make it completely
> backwards-compatible, wouldn't it? (not taking into account, for the
> moment, whether we call it "declare" or "typesafe" or "typedvar" or
> whatever).

The risk with all of this is that it's difficult to go back. If you have
extensions which require certain types as parameters then you are stuck.
I think this could be most problematic if strings were also strict. Say
[puts] required a string and you passed it a double. Would it cause an
error? I'm not sure I'd like that.

For other types it might be useful as often I have procs which check
the type anyway. OTOH I wonder how useful? I have those checks in place
anyway, so it would only be shorthand.

--
/ http://www.fishpool.com/~setok/

ulis

unread,
Jul 2, 2002, 9:21:40 AM7/2/02
to
> I think it's an idea worth pursuing, but not in this way. The
> problems we've encountered in writing lots of Tcl programs haven't
> (mostly) been about strings vs integers vs bytearrays. They've been
> almost always scalars vs lists. (Someone writes a proc taking a list
> argument, but processing it using string manipulation, presuming that
> list elements won't include spaces. That kind of thing, generally
> being fuzzy about which things are strings and which are lists.)
>
> So if an incompatible change were to be made, I think I'd like it to
> be some more explicit distinction between lists and scalars, rather
> than between different kinds of scalars.

I had the same experiment and agree with that (explicit distinction
between lists and scalars).

ulis

Gustaf Neumann

unread,
Jul 2, 2002, 11:02:43 AM7/2/02
to
"Bob Techentin" <techenti...@mayo.edu> wrote in message news:<afqd8d$l2v$1...@tribune.mayo.edu>...

> "Bryan Oakley" <oak...@bardo.clearlight.com> wrote
> >
> > Just brainstorming here a bit...
> >
> > declare float floatVariable
> > declare int intVariable
> > declare float floatList -type list
> >
> > set floatVariable "bugger!"
> > => invalid float value "bugger"
> >
>
> Couldn't this kind of functionality be easily implemented in a proc
> which set the variable and some traces? Here's a rather un-robust
> example.

but still, quite nice!

one neat thing about traces is that one can add arbitarty constraints for
a variable, like

constrain intvar {is_int($X)}
constrain someothervar {is_int($X) && $X>10 && $X<100}

where $X is a place-holder for the actual value

-gustaf

Kristoffer Lawson

unread,
Jul 3, 2002, 10:10:30 AM7/3/02
to
Gustaf Neumann <neu...@wu-wien.ac.at> wrote:
>
> one neat thing about traces is that one can add arbitarty constraints for
> a variable, like
>
> constrain intvar {is_int($X)}
> constrain someothervar {is_int($X) && $X>10 && $X<100}

I'm not adding anything to this comment but: yes, that's neat. Hm.. I
think that's something I'm going to start using.

--
/ http://www.fishpool.com/~setok/

Tom Wilkason

unread,
Jul 3, 2002, 11:38:20 AM7/3/02
to
"Bryan Oakley" <oak...@bardo.clearlight.com> wrote in message
news:3D20A2CC...@bardo.clearlight.com...
<snip>|

| We could fake multdimensional arrays for those who can't quite grasp
| arrays-as-hash-tables:
|
| declare string stringArray -dimension 2
| set stringArray(1,2) "ok"
| set stringArray(1, 2) "bad"
| => invalid array index "1, 2"
|
| It could do this by having enforcing a simple regexp for array indices
| (eg: there must be N-1 commas, and there must be no spaces. Or something
| like that. I'd personally never use that, but people coming from
| languages that have "real" arrays might find it helps in the transition.

Let's turn this thought around, what about using declare to allow the use of "real"
arrays, i.e. those with numerical indicies (possibly sparse) to prevent the need for
slow hash lookups? It would make matrix number crunching much faster.

Tom Wilkason

miguel sofer

unread,
Jul 3, 2002, 12:45:27 PM7/3/02
to

Note that tcl8.4 supports direct access to nested lists, via the
expanded [lindex] and the new [lset] commands. Directly accessible
nested lists are pretty close to "real multidimensional arrays" and much
faster than arrays/hashtables. Matrix number crunching does get much
faster.

What you can do now is for instance

%info patch
8.4b1
% set matrix {{1 2 3} {4 5 6}}
{1 2 3} {4 5 6}
% lindex $matrix 1 2
6
% lindex $matrix {1 2}
6
% lset matrix 1 2 9
{1 2 3} {4 5 9}
% lset matrix {0 1} 8
{1 8 3} {4 5 9}
% lindex $matrix 0 2
3

miguel


rick horwitz

unread,
Jul 8, 2002, 8:10:37 PM7/8/02
to
Guys, I've got to take the gloves off on this one. Type safety in TCL
in particular and any programming language in general, in the year
2002, is about the dumbest thing I have heard of. It is a vestage of a
by-gone era. If you are still reading this then let me take you back
to why 'typing' was implemented in the first place-to make it
easier/more efficient for compilers/computers to deal with the storage
and execution of logic and data. It was done at the expense of the
human resource rather than the rather limited memory and processor
resources available at that time. Hey, we are talking about the days
when 'core' cost in the thousands and a machine cycle cost almost as
much.
Productivity wasn't the issue; making it easier for compilers that had
little room to play with and making more efficent us of available
machine cycles was.

Hence, data typing made sense. You spend time ($$$) telling the
computer what it is dealing with so that code doesn't have to be
written and the maching cycles expended to do it for you.

Today, there is no rational, economical reason to waste one key stroke
on such an effort.

The real value of TCL (and other type-less languages, such as MUMPS,
APL, etc) is the opportunity to achive real programmer productivity
and, at the same time, construct software that is machine independent.
Memory is cheap, cycles are cheap and exceedingly fast, and disk
storage is cheap. But people are not.

Look at this message. Did I need to reserve space or have specific
locations for writing the numbers 345. Did I have to preface the text
with "the following is varchar 32". Is this the only medium in which I
can write this message?

So please tell me again about the business value of why I would want
or care about having a Type Safe TCL or any language, for that matter.

Rick

Bruce Stephens

unread,
Jul 9, 2002, 5:37:35 AM7/9/02
to
whee...@att.net (rick horwitz) writes:

[...]

> So please tell me again about the business value of why I would want
> or care about having a Type Safe TCL or any language, for that
> matter.

Static typing isn't just for compilers; sometimes it's for
programmers, too.

When professional programmers are writing programs, an important part
of what we're doing is communicating the intent to humans, because at
some point, humans are going to be reading and modifying the code, and
their time is much more expensive than computer time.

Sometimes it's useful to make explicit the types of variables---not
just "int" or "string" (which is the kind of thing that helps
compilers), but "length" and "screen position" and "age", which help
humans much more than compilers. It helps catch silly errors, early
(even in code which may never be exercised in your test suite), and
it's useful in understanding the code.

It's certainly possible to do things differently, and one can argue
that Tcl's typing system is appropriate for its uses, just as one can
argue that Lisp's is (Tcl's is similar, but subtly different to,
Lisp's). To argue that type-safety is purely for the benefit of
compilers is silly, though.

lvi...@yahoo.com

unread,
Jul 9, 2002, 8:53:24 AM7/9/02
to

According to rick horwitz <whee...@att.net>:
:So please tell me again about the business value of why I would want

:or care about having a Type Safe TCL or any language, for that matter.

Let's see - first thing I can think of is bug control - someone passing
to a class strings when the underlying functions are going to crap out,
or even worse generate wrong info, because they expect floating point
or integers, or whatever.

I've seen several approaches to this sort of problem.

1. Ignore it, saying things like "oh, no one would ever pass the wrong argument"
2. Pass the buck, saying things like "let the caller worry about that"
3. Code for it, writing the same edits over and over and over.
4. Abstract it - such as what was done by GPS or some other method.
--
Support Internet Radio <URL: http://saveinternetradio.org/ >
Join Tcl'2002 in Vancouver http://www.tcl.tk/community/tcl2002/
Even if explicitly stated to the contrary, nothing in this posting
should be construed as representing my employer's opinions.

Kristoffer Lawson

unread,
Jul 9, 2002, 9:28:50 AM7/9/02
to
Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:
>
> When professional programmers are writing programs, an important part
> of what we're doing is communicating the intent to humans, because at
> some point, humans are going to be reading and modifying the code, and
> their time is much more expensive than computer time.

There is a balance. It can also get in the way of things. I've been coding
a lot of Java recently and more often than never I have to read through
API documents and fiddle around with the code simply because I want to
pass some data to a method. So it does work both ways.

In any case I would say just using "int", "string" and "double" -style
types would be severely limiting and not really fit in well with the intent
of using types as a form of communication. It would be much better to use
a generic framework for restricting variables to specified values and
ranges, so errors are caught as soon as they happen and we can effectively
communicate the true purpose of the variable. Variable traces would
seem to cater for this need quite nicely.

--
/ http://www.fishpool.com/~setok/

Gerald W. Lester

unread,
Jul 9, 2002, 9:49:51 AM7/9/02
to

Kristoffer Lawson wrote:
>
> Bruce Stephens <bruce+...@cenderis.demon.co.uk> wrote:
> >
> > When professional programmers are writing programs, an important part
> > of what we're doing is communicating the intent to humans, because at
> > some point, humans are going to be reading and modifying the code, and
> > their time is much more expensive than computer time.
>

> ...


>
> In any case I would say just using "int", "string" and "double" -style
> types would be severely limiting and not really fit in well with the intent
> of using types as a form of communication. It would be much better to use
> a generic framework for restricting variables to specified values and
> ranges, so errors are caught as soon as they happen and we can effectively
> communicate the true purpose of the variable.

I agree. Traditional typing is insufficient and mainly designed for
compiler/runtime efficiency. Beside restricting to a range (the range
may have to be expressed in one of many ways), one many times also needs
to restrict to a format (i.e. two decimals). Then the next level of
restrictions is to a unit of measure -- this could be mass or might have
to be kg -- depending on the use in the algorithm.

Lastly of course you need a "amorphous" type, i.e. one that can change
into anything (like Tcl variables today). I'd argue that this should be
the default since it works very well in a large class of programming
problems (as demonstrated by Tcl's current use).

> Variable traces would seem to cater for this need quite nicely.

While this could be used for a prototype installation, I believe the
underlying core would have to change significantly for a production
release. I also don't think we have worked out what "typing" for Tcl
should be.

--
+--------------------------------+---------------------------------------+
| Gerald W. Lester | "The man who fights for his ideals is
|
| Gerald...@cox.net | the man who is alive." -- Cervantes
|
+--------------------------------+---------------------------------------+

Cameron Laird

unread,
Jul 9, 2002, 1:27:30 PM7/9/02
to
In article <myBW8.1175$x51.3...@reader1.news.jippii.net>,
Kristoffer Lawson <se...@gfanrend.fishpool.fi> wrote:
.
[nice thread, with
valuable comments
from all sides]
.

.
>In any case I would say just using "int", "string" and "double" -style
>types would be severely limiting and not really fit in well with the intent
>of using types as a form of communication. It would be much better to use
>a generic framework for restricting variables to specified values and
>ranges, so errors are caught as soon as they happen and we can effectively
>communicate the true purpose of the variable. Variable traces would
>seem to cater for this need quite nicely.
.
.
.
Oh, yes. It's important to emphasize that the world
of typing is far larger than C's pathetic int-char-
double basis. For examples of how good this can get,
see Eiffel, Haskell, Ada (!), and so on.
--

Cameron Laird <Cam...@Lairds.com>
Business: http://www.Phaseit.net
Personal: http://starbase.neosoft.com/~claird/home.html

Marc Spitzer

unread,
Jul 9, 2002, 1:05:35 PM7/9/02
to
In article <EE9A74617DD62C52.38D20BE6...@lp.airnews.net>

, Cameron Laird wrote:
> In article <myBW8.1175$x51.3...@reader1.news.jippii.net>,
> Kristoffer Lawson <se...@gfanrend.fishpool.fi> wrote:
> .
> [nice thread, with
> valuable comments
> from all sides]
> .
> .
>>In any case I would say just using "int", "string" and "double" -style
>>types would be severely limiting and not really fit in well with the intent
>>of using types as a form of communication. It would be much better to use
>>a generic framework for restricting variables to specified values and
>>ranges, so errors are caught as soon as they happen and we can effectively
>>communicate the true purpose of the variable. Variable traces would
>>seem to cater for this need quite nicely.
> .
> .
> .
> Oh, yes. It's important to emphasize that the world
> of typing is far larger than C's pathetic int-char-
> double basis. For examples of how good this can get,
> see Eiffel, Haskell, Ada (!), and so on.

If you want a good type checking system look at common lisp.
you get strict run time type checking and you have the ability
to put type declarations in after the program works as an aide
for the compiler in optimization. And a rich set of types to
work with.

marc

Donald Arseneau

unread,
Jul 9, 2002, 8:29:54 PM7/9/02
to
whee...@att.net (rick horwitz) writes:

> Today, there is no rational, economical reason to waste one key stroke
> on such an effort.

Typed variables are still useful because they allow catching of
programming errors. The classic Tcl example is
if { $a == $b } {
where Tcl will do numeric or string comparison. That said,
introducing variable types to Tcl is a Major change, as it affects
how many commands operate.

I agree that specifying a variable to be list-only would be
useful.

Aside from types, the mere declaration of variables is a big
improvement for bug finding! Perhaps only:

global hi there
local foo bar

so that [set bat xxx] would be detected as a (typographic) error.

Donald Arseneau as...@triumf.ca

Don Porter

unread,
Jul 9, 2002, 11:28:18 PM7/9/02
to
Donald Arseneau wrote:
> Aside from types, the mere declaration of variables is a big
> improvement for bug finding!

Note that as you do more of your Tcl programming with namespaces, you
will find that you are doing more "variable declaration" just because
you need to to precisely define what the program does. For example,

namespace eval foo {
set x 1
}

At this point, what variable have you set to the value 1 ? The answer
is it is impossible to know without knowing the original state of the
interpreter. If a variable foo::x already existed, then it is now 1.
If no such variable existed, and a variable ::x existed, then ::x is
now 1, and foo::x still does not exist. If neither exists, then
foo::x is created with value 1.

Since you really don't want code behaviot depending on an unknown
initial state, the safer way to program this is:

namespace eval foo {
variable x 1
}

...which looks a lot like "variable declaration".

--
| Don Porter Mathematical and Computational Sciences Division |
| donald...@nist.gov Information Technology Laboratory |
| http://math.nist.gov/~DPorter/ NIST |
|______________________________________________________________________|

Darren New

unread,
Jul 9, 2002, 11:38:33 PM7/9/02
to
Donald Arseneau wrote:
> I agree that specifying a variable to be list-only would be
> useful.

Just what would such a declaration mean? Where would it disallow the use of
a particular value or variable?

--
Darren New
San Diego, CA, USA (PST). Cryptokeys on demand.
** http://home.san.rr.com/dnew/DNResume.html **
** http://images.fbrtech.com/dnew/ **

Proud to live in a country where "fashionable"

is denim, "stone-washed" faded, with rips.

Donald Arseneau

unread,
Jul 10, 2002, 1:45:31 AM7/10/02
to
Darren New <dn...@san.rr.com> writes:

> Donald Arseneau wrote:
> > I agree that specifying a variable to be list-only would be
> > useful.
>
> Just what would such a declaration mean? Where would it disallow the use of
> a particular value or variable?

Let's see.... it was Bruce Stephens who brought it up, and I
envision it like: a variable declared to be a list could only
be assigned clean-list values, as those produced by [list ].
String-manipulation commands (string, append) would give an
error on receiving a value from such a variable. A string-only
variable could not be assigned the result of a [list] or [l...]
command, and could not be used as an argument of a [list] (etc)
or [expr] command.

Of course I wouldn't want such single-type variables to be required,
or even be the default!

Such rejection of the argument looks like a vast internal change,
whereby the value must carry some tag to tell if it came out of
a typed variable, or was produced some other way, so that

set strvar {foo bar {baz boo}}
lreplace $strvar 1 1 x

would give an error whereas

lreplace [list foo bar {baz boo}] 1 1 x

would not. (I doubt that the usefulness of the facility would
make the implementation worthwhile.)

Donald Arseneau as...@triumf.ca

Kristoffer Lawson

unread,
Jul 10, 2002, 7:00:33 AM7/10/02
to
Donald Arseneau <as...@triumf.ca> wrote:
>
> global hi there
> local foo bar
>
> so that [set bat xxx] would be detected as a (typographic) error.

I would disagree with that. Generally those are the kinds of errors which
are detected very easily and I find it a huge nuisance to declare variables
before using them. Maybe some kind of optional system for people who really
really want it (it's not too difficult to do yourself in pure Tcl...),
but I wouldn't want to change my coding habits on that issue.

--
/ http://www.fishpool.com/~setok/

Tom W

unread,
Jul 10, 2002, 8:18:34 AM7/10/02
to
"Donald Arseneau" <as...@triumf.ca> wrote in message
news:yfielec...@triumf.ca...

Rather than forcing a list to be a list, what would really be useful to me
is a command to denote if a passed in argument (or any other variable for
that matter) has a valid list rep (islist?). There are cases where an
argument may be a single string or a list of strings and there isn't any way
to tell the difference when handling the argment (the string can contain
spaces so an llengh on it will listify it). The only way around it is to
force the single string to a [list $string] when calling the procedure.

Tom Wilkason


Donal K. Fellows

unread,
Jul 10, 2002, 11:05:58 AM7/10/02
to
Donald Arseneau wrote:
> Such rejection of the argument looks like a vast internal change,
> whereby the value must carry some tag to tell if it came out of
> a typed variable, or was produced some other way[...]

That's not that hard to actually implement (though a fair bit of work to go
through the core and make sure that it's actually doing the right thing at the
right point.) Just have another Tcl_ObjType that is just used for values that
have been "constructued" properly but which is otherwise identical to the normal
list type. I'm just not sure that it would work as well as some people seem to
think it does.

-- A large ASCII art .sig is the Usenet equivalent of walking around in
public with your asscrack sticking out past the top of your sweatpants.
You be the judge. -- Mike Hoye <mh...@prince.carleton.ca>

0 new messages