Version 62 of Why is TCL syntax so weird

Updated 2005-12-10 19:20:49

Question: Why is Tcl syntax so weird?

Answer: it's not. Everything else is weird.

Okay, you might not buy this. I don't either, completely. The point is, though, that Tcl may be the only language I've ever heard of where there are no special/built-in functions.

VL 14 jun 2003: Hmmm, how about Prolog, LISP-dialects, etc. etc. etc.? Or am I missing your point here? I suppose that what is a language and what is the "standard library" of that language are a bit of a grey area.

pdm good point. I have mostly used procedural rather than functional languages. From my college days, I vaguely remember the syntax being simpler in prolog or lisp. Which actually made it harder for me to think that way. Maybe I was poisoned by an early exposure to BASIC :)

There is no Pascal println that allows variable arguments when every other function has a fixed number of arguments.

LV On the other hand, variable arguments are just fine in Tcl. It is just that the default output command, puts, requires one string as its output format. If someone wanted to write something like println, they could write a proc that would collect its arguments, hand them to format and then to puts.

In fact, you could have something like this:

 proc println { args } { puts [join $args {}] }

so that you coded, in tcl,

 set a "STring 1"
 set b "string 2"
 println $a $b [list This is a list]

pdm This shows one of the strengths of Tcl: you can make it do almost anything you want. Sometimes it isn't obvious, especially if you are stuck in Pascal-think. I find myself having to think harder because I'm trying to force C code into Tcl. If I just do it the Tcl way it can be much easier :)


There is no C for that has three arguments separated by semi-colons where each argument can have any number of operations separated by commas.

LV There are, however, several looping constructs that you can do looping - for instance, where in C you would write:

 for (i=0;i<10;i++) {
     printf("x is %s\n", x);
 }

in tcl you would write:

 for { set x 0 } {$x<10} { incr x } {
   puts "x is $x"
 }

glennj: the tcl for is just like the C for -- the start and next parameters are arbitrary script bodies. Not that this is encouraged, but you can do:

 # add up the numbers from 0 to 9
 for {set sum 0; set counter 0} {$counter < 10} {incr sum $counter; incr counter} {}
 puts $sum ;# ==> 45

pdm You're right, of course. What I meant was that the rules for Pascal or C are not simple and consistent. The rules for TCL are. Since I have "baggage" of C, Perl, etc, it seems weird at first.

It is real simple: a command followed by zero or more arguments. That's it.

Unfortunately, that means a simple assignment statement has to be written funny. Trying to say

    a = "12345"

would try to run the a command, which probably doesn't exist. If you try to use Perl-like syntax, you might try

   $a = "12345"

which would also fail because the parser would try to get the value of a variable called a and treat that as the command name (see Substituting Command Names).

LV Unless you play games with Salt and Sugar, which allows you to write assignments in more unusual ways.

So, TCL has a set command that takes two arguments: the first is the name of a variable and the second is the value.

I just think it's weird because everything else has special cases.

LV other languages use set - csh for instance, which apparently provides a number of influences on Tcl. The original BASIC required a syntax like:

let a = 1

which is even worse!

Arjen Markus I can add to this, that formally and semantically the use of an equal sign, as it appears in many programming languages, is claimed to be a bad move by some. The reason is, that in a mathematical sense, an equal sign simply means that something is equal to something else.

In descriptions of algorithms one frequently sees

   variable <- value

to distinguish it from a check for equality.

Still other languages, Eiffel for one, use this

   variable := value

So, again, the fact that Tcl does not adhere to the commonly found constructs does not mean that it is weird.

As a personal note, the first time I tried to find man pages about Tcl I was very disappointed to find only a description of the basic syntax - nothing about if, for or whatever.

DKF - Note that in some BASIC systems (ZX80, ZX81 and ZXSpectrum in all its variants, though some came with variations that did not work this way IIRC) the LET keyword was inserted by pressing a single key, which made its use much less of a chore (though the platform was definitely fairly bizarre.) Lars H: That comment makes me remember when I wrote (in BASIC) a combined assembler/editor for the ZX Spectrum. The entire assembler program was stored in a string (now that we know that everything is a string, this is obvious, but back then it wasn't). And "n" is still my "foo loop variable", because "NEXT n" was just a matter of pressing the "n" key twice.


LV As a personal note in reply to the message about disappointment in the man pages - man pages were not, at least initially, intended as tutorials to the use of the subcommands, but simple reference items describing what a command's subcommands, etc. were.

It was, and to the most part still is, expected that sites like this one, books, etc. would provide tutorial level information.

If there is reference material that you feel is seriously lacking, there are several alternatives.

  1. We have a variety of pages on this wiki, at least one per tcl command, on which questions, and subsequently answers to those questions, can be placed.
  2. http://tcl.sf.net/ and the tk sibling have a feature request option, where one can request changes. These may, or may not, be implemented, but at least they won't be lost.
  3. At that same site, there is a patch manager, where people can submit patches to broken behavior. If you feel the man pages are broken, consider fixing at least one of them, and submitting it as an example of proper documentation.

As another note, there is a really, really weird construct in C that is explicitly allowed, if my memory serves, it is called the Duffy construct and consists of an unexpected mixture of switch and case statements. Unfortunately, both my memory and my library do not serve at this moment. The reason it is allowed by the standard is merely that it optimizes certain operations.

pdm For the compiler/language-designer purists, that brings up an interesting question: when is it okay to "break" or "abuse" the syntax of a language in the name of faster runtime? My guess? The TCL and C designers answered this question "whenever a clever user/developer can figure out how" and "whenever needed", respectively :)

EE: Duffs Device [L1 ] is an example of loop unrolling, but the reason it is allowed by the standard is not "merely that it optimizes certain operations", but rather because it does not violate any syntax rules or constraints.

AMG: I did a bit of loop unrolling here on the wiki. See my contribution to Matrix Multiplication. The Tcl script uses nested [for] loops to generate a single, long line of Tcl script that accomplishes matrix multiplication with no run-time loops. Alas, I wasn't responsible enough to profile before I optimized, or else I'd be able to say whether or not this is actually worth anything.

In a sense, I embed a mini-compiler in my code. This ties in with the meta-language comment further down this page.


RS Call it weird or not, most "algebraic" languages like C have mathematical syntax (infix operators +-*/, parens etc.) mixed into another with keywords, braces etc. C++ goes so far as to allow overloading operators, but you couldn't define new operators or new arities (for instance, a unary /). Math syntax is of course needed as computers often compute. In Tcl, most math is concentrated into the expr command, leaving the rest of the language as clear and pure as it is. But even in expr, using the general rules of string manipulation we can do more things than are possible in C or other algebraic languages:

 foreach operator {+ - * /} {
   puts "3 $operator 3 = [expr 3 $operator 3]"
 }

The expr parser would not accept the operator substitution, so in cases like this, leave the argument to expr unbraced, so you can enjoy the full freedom of Tcl.

DKF - SML permits declaration of new operators. Overloading existing ones requires a language extension though.

AM Fortran (90 and later) allows the definition of new unary and binary operators, it also allows extending the existing operators for new data types (but you can not redefine the meaning of summing two integers for instance - for obvious and wise reasons).


There are some weird items in the parsing of Tcl like:

 set x a"b
 set y $x.b
 set x.b c
 puts $y ; # is a"b.b

but on the whole the language is simple. But the parser is just a small part of the story after the parser gets done with the source each command has almost complete freedom to add more levels of substutions, evaulation or what ever.

I don't think this "strangeness" is too bad because I picked it up so easy but I can understand that others may be turned off by it.

;^)

Earl Johnson


This is a response to Earl's remarks above: I think this "strangeness" is in the eye of the beholder. When I read this code it all looks right to me. Before I knew tcl I it would have told me that tcl is different. I'd expect it to be different, after all it is a different language. The question I needed to resolve is "Is it worth it to learn tcl?" since it's different. tk is what made it worthwhile for me, and I suspect it did for others. I didn't learn perl because it was different, didn't have a gui, and seemed to carry over a lot of the ills of other early shell languages. bob


TV What a strange page title..

I guess people have a certain structure or language in mind when they program, or maybe certain concepts, which could be either like comparing english and german, or maybe like comparing logo and C++. Tcl is of course simple in its fundamental form while it has the power to do most known programming things without too much effort.

But if your mindset is to be grounded in pascal's formal definitions or your fingers just won't move without objects of your desire, you probably weren't raised on tcl or scripting.


Tcl syntax *is* weird, at least when compared to other (popular) languages. It's weird in that it doesn't have much syntax. Tcl uses semantics where most languages would use syntax: variable assignment, control flow and command definition are all done through the same syntax. Whereas most languages have a list of keywords and a BNR grammar for these sort of operations, Tcl has default commands and even these can be redefined.

I think of Tcl more as a meta-language, and every program winds up being a custom and application specific language. It's similiar to Lisp and Forth in that regard, but (IMO) easier to read than either of those.

And that is weird to anybody comming from a C++/Perl/Java or even Python background. In my experience, lisp-niks get it right away (but dislike Tcl for the syntax it does have).

pdm... and for the heretical under-use of parentheses :)

Seriously, though, this last comment puts it very well. Thank you, anonymous contributor!


alove 10 dec 2005 The reason this issue keeps coming up is because other languages all the way back to BASIC and including Perl and Python, have very user-friendly and intuitive syntax for math expressions, for example:

 Python: c = a + b
 Perl:   $c = $a + $b;
 BASIC:  c = a + b
 PHP:    $c = $a + $b
 Ruby:   c = a + b
 TCL:    set c [expr {$a + $b}]]     - can you feel the difference?

Considering how basic and fundamental arithmetic expressions are, I'm amazed that no one has fixed this yet. User friendliness takes precedence over abstract ideas like the Dekalogue. If you have to make an exception to make arithmetic expressions look pretty, as in every other interpreted language, then I think you should.


EMJ 10 dec 2005 - I was going to correct the Tcl line above, then I thought it was better to have a visible correction:

 Tcl:    set c [expr $a + $b]

The original works (except for the extra right bracket), but the braces are unnecessary, so why put them in? Or why not put something unnecessary in the other languages?

  • aricb, with apologies for interrupting EMJ: put in those braces for all the reasons at Brace your expr-essions. Those few extra keystrokes will pay big dividends--and you'll sleep better at night :)
  • emj, apology accepted, I'm prepared to believe all the reasons, but would adding bits improve the behaviour of any of the other languages? I don't know, but when making comparisons you need to be on the same level.

Everything is a string, and every line is a command - that's Tcl, it's clean, simple, and consistent. Of course, since it is flexible as well, you could just add a bit of logic to unknown to say the if the second argument is just an equals sign, convert the whole thing to set ... [expr ...]. Naive users may think it's special syntax, but it won't be. And I won't do it, because I don't want it.

Changing the foundations of Tcl to follow a fashion, or to be like some other language, is a very slippery slope.

jcw - That last comment can be a two-edged sword. (emj I do not want to take a two edged sword doown a slippery slope :) ) Tcl is also very adept at embedding domain-specific notations - the "expr" command itself is an example of that. There are ways to stay with the current rules, yet abbreviate:

   $ {c = a + b}

This requires a command "$" which parses its arg, a bit like expr but treating names as variable or array references.

emj - Embed what you like, no argument there.

The other notational inconvenience is list indexing and such:

   set x [lindex $data 12]
   set y [lrange $data 1 end-1

If array index notation were allowed for lists, it could be written as:

   $ {x = data(12)}
   $ {y = data(1,-1)}

All without changing anything in Tcl. As an extension which would work with any Tcl >= 8.2

emj - but what will happen if you do

   parray data

to a list?


Category Syntax