Reputation: 25
I'm learning about Tcl just now. I've seen just a bit of it, I see for instance to create a variable (and initialize it) you can do
set varname value
I am familiarizing with the fact that basically everything is a string, such as "value" above, but "varname" gets kind of a special treatment I guess because of the "set" built-in function, so varname is not interpreted as a string but rather as a name. I can later on access the value with $varname, and this is fine to me, it is used to specify varname is not to be considered as a string. I'm now reading about lists and a couple commands make me a bit confused
set colors {"aqua" "maroon" "cyan"}
puts "list length is [llength $colors]"
lappend colors "purple"
So clearly "lappend" is another one of such functions like set that can interpret the first argument as a name and not a string, but then why didn't they make it llength the same (no need for $)?
I'm thinking that it's just a convention that, in general, when you "read" a variable you need the $ while you don't for "writing".
Upvotes: 0
Views: 53
Reputation: 246932
A different look at the question: what Tcl commands are appropriate for list literals?
It's valid to count the elements of a list literal:
llength {my dog has fleas}
But it doesn't make sense to append a new element to a literal
lappend {my dog has fleas} and ticks
(That is actually valid Tcl, but it sets the odd variable ${my dog has fleas}
)
this is more sensible:
set mydog {my dog has fleas}
lappend mydog and ticks
Upvotes: 2
Reputation: 137627
Names are strings. Or rather a string is a name because it is used as a name. And $
in Tcl means “read this variable right now”, unlike in some other languages where it really means “here is a variable name”.
The $blah
syntax for reading from a variable is convenient syntax that approximately stands in for doing [set blah]
(with just one argument). For simple names, they become the same bytecode, but the $…
form doesn't handle all the weird edge cases (usually with generated names) that the other one does. If a command (such as set
, lappend
, unset
or incr
) takes a variable name, it's because it is going to write to that variable and it will typically be documented to take a varName (variable name, of course) or something like that. Things that just read the value (e.g., llength
or lindex
) will take the value directly and not the name of a variable, and it is up to the caller to provide the value using whatever they want, perhaps $blah
or [call something]
.
In particular, if you have:
proc ListRangeBy {from to {by 1}} {
set result {}
for {set x $from} {$x <= $to} {incr x $by} {
lappend result $x
}
return $result
}
then you can do:
llength [ListRangeBy 3 77 8]
and
set listVar [ListRangeBy 3 77 8]
llength $listVar
and get exactly the same value out of the llength
. The llength
doesn't need to know anything special about what is going on.
Upvotes: 1