How to check if variable is present in a table? TCL - mysql

I'm very new to this language and need some help. I want pass/send email variable and see that if it is present in a database table?
'proc: TEST::TestingFunc {ArrayName}{
upvar #0 $ArrayName Param
if {[info exists Param(data)]} {
set email $Param(data)
}
}'

This is not an answer, I just need the formatting capabilities to write this comment. It's not quite clear what you are asking about or what you want to do. The code you posted seems mostly OK if you want to check if there is a member named data in a given associative array, and get its value. There are a couple of errors in the code: it should look something like this
proc TEST::TestingFunc {ArrayName} {
upvar #0 $ArrayName Param
if {[info exists Param(data)]} {
set email $Param(data)
}
}
For this to work, you also need to have created a namespace called TEST.
Beyond this, I'm unsure what you want to do. What do you mean by "pass/send"? Is the "database table" you are talking about the associative array, or do you mean something else?

Related

Understanding the use of Tcl namespace variable

I have a namespace variable which is defined as below:
namespace eval ::SMB::{
variable SmbInfo
------
------
proc ::SMB::SmbCreate {name dutport} {
variable SmbInfo
global DutPorts DutPort_2 DutPorts_3 smb
------
------
if{"" != [info command SMB::$name]} {
return -code error "command name \"$name\" already exists"
}
set SmbInfo($name -DutPort) $dutport
I am new to Tcl and trying to understand the above piece of code. Few questions, please correct me if I am wrong at any point:
The variable SmbInfo defined on top in namespace is getting overridden by the one declared in the procedure SmbCreate. I am unable to figure out what is the objective of the line:
set SmbInfo($name -DutPort) $dutport
I can see that 'DutPorts' is defined as global but I could not find 'DutPort'. I have not executed the code yet. Could it be an error?
Is ($name - DutPort) creating an array index for the variable SmbInfo and the value of $dutport is being set to that particular array variable?
I have similar code structures in the file like below
set SmbInfo($name - SmbSetDmac) [BuildMac1 $SmbInfo($from_name-DutPort)]
Where BuildMac1 is a procedure. A bit explanation of the above code might also make the thing clear.
If anything I missed to post in the question, kindly point me, I will edit my question.
Thanks in advance.
The second declaration doesn't override, it's the same variable in both cases.
The command is a syntax error because of the space after $name. The intent seems to be to assign the value of $dutport to the member of SmbInfo that has the name "$name -DutPort" (where $name is replaced by the variable value).
A similar assignment, but here the value comes from the result of the command.
There are a few syntax errors in the code, too many or too few spaces here and there. It seems unlikely this code has ever been executed.
The purpose of the smb::SmbCreate command would seem to be to 1) create a new command in the SMB namespace named by the first parameter (unless such a command already exists) and 2) store metadata in the SmbInfo namespace variable, indexed by a) the name parameter and b) a keyword such as -DutPort or -SmbSetDmac.
Code like this essentially implements an ad-hoc object-oriented interface. If the whitespace issues are resolved, it should work fine.
You have many syntactic problems that are going to cause you much grief. Tcl cares very much about its syntax level, which includes exactly where the spaces and newlines are, and whether there are {braces} and [brackets] as expected. You must get these things right.
Looking at the specific code you're having problems with, this line:
set SmbInfo($name -DutPort) $dutport
would appear to be highly unlikely, as it is passing three arguments to the set command when that only takes one or two. I'd guess that you've got a command that you're calling to obtain a key for an array, and that the code therefore ought to be this:
set SmbInfo([$name -DutPort]) $dutport
See those [brackets]? They matter here, as they say “run my contents as a little subscript and use the result”. With that sorted out, there's also the question of whether $name -DutPort works at all, but you'll just have to be guided by the error messages there. Tcl usually gives very good error messages, though sometimes you have to think about why the code got in the state where it is giving that message in order to figure out what the actual problem is. You know, usual debugging…
I would expect similar problems with:
set SmbInfo($name - SmbSetDmac) [BuildMac1 $SmbInfo($from_name-DutPort)]
and would guess that it is actually supposed to be:
set SmbInfo([$name -SmbSetDmac]) [BuildMac1 $SmbInfo([$from_name -DutPort])]
Note again that I have modified the spaces to follow the existing pattern (which I'm guessing is a property access; it looks like it's OTcl or XOTcl) and added brackets.
Finally, this line:
if{"" != [info command SMB::$name]} {
is also syntactically wrong, and should instead be:
if {"" != [info command SMB::$name]} {
That extra space matters, because it separates the word that is the command name (if) from the word that is the condition expression. The remainder of the line is probably correct (the SMB::$name might be suspicious, except you're using it in info command, but then you probably only need info command $name as it already knows about what namespace you're working in and you're using the unqualified name elsewhere).

What does it mean proc argument is variable

I wonder if it is right semantics to have a variable as an argument, something like this:
proc p1 {$aa} {}
I tried it on tclsh, there is no complaint, but the following experiment fails:
% set aa bb
bb
% set bb 200
200
% proc p1 {$aa} {puts $bb}
% p1 bb
can't read "bb": no such variable
Do you see what is wrong?
[UPDATE - after seeing Peter's answer]
I know the upvar semantic, thanks.
My main curiosity is still around using variable as proc argument. I know it is not common, but just cannot help musing what it really can do if the language syntax allows it.
Yes, your upvar example is exactly what I want to explore using a variable as proc argument, but my exploration so far tells me, really, there is no way we can do this because "$" is interpreted as a plain char.
Do debunk me please if I am wrong.
Tcl does not support reference arguments as such: the usual pass-by-reference semantics is too static for Tcl. Instead, the logic of the command can, by use of upvar, dynamically create reference parameters including indirect reference parameters and calculated reference parameters, and also retarget the local name to another external variable. The upvar mechanism may look ungainly, but is very powerful indeed.
(The (edited) remains of my original answer follows:)
The usual idiom for doing this is
proc p varName {
upvar 1 $varName var
puts $var
}
The upvar command looks into another stack frame (in this case 1, which is the caller's stack frame) and makes a variable named $varName (i.e. the variable's name is the value of varName) in that stack frame and a variable named "var" in the command's stack frame refer to the same data object.
I won't explain this further since this is not useful to the asker.
Documentation: proc, puts, upvar
There are cases where it makes sense for the arguments in a procedure creation call to be supplied from a variable. The main example is where you are creating procedures dynamically, calculating the arguments you want to use as you go along.
That's actually a use-case that isn't done very frequently! It's not particularly easy to use well. But I have done it. (OK, that's a method call, but the syntax of formal arguments is shared.)
The main reason that the capability is there is that it's part of Tcl's general syntax. Tcl tries very hard to not have special cases in how it parses things (other than in how a command parses the strings passed into it) and this includes in things that would be very special cases in the enormous majority of other programming languages, such as formal parameter lists to procedures. In Tcl, these are just ordinary values and can be produced using any technique that gives ordinary values.
The usual thing with putting them in braces is just how you do it reliably and is easy to teach. It's also overwhelmingly what people want to do.
All this is independent of the facts that Tcl's commands (including its procedures) can handle variable numbers of arguments (check out the special args parameter and how to specify default values) and that $aa is a legal (but strange) name for a local variable.

Adding help to the user defined functions in TCL

how can i add some kind of help to the user defined functions in TCL
Supposing if i have a function called runtest {ip_address test_time},
How to describe what the test or procedure is about in the TCL_shell?
How can i specify the information to the user, if he types in function_name --help in the TCL shell the user should be able to know what the function does and what exactly are the parameters.
how can i do this?
While it is true that it is not part of the language, it is fairly easy to implement something that adds this functionality to pre-existing functions. The only caveat being that the function then cannot take the string --help as a valid argument since that argument will trigger the feature.
Here's one simple implementation:
# Lets call the feature "document". As in, add documentation:
proc document {procname text} {
rename $procname __$procname
proc $procname args [string map [list %TEXT% $text %PROC% $procname] {
if {$args == "--help"} {
puts {%TEXT%}
} else {
set script [linsert $args 0 __%PROC%]
return [uplevel 1 $script]
}
}]
}
What this does is to override the function (by renaming and then declaring another function of the same name) and see if the function is called with the argument --help. If it is it prints the documentation otherwise it executes the original function. Just be careful not to call this twice on the same function (it can be modified for it to work though).
So you can do things like:
proc foo {} {puts 2}
document foo {Prints the number 2.}
Now if you call:
foo --help
and it would output:
Prints the number 2.
You don't have to touch the existing procedures:
proc help {procname} {
puts $::helptext($procname)
}
proc addhelp {procname text} {
set ::helptext($procname) $text
}
addhelp foo "this is the help text for procedure foo"
help foo
Without redefining the proc command, you cannot. Ie, that functionality is not built into the language, but would be possible to add if you so wished.
I will note that adding the capability yourself, while possible, is probably beyond the difficulty where it's worth doing, especially for someone that isn't intimately familiar with the language. That being said, you can check the tclers wiki for a preexisting implementation.
I tend to prefer to put help in a separate file (e.g., as HTML) which lets me browse it in another window. There are so many ways you can do that while still keeping the docs with the code, such as through doxygen.
There are also a number of ways of doing interactive documentation, several of which are described in the Tcler's Wiki; it would seem to me that some of the techniques mentioned on that page (together with #slebetman's answer) would give you what you wanted. (I think it would be easier to have a separate help command as that would avoid having the help syntax interfere with the command, but that's your call.)

TCL - return variable vs upvar and modify

Would like to take an advice from TCL professionals for best practice.
Say you want to construct a list with a specific data by using a proc. Now which is the best way?
proc processList { myList } {
upvar $myList list_
#append necessary data into list_
}
proc returnList {} {
set list_ {}
#append necessary data into list_
return $list_
}
set list1 {}
processList list1
set list2 [returnList ]
Which one of this practices is recommended?
EDIT: I am sorry but I can't understand consensus (and explanation) of people who answered to this question.
I virtually always use the second method:
proc returnList {} {
set result {}
# ... accumulate the result like this ...
lappend result a b c d e
return $result
}
set lst [returnList]
There's virtually no difference in memory usage or speed, but I find it easier to think functionally. Also, in Tcl 8.5 you can do the splitting up of the result list relatively simply (if that's what you need):
set remainderList [lassign [returnList] firstValue secondValue]
With that, you'd end up with a in $firstValue, b in secondValue, and c d e in $remainderList.
The first option modify an existing list whereas the second create a new list. For a better comparison, I would add a parameter to returnList() and create a return value from that parameter.
Given that, the difference is in the way of passing parameters -- by reference or by value-- and in the memory budget needed by each operation.
There is no side effect with the second method, but it could be very consuming if the list is huge.
There is no general rule for recommending one over the other. My own rule is to start with the second way unless other constraints lead not to do so.
What would the syntax be for the equivalent of:
set lst [returnList]
If you wanted to return more than one list at once?
I thought that if you did something like this:
return [$list1 $list2]
It was supposed to return a list of lists, which you could then access with lindex. But, that doesn't appear to be exactly what it does. It really just gives you two lists back, without external curly braces grouping them into a single list. In Perl, you can do something like:
($var1, $var2) = process_that_returns_two_values;
But I don't think "set" allows that in Tcl.

do we need to "unset" variables in TCL?

Is it a requirement of good TCL code? What would happen if we don't use the "unset" keyword in a script? Any ill-effects I should know about?
I'm inheriting some legacy code and the errors that come about due to "unset"-ing non-existent variables are driving me up the wall!
It's possible to determine whether a variable exists before using it, using the info exists command. Be sure that if you're not using unset, that you don't upset the logic of the program somewhere else.
There's no Tcl-specific reason to unset a variable, that is, it's not going to cause a memory leak or run out of variable handles or anything crazy like that. Using unset may be a defensive programming practice, because it prevents future use of a variable after it's no longer relevant. Without knowing more about the exact code you're working with, it's hard to give more detailed info.
In addition to the other responses, if your Tcl version is new enough, you can also use:
unset -nocomplain foo
That'll unset foo if it exists, but won't complain if it doesn't.
Depends on the system stats it may give "unable to allocate bytes" issue as and when your script is storing huge data into variables and arrays. it'll break once the cache or RAM is full saying "unable to allocate XXXXXXXX bytes".
Make sure you're not storing that much data into variables, otherwise do unset once the use is over for the respective datasets(variables)
For note as I don't seem able to comment on the "info exists" above;
I use this form often..
if { [info exists pie] && [$pie == "ThisIsWhatIWantInPie"]} {
puts "I found what I wanted in pie."
} else {
puts "Pie did not exist; but I still did not error,TCL's evaluation \
will see the conditional failed on the [info exists] and not \
continue onto the comparison."
}
In addition to the other responses, I want to add that, if you want to neglect the errors raising as a result of unsetting non-existent variable use 'catch'.
#!/bin/bash
catch {unset newVariable}