Why doesn't Tcl use a dollar sign before varia

2019-01-12 09:57发布

问题:

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...)

回答1:

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".



回答2:

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.



回答3:

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.



回答4:

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".



标签: syntax tcl