I have searched for lappend $var1 $var2, but don't find any exact answer, how it will be executed.
% set a {a b c}
a b c
% set b {d e}
d e
% puts [lappend $c $b]
can't read "c": no such variable >>> here it throws error like variable not exist
% puts [lappend $a $b]
{d e} >>> here it doesn't throw any error, can someone explain it and how to print the value of $a, if $a is a new variable
% puts $$A
can't read "A": no such variable
% puts $$a
$a b c
% puts ${$a}
can't read "$a": no such variable
Tcl's got a two level syntax that it applies rigorously to everything. The first level is the Tcl generic syntax, which takes:
lappend $var1 $var2
and parses it out to three words: lappend, a word obtained by reading the variable var1, and a word obtained by reading the variable var2.
Then Tcl dispatches to the command named by the first word (lappend, a Tcl built-in) which applies command syntax handling. In the case of lappend, it's pretty simple: the first argument names a variable and the second and subsequent arguments are words to append to the list in the named variable.
In your case, the first argument that names a variable is obtained by reading another variable (var1) and the value to append to the list is coming from a variable (var2); a name like a b c d e is a legal variable name in Tcl, but it's really awkward to use. And the chance is very high that you don't want to write that: putting variable names in a variable is usually an indicator of confusing code. You can do it, but you hardly ever want to do it (except when you're using the variable name with upvar). You probably really meant to write:
lappend var1 $var2
Tcl is very exact about the distinction between variable names and variable contents. The $ is not decorative! It's there to say “read this variable, right now”, and $var1 is virtually equivalent to [set var1] in semantic terms. (The $ shorthand was later, a Tcl 2.0 feature from way back in the day!)
Tcl also doesn't allow double-dereferencing with $$vrbl. In the rare cases you need it, you do [set $vrbl]. And if you do that, you probably should immediately see if you can use an array instead as that's typically a better choice…
lappend's first parameter is a variable name, not a value. Therefore, in general, it should be:
lappend var1 $var2
where both var1 and var2 are list variables. See the Tcl lappend man page for more details.
Related
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".
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
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.
set_dont_use [get_lib_cells */*CKGT*0P*] -power
set_dont_use [get_lib_cells */*CKTT*0P*] -setup
The above is a text file.
I Want to store */CKGTOP* and */CKTTOP* in to a variable this is the programme which a person helped me with
set f [open theScript.tcl]
# Even with 10 million lines, modern computers will chew through it rapidly
set lines [split [read $f] "\n"]
close $f
# This RE will match the sample lines you've told us about; it might need tuning
# for other inputs (and knowing what's best is part of the art of RE writing)
set RE {^set_dont_use \[get_lib_cells ([\w*/]+)\] -\w+$}
foreach line $lines {
if {[regexp $RE $line -> term]} {
# At this point, the part you want is assigned to $term
puts "FOUND: $term"
}
}
My question is if more than one cells like for example
set_dont_use [get_lib_cells */*CKGT*0P* */*CKOU*TR* /*....] -power
set_dont_use [get_lib_cells */*CKGT*WP* */*CKOU*LR* /*....] -setup
then the above script isn't helping me to store the these "n" number cells in the variable known as term
Could any of u people help me
Thanking you ahead in time
I would go with
proc get_lib_cells args {
global term
lappend term {*}$args
}
proc unknown args {}
and then just
source theScript.tcl
in a shell that doesn't have the module you are using loaded, and thus doesn't know any of these non-standard commands.
By setting unknown to do nothing, other commands in the script will just be passed over.
Note that redefining unknownimpairs Tcl's ability to automatically load some processes, so don't keep using that interpreter after this.
Documentation:
global,
lappend,
proc,
unknown,
{*} (syntax)
Your coding seems like the Synopsys syntax, meaning - it shouldn't work the way you wrote it, I'd expect curly braces:
set_dont_use [get_lib_cells {*/*CKGT*0P* */*CKOU*TR* /*....}] -power
moreover, the \w doesn't catch the *,/ (see this).
If I were you, I'd go for set RE {^set_dont_use \[get_lib_cells \{?([\S*]+ )+\}?\] -\w+$} and treat the resulting pattern match as a list.
Edit:
see this:
% regexp {^set_dont_use [get_lib_cells {?(\S+) ?}?]} $line -> match
1
% echo $match
*/*CKGT*0P*
If you have more than one item in your line, add another parentheses inside the curly braces:
regexp {^set_dont_use \[get_lib_cells \{?(\S+) ?(\S+)?\}?\]} $l -> m1 m2
ect.
Another Edit
take a look at this, just in case you want multiple matches with the same single pattern, but than, instead of \S+, you should try something that looks like this: [A-Za-z\/\*]
I just tried the following in tclsh:
proc pp {$ag} { puts hi}
pp whatever
To my surprise, this works fine! I had expected a syntax error because the proc argument is a variable. But it seems tcl takes it fine.
Then I experimented:
proc pp {$ag} { puts "hi $ag"}
pp whatever
and
proc pp {$ag} { puts "hi ${$ag}"}
pp whatever
I got error, can't read "ag": no such variable.
This makes me wondering, can proc argument be variable? If not, why not error out in the first script?
The first case works because you never use the parameter to pp.
When you invoke the proc command, the text of the invocation is evaluated just like in any other command invocation. In all the above cases, the third argument (which will become the argument list of the pp command) is is wrapped in braces, which means it won't be evaluated as a variable but as a string of three characters: "$ag" (i.e. the dollar sign is just a regular character here). This is not an error, and does work, just not the way you seem to expect it to.
It's a bit tricky to get the value of the parameter $ag, though. This works:
proc pp {$ag} {puts "hi [set {$ag}]"}
The dollar notation is actually just syntactic sugar for the unary set command. Sometimes the dollar notation won't work, and you need to fall back to an explicit set.
This does work too, though:
proc pp {$ag} {puts "hi ${$ag}"}
So, in your invocations, the third argument to proc isn't really a variable evaluation, it just looks like one. You can of course use an actual variable evaluation in the invocation of proc:
set foo {bar baz}
proc qux $foo {puts $bar ; puts $baz}
qux abc def
# => abc
# => def
What the Tcl interpreter really sees here is:
proc qux {bar baz} {puts $bar ; puts $baz}
Or you can go really crazy:
set foa {proc qux}
set fob {bar}
lappend fob baz
set foc {puts $bar}
set fod "puts \$baz"
{*}$foa $fob [join [list $foc $fod] { ; }]
Which amounts to the same thing as the previous invocation of proc. (If you don't believe me, try list {*}$foa $fob [join [list $foc $fod] { ; }])
This example just looks (and is) weird, but many times it's actually useful to construct new commands within your program, and in those cases it's really nice that the text used in the invocation of proc, like with any other command, is simply text that the evaluation rules of Tcl can be applied to. You can use any kinds of string or list operations on it and join up pieces of text from various sources, even user input (if you can trust it).
Documentation: Tcl evaluation rules including $ and {*}, join, lappend, list, proc, puts, set
I am a newbie in TCL Programming. I was having confusion about curly braces, answer to this question tcl curly braces cleared most of my doubts.
I can understand $var, {var}, and {$var}, But recently I came across another use of curly braces, ${var}. How is this interpreted by TCL?
I have seen this is used when accessing variables in namespaces when namespaces name is in variable.
for example:
set x myNamespace ;#myNamespace is name of namespace
puts [set ${x}::var1] ;#var1 is variable in the namespace
It gives error when you don't use curly braces around 'x'.
And I also don't understand the difference between {a b c} and [list a b c], what is the difference in result of interpretation of these two commands by TCL interpretation.
elaborated explanation would be highly appreciated.
See rule 8 of the manual. It allows you to have variable names that might get mis-interpreted. For instance:
% set dotted.name 1
1
% puts $dotted.name
can't read "dotted": no such variable
% puts ${dotted.name}
1
Read section 8 carefully as it actually explains all this quite explicitly.
Update to answer edited question
In the example you provide using a namespace name in a variable you must consider section 8 part 1: a variable name includes letters, digits, underscores and namespace separators. This means that x::var1 is a valid variable name. So $x::var1 will attempt to dereference the var1 variable in the x namespace. As this is not what you meant, you must dereference your x variable separately. There are two ways to do this. You can either use the set command or the dollar operator.
set x myNamespace
puts [set ${x}::var1]
puts [set [set x]::var1]
The two puts statements are equivalent here with the second version showing an explicit separate pass to obtain the value of the x variable which is then substituted into the expression for the outer set command. The same occurs in the first version but just uses the grouping operator to restrict the effect of the dollar to the x variable name.
I'm playing around with Tcl and have found several scenarios where [list a b c] is interchangeable with {a b c}. What is the preferred method, and where does [list a b c] fail to match the behavior of {a b c}?
% set lista [list a b c]
a b c
% set listb {a b c}
a b c
% set b {1 2 3}
1 2 3
% set lista [list a $b c]
a {1 2 3} c
% set listb {a $b c}
a $b c
When you are building a list using literals, the two forms are equivalent. When you are using variables, the [list ...] form will expand the variable before placing it in the string and the {...} form will not.
Essentially, {...} treats whatever is inside of it as a single, continuous string; the special character $ is never interpreted. The [list ...] statement takes its arguments and concatenates them together, separated by spaces. Therefore, if the items you are working with are string literals and do not contain anything that needs to be interpreted, then the two forms are the same.
For literals, they're identical in all functional respects (other than that the straight literal form is slightly faster, of course). For non-literals, they're obviously doing different things (as bta says).
However, there's more to it than that. Let's dive deeper!
There are cases where you do not want to use the {…} or the "…" forms, and that's exactly when working with certain non-literals. In particular, if you are using tcom or Tcl/Java (i.e., Jacl or TclBlend) then you will be working with objects that do not obey Tcl's semantics properly. In particular, you'll have “fragile” objects attached to some of the values; if the Tcl_Obj containing the reference to the value has its type changed (“shimmered” in Tcl parlance) then the reference to the underlying COM or Java object will be irretrievably dropped and the garbage collector will delete the object before you're finished with it. Using the [list …] form to build lists (and list operations like lindex to retrieve) will ensure that these fragile internal representations are maintained correctly until you no longer need them.
For normal Tcl values, including those produced by most extension packages, you don't need to worry about this other than to note that using the non-lossy operations is also faster. If you want your code to be quick (who doesn't?) then [list] is your friend even when it is not necessary (which it often is).
The other case you want to pay attention to is when producing callbacks.
Often you want to do callbacks where some values are known at the point when the callback is created, and not otherwise stored in some variable that exists when the callback is executed. (I do this a lot with after, fileevent and trace, but there are lots of places where this is done.) Callback scripts that are created with list (or some other list-producing command) are faster than all the other alternatives because the Tcl script evaluation engine can prove that they have no substitutions and go directly to feeding the list elements into the command dispatcher. This is quite an advantage when you're just passing values to a procedure, which is considered good practice for callbacks.