I am just going to use Perl as a comparison here:
$foo = 5;
print $foo;
sets the variable $foo
to 5, and then prints the contents of the variable (notice that $foo
is always accessed as $foo
).
In Tcl:
set foo 5
puts $foo
does the same thing as the Perl counterpart.
Why doesn't Tcl set variables with the "$", but need a "$" to access a variable?
Why is this true for procedures too (e.g.proc bar {spam eggs} {...}
)?
To me, the Tcl code looks like this (in pseudocode):
"foo" = 5 # Setting a string?
puts $foo # "$foo" is not defined.
(my comments only reflect what appears to be happening, not what is happening).
Another point I want to add is the clarity of this:
set foo foo
Yeah, I could always do set foo "foo"
, but isn't set $foo foo
more consistent?
From what I know, "foo" can be a variable or a string, depending on the situation, as seen in my last example (set foo foo
= set var string
), but I don't get this syntax (maybe because I'm used to Python...)
I think the original Tcl only had the set
command, so the only way to fetch the contents of a variable "foo" was calling set foo
. But as Tcl progressed into the domain of general-purpose scripting languages (recall that Tcl was envisioned as being an embeddable language where you use a thin layer of Tcl over compilcated components written in C, so one wasn't expected to use lots of variables), it was deemed that that $varname syntactic sugar is useful and so it was added.
In other words, Tcl does not use "$" in the same way as Perl does, in which the "$" means "interpret whatever follows as a scalar", neither does "$" in Tcl denote a variable. Instead it merely a syntactic sugar for "give me the value of a variable whose name is given by the immediately following word".
Well, I decided to comment upon the last bits of the original question, but the comment overgrown the limit, and so I'll post it as an answer even while it does not address the indicated question. I'll hope it will clarify some things which appear to be implied in the question though.
A note about the consistency of set foo foo
: you're approaching Tcl in a somewhat wrong way. Tcl is radically different from Perl or Python in that it has almost no syntax (really, like LISPs). "set foo foo" is not a syntax for setting a variable as it could be in another language, it's a call to a command currently available under the name "set" and passing it two arguments--"foo" and "foo"; it's whatever is registered under the "set" command name decides what is the name of a variable and what is the value to set it to. Likewise, looping commands are not syntax, they are commands. Really, it worth stopping here and think that
for {set i 0} {$i < 10} {incr i} {
puts $i
}
is not merely a whimsical language designer's idea to go with curly braces instead or "normal" parentheses like in C. Instead, here the Tcl parser parses out five words, takes the first one to be the name of a command, looks it up, and passes it the rest of the words; it's the implementation of for
which interprets those {set i 0}
, {$i < 0}
etc and executes them appropriately. The syntax is there only to specify how there words are parsed out from the input stream of characters. And since everything is implemented using commands, your commands are able to behave no different from builtin ones; this allows you to create custom commands as powerful as for
or switch
(something akin to macros in LISPs). In another language this would be equal to the ability to extend sytnax in arbitrary ways.
When this idea "clicks" , Tcl will no longer appear to be weird.
And it's this property which makes Tcl so easily extensible (and embeddable): because the commands you provide from your C side behave absolutely the same as all builtin commands.
Think of $foo
as meaning the value of the variable foo
, ie the text which it was last set to. Now, if foo
currently has the value x
, set $foo y
means set x y
, which is clearly not what is meant. It is actually more consistent than other languages, where foo
sometimes means the value of the variable foo
, and sometimes the variable foo
itself.
The real answer, if any, could only be given by the original language designers (John Ousterhout) I guess. So the rest is open to speculation or (educated) guesses. There is some history on TCL available here, but upon a quick reading there is no direct answer there.
Why doesn't Tcl set variables with the "$", but need a "$" to access a
variable?
My take would be that this way it is closer aligned to (UNIX) shell languages. TCL was conceived at Berkeley, arguably a strong UNIX (or BSD for that matter) environment.
UNIX shells also don't use the $ sign (or equivalent for the respective shell) when declaring or assigning variables, but require it when referencing it:
# bourn shell like shells (sh, bash, ksh, ...)
foo=foo
echo "The value of the variable foo is $foo."
Even the unholy Windows CMD.EXE processor uses a comparable method (although I guess that was not what TCL designers had in mind ;-)
REM DOS COMMAND.COM / Windows CMD.EXE
set foo=foo
echo The value of the variable is %foo%.
Also, "string values" (although shells are notoriously weak typed) don't generally require quotes if there are now spaces in the string value.
Yeah, I could always do set foo "foo", but isn't set $foo foo more
consistent?
Well, it wasn't for the TCL designers/creators ;-)
EDIT I almost forgot: You could actually do the following in TCL:
set foo bar
set $foo something
puts $bar
This will actually output "something". The second line actually sets the string "something" to the value of the variable "foo", thus setting a variable named "bar" and assigning it the value "something".