I am new for Tcl/Tk. I am using vtk with Tk command window for running vtk tcl/tk examples. Here is a code which include Tk expression as condition of if and I am not getting it.
if { [info command rtExMath] != "" } {
##Do something related VTK
}
I have explored info of Tk but there is a combination with keyword command and also no any good explanation I found for rtExMath.
Please explain me above.
The info commands command (info command is just an unambiguous prefix) returns a list of all commands, or a list of all commands that match the given glob pattern. In the case you're looking at, the glob pattern is actually going to be a string-equality check (and is even optimised to such internally); there's no glob metacharacters in it. The result of that is that [info command rtExMath] != "" is a condition that is true exactly when the command rtExMath exists.
Tcl itself does not define any command called rtExMath; I conclude that it must be part of some specialist extension or application. However, Googling makes me suspect that it is actually a somewhat-standard name for an instance of the vtkMath class in Vtk, but I don't really know for sure. (I'm guessing that the binding of that class to Tcl was done by SWIG…)
Related
I am trying to convert some tcl script into a C++ program. I don't have much experience with tcl and am hoping someone could explain what some of the following things are actually doing in the tcl script:
1) set rtn [true_test_sfm $run_dir]
2) cd [glob $run_dir]
3) set pwd [pwd]
Is the first one just checking if true_test_sfm directory exists in run_dir?
Also, I am programming on a windows machine. Would the system function be the equivalent to exec statements in tcl? And if so how would I print the result of the system function call to stdout?
In Tcl, square brackets indicate "evaluate the code between the square brackets". The result of that evaluation is substituted for the entire square-bracketed expression. So, the first line invokes the function true_test_sfm with a single argument $run_dir; the result of that function call is then assigned to the variable rtn. Unfortunately, true_test_sfm is not a built-in Tcl function, which means it's user-defined, which means there's no way we can tell you what the effect of that function call will be based on the information you've provided here.
glob is a built-in Tcl function which takes a file pattern as an argument and then lists files that match that pattern. For example, if a directory contains files "foo", "bar" and "baz", glob b* would return a list of two files, "bar" and "baz". Therefore the second line is looking for any files that match the pattern given by $run_dir, then using the cd command (another Tcl built-in) to change to the directory found by glob. Probably $run_dir is not actually a file pattern, but an explicit file name (ie, no globbing characters like * or ? in the string), otherwise this code may break unexpectedly. On Windows, some combination of FindFirstFile/FindNextFile in C++ could be used as a substitute for glob in Tcl, and SetCurrentDirectory could substitute for cd.
pwd is another built-in Tcl function which returns the process current working directory as an absolute path. So the last line is querying the current working directory and saving the result in a variable named pwd. Here you could use GetCurrentDirectory as a substitute for pwd.
So I have been trying to find an answer for this for a bit and could not find the answer on the internet. I need to check to see if an environment variable exists. I thought I had the right code but it keeps returning false.
if { [info exists ::env(USER)] } {
RAT::LogMsg INFO "Found USER"
} else {
RAT::LogMsg INFO "Nope!"
}
Any ideas?
You might want to check what environment variables are actually set; I don't think that USER is one of the guaranteed ones.
RAT::LogMsg INFO "Got these env-vars: [lsort [array names ::env]]"
If puts stdout works in your environment, you can try doing:
parray ::env
(The parray command is a procedure that pretty-prints an array.)
To get the current username reliably, check out the tcl_platform array's user element. That array is generated internally by Tcl (well, with probes to relevant basic OS APIs) instead of by looking at environment variables, and that particular element is always present back at least as far as Tcl 8.4.
RAT::LogMsg INFO "Username is $::tcl_platform(user)"
I've just noticed that the documentation is wrong: it says that the user element comes from USER and/or LOGNAME environment variables. It doesn't, and doesn't in at least 8.5 and 8.6. (And it's definitely my mistake. I forgot to update the code when I fixed this. Ooops!)
You have the right code, test in tclsh:
% if {[info exists ::env(USER)]} {puts "found $::env(USER)"}
found strobel
%
The problem must be in your environment.
What means this error?
command already exists in namespace "::"
Can you provide simple case when this error raises?
That's (probably) an error thrown by the [incr Tcl] core when you try to do something like defining an itcl class with the same name as an existing command that isn't already a class; the part you left out (in quotes, between “command” and “already”) was the name of the command that you were trying to override. For example (the subst is fairly arbitrary here):
% package require itcl
4.0b7
% itcl::class subst {}
command "subst" already exists in namespace "::"
No command that is a “standard” part of Tcl itself (and not an extension package or user code) generates an error that's remotely close.
As for how to fix… don't use the same name as an existing non-class. What this means in the context of your code though, I don't know. You don't reveal enough information for me to work out the deeper reason why you might be having this problem in the first place.
I have developed some code, and I'm facing problem with error flagging of the Tcl interpreter on a Linux machine.
#!/usr/bin/tclsh
if {1} {
puts "abc1"
} elseif {} {
puts "abc2"
}
The above code is not flagging error for "elseif" condition until it get into the
elseif condition.
Is there any way to check this kind of typo error done unintentionally.
Tcl does not find errors at compilation time, and in the the sample above it can determine that it will never need to examine the elseif clauses in the first place; it just issues that first puts directly.
Now, in the case where there is a non-trivial first condition it is the case that the errors in the elseif expression are not reported until they are reached. This is how the semantics of Tcl — and especially the if command — are defined; errors in evaluation (as opposed to gross major syntax) are reported at the time of execution of the command. I can understand your frustration with this, and suggest that you check out the Tcler's Wiki page on static syntax analysis tools, which can flag up potential problems for you (under very modest assumptions that are virtually always true). In particular, I have heard good things about Frink and the checker tool in TDK (the latter being a commercial tool, but very high quality).
To elaborate on Donal's answer, Tcl does not find errors at compile time because in the general case it cannot be done, any code executed before the if might have redefined the if command, so it could be valid, the only way to determine if this is the case is to run the code (i.e. this is the halting problem)
consider this script:
gets stdin input
if {$input == "fail"} {
rename if if_
proc if {arg1 arg2 arg3} {
puts "ha ha"
}
}
if {1} { puts "success"}
clearly it is impossible to statically determine if the if {1} line has the right number of arguments without running the program
TCL really has virtually no syntax, there is nothing a compiler can check, the best you can do is Lint style warnings, which will only be accurate in some cases
Tcl does not find errors at compilation time, But we can check the syntax using regexp.
Match the pattern " elseif { ", If present check whether there is any characters within the "}" curly brace. If nothing present then print an error message.
There are tcl static syntax checker that can find such problems.
Here is the list of such checkes: http://wiki.tcl.tk/3162
The ttclchecker http://www.xdobry.de/ttclcheck
produces following error message for this short script
stackoverflow.tcl:4: error in expression missing operator <<{}>>
I have to run TCL code written for version 8.5 with the interpreter of version 8.3.
I am having problems with eq. Seems 8.3 doesn't recognize it. A simple code:
% expr { "a" eq "b" }
returns an error message like:
syntax error in expression "a eq b"
I am trying to fix this by adding an interp alias before everything like this:
interp alias {} eq {} ==
but seems it has no effect.
Is there any way to make eq an alias for ==? If no, is the only way to get rid of this error is to replace all eq statements by == statements?
The eq and ne operators were introduced in Tcl 8.4. See Changes in Tcl/Tk 8.4 on the Tcler's wiki. There is no way to make "eq" be an alias for "==" within an expression. Your attempt to use the alias command only resulted in creating a command named eq that does whatever the command == does (specifically, fail unless you actually have a command named ==).
If you absolutely must find a way to make this work, in your 8.3 interpreter you can rename expr to be something else (eg: _expr), then create your own expr command that does a string substitution before calling the renamed expr command. This is fraught with peril since you have to make sure to only substitute operators and not the data being compared.
I'm not even sure this code works properly in tcl 8.5
First make sure your expr is between curly brackets:
% expr {"a" eq "b"}
The alias allows you to create an alias for a command, but eq is not a command, it´s a subcommand of the expr command, so you would really need to create your own proc expr args wrapper.
Why do you need to use tcl 8.3? it's a really old version.
Tcl 8.3 is rather old, and the recommended path for upgrading from TclPro (as I see you're using from comments) to something less… antediluvian… is to purchase the Tcl Dev Kit from ActiveState, which is at least the spiritual successor and has current support. Nobody supports TclPro any more.
That said…
Now, with Tcl 8.3 the equivalent of the functionality of the eq operator was the string equal command (in 8.4, they actually compile to the same bytecode; one is a short-cut for the other). This means that for this:
if {"a" eq "b"} {...
would be instead written as this:
if {[string equal "a" "b"]} {...
though if you've definitely got a non-integer for one of the arguments, you can just use this:
if {"a" == "b"} {...
There is no mechanism for aliasing operators in any version of Tcl (well, certainly not up to 8.6, which is the current development/beta version).
The Gripping Hand
As Bryan says, you can write your own versions of expr (and if and for and while) that have this extended functionality, but that's a lot of work (i.e., months including all the testing, though you can probably reuse the test suite from Tcl 8.4 to help) and it's just so you can use a version of Tcl that is known to be obsolete. (I have no idea if it has security issues in it, and you can't pay me enough for me to want to try to find out.) You're better off paying for the TDK.