A question about namespace in Tcl - namespaces

I have two question about namespace in Tcl.
namespace eval ::dai {
set a 5
set b 10
namespace export *
}
My questions are:
export * - the export will make some variable inside this namespace can be used in other namespace, but what does this export * mean?
Set a 5, should not we use variable a 5? are they the same? some tutorials say inside namespace, we should use variable, what is the difference between variable and set in namespace?

1) As is (supposed to be) logical for Unix users, "*" means "everything available at the moment". It's like when you do rm -f * in a shell, the shell expands "*" and replaces it with a list of all the files present in the current directory. Actually, as namespace manual states you can specify more elaborate patters than simple "*". To learn what that "glob-style" thing mentioned there means read about string match.
2) The question "should not we use..." is incorrect because it depends on what you want to do. If you want to declare a variable located in the namespace, use variable. If you want to set a variable, use set, but bevare that if that variable x is not exist in the namespace yet, Tcl will attempt to find a global variablte with this name, see:
% set x 5
5
% namespace eval foo {
set x 10
}
10
% set x
10
# ^^ observe that the global variable has been assigned
% namespace eval foo {
variable x
set x 20
}
20
% set x
10
# ^^ observe that now `set x 20` found the variable `x` in the namespace and assigned to it
This is explained in the "NAME RESOLUTION" section of the namespace man page.
Note that this behaviour may appear illogical, but it actually matches that of the procedure scope: if you do set foo bar in a procedure body, this means setting the local variable unless you stated otherwise using either global or variable or by using a fully-qualified name (like ::ns::foo).

namespace export only applies to commands (i.e. procs) in the namespace: it registers them as being eligible to be imported into another namespace. For example:
% package require textutil
0.7.1
% textutil::splitx abcdefghij {[aeiou]}
{} bcd fgh j
% splitx abcdefghij {[aeiou]}
invalid command name "splitx"
while evaluating {splitx abcdefghij {[aeiou]}}
% namespace import textutil::*
% splitx abcdefghij {[aeiou]}
{} bcd fgh j

Related

Cannot define namespace variable which was defined globally TCL

I cannot define variables in namespace (in TCL) which was defined previously in global scope. See my example:
xsct% $tcl_version
[8.5]
xsct% set foo 1
1
xsct% $foo
[1]
xsct% namespace eval ns {
set foo 2
set bar 3
}
3
xsct% $::ns::bar
[3]
xsct% $::ns::foo
can't read "::ns::foo": no such variable
xsct%
I have reproduced the issue online: http://tpcg.io/3SIBYG
How can I define variables in namespaces independently from global scope?
I use:
Win10
TCL 8.5 in Xilinx's XSCT TCL console
Always define variables in a namespace with the variable command at least the first time you access them, otherwise you end up with namespace variable resolution rules taking over and making your life unpleasant. They're weird (though actually very similar to how command resolution works) and you virtually never want them, and may get removed in Tcl 9. But until then, you're stuck doing:
namespace eval ns {
variable foo 2
variable bar 3
}
or:
namespace eval ns {
variable foo
set foo 2
variable bar
set bar 3
}
If you want to do arrays, you can. Do them like this (with only one argument to variable):
namespace eval ns {
variable ary
array set ary {foo 2 bar 3}
}
What the variable command actually does is make the variable in the namespace in unset state so that it still resolves when commands like set and array can find the variable and write to it.

Global variable usage in tcl

I have set 3 global variables as below in a file FILE1:
set VAR1 2
set VAR2 3
set VAR3 4
Now I want to use these 3 variables in another file FILE2 in iterative way:
Means, something like this:
for {set a 1} {$a < 4} {incr a} {
$::VAR$a
}
where VAR$a - should be incremented each time to VAR1,VAR2,VAR3 etc...
But if I try like this using the global variable I get error in tcl
Any better solution for this?
Either make your meaning clearer to the interpreter
set ::VAR$a
(you are aware that this is just getting the variable's value without doing anything with the value, that is, a pointless operation, right?)
Or use an array, which is basically a two-part variable name:
set ::VAR($a)
in which case you need to initialize as an array:
set VAR(1) 2
etc, or
array set VAR {1 2 2 3 3 4}
The reason why $::VAR$a doesn't always work is AFAICT that the variable substitution becomes ambiguous. Given these definitions:
set foobar 1
set a foo
set b bar
what should $a$b substitute into? To avoid ambiguity, the substitution rules are kept simple: the first substitution stops before the second dollar sign, and the whole expression evaluates to the string foobar. How about $$a$b to substitute the value of foobar, then? No, a dollar-sign followed directly by a character that can't be a part of a variable name means that the first dollar sign becomes just a dollar sign: you get $foobar. The best way to handle this is to reduce the levels of substitution using the set command to get a value: set $a$b. Bottom line: variable substitution using $ does not always work well, but the set always does the job.
Documentation:
set,
Summary of Tcl language syntax

Printing multiple variables in tcl

I have to print multiple variables in a single puts like this
puts "$n1_$n2_$n3_$n4"
where n1 , n2 , n3 , n4 are 4 variables.
It wont print and will show error n1_ : no such variable
Expected output should be something like this (example)
01_abc_21_akdd
Variable names in Tcl can be any string in Tcl, there are no restrictions but if you want to use special characters (those not in the range of a-z, 0-9 and _, and letters in different languages depending on the platform and locale), you have to either brace the expression names or use other workarounds (like with the answer of Hoodiecrow).
What this means is that if you have a variable named abc.d, and if you use $abc.d, the Tcl engine will try to find the variable $abc because . is not a 'normal' character.
But if you have a variable named abc and use $abcd, or $abc_d, then the engine will start looking for the variables abcd or abc_d and not abc.
Because of this, you will have to use braces between the variable name for example:
${n1}
The reason why putting a backslash works is that \ is not a 'normal' character and after reading the above, it should be a little more obvious how things worked.
There are a few things that yet can go in variable names which don't need bracing and still mean something, except that something is 'special':
::: This is usually used for scoping purposes. For instance if you have a global variable named my_var, you can also use $::my_var to refer to it. Here :: tells Tcl that my_var is a global variable. Note that if there are more than two : in a row they will not add up:
% set ::y 5
5
% set ::::y
5
% set :::y
5
:: is usually used to define the namespace the variable is in. For example, $mine::var is a variable called var in the namespace with a name of mine.
(): These are used for arrays. $arr(key) is a variable with two parts: the array name arr and the key name key. Note: you can have an array named and a key named because...
% set () abc
abc
% puts $()
abc
% array get ""
{} abc
There might be some more, but those are the basics you could look out for.
Two other ways:
puts "${n1}_${n2}_${n3}_${n4}"
puts [format "%s_%s_%s_%s" $n1 $n2 $n3 $n4]
Documentation: format
(Note: the 'Hoodiecrow' mentioned in Jerry's answer is me, I used that nick earlier.)

How tcl curly braces in ${variableName} is interpreted?

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.

TCL : what is the default package for tcl commands

I want to know in which package all tcl commands will be available .
for example string , list etc .
When we want to use expect , we will use Expect package , similarly we are using these (string , list etc ...) commands without importing any package . i want to know in which package these are all belong ?
basically I came from java ... In java "java.lang" package default.
Formally, all commands that form the core of the Tcl language are provided by the Tcl package. That package is required for you before you run any code (and has to be; the package command itself is one of those commands). By historical convention, the large majority of Tcl commands are placed in the global namespace, which is on the command resolution path of all namespaces. (It's logically last on the path unless explicitly set with namespace path.) Some Tcl commands are defined in the ::tcl namespace, including a fair number of internal commands, direct access to which are not supported (if it isn't documented, it isn't supported; some are explicitly not supported but are relatively well known nonetheless; they're in the ::tcl::unsupported namespace). The namespace ::oo (and its children) are reserved for TclOO.
Commands defined by other packages — especially any newly-created packages — should be placed in a namespace with the same name as the package. This is merely a convention, and is not followed in older packages (particularly those that predate the namespace mechanism, such as Tk and TclX) because it is reckoned to be more important to maintain backward compatibility with existing scripts, but you will definitely find it easiest if you follow it. Also, it's usually the convention that the global namespace belongs principally to the user-defined application, despite the degree of pollution from other packages; it's yours to mangle as you see fit.
The exported commands of a namespace (which should typically be the public commands of the package with the same name) can be made available in another namespace without qualification via namespace import:
namespace eval ::foo {
proc grill {} { puts "grill!" }
namespace export grill
}
namespace eval ::bar {
namespace import ::foo::grill
grill
puts [namespace which grill]; # Prints ::bar::grill
puts [namespace origin grill]; # Prints ::foo::grill
}
Alternatively (from Tcl 8.5) you can update the resolution path of a namespace so it also looks in the other namespace:
namespace eval ::foo {
proc grill {} { puts "grill!" }
}
namespace eval ::bar {
namespace path ::foo
grill
puts [namespace which grill]; # Prints ::foo::grill
puts [namespace origin grill]; # Prints ::foo::grill
}
Note that the two mechanisms are a bit different: with imported commands, there is a local delegate for the command (and as that delegate is actually a command, you can rename it, etc.) whereas with path changes there are no such delegates; the command in the originating namespace is located directly during resolution of what grill means in that context.
List and strings does not come under any special packages. They are the basic commands. All the variables are treated as a string in tcl.
$ tclsh
% set l [list 1 2 3 4 5]
1 2 3 4 5
% lappend l 6
1 2 3 4 5 6
% set str "Hello, World"
Hello, World