Please explain about proc command in Tcl - tcl

I am a new learner in Tcl. Please explain it....
what is the work of [proc] command in Tcl ? I know that [proc] build a new command but want to understand it more closely.

The proc command creates a new command. The syntax for the proc command is
proc Name args body
when proc is evaluated, it creates a new command with name Name that takes arguments args. When the procedure Name is invoked, it then runs the script contained in the body.
The following is simple Tcl script using proc command to find sum of two values:
proc sum {arg1 arg2} {
set x [expr {$arg1 + $arg2}];
return $x
}
puts " The sum of 2 + 3 is: [sum 2 3]"
This is the input script.
The output:
The sum of 2 + 3 is 5
Note: Here the new command is now sum.

Related

How to convert script into a hard coded version of it in Tcl language?

I am looking for a way to convert a script into its fully hard-coded version. I even don't know how this kind of function is named in software industry.. so I even don't know how to google it. Here are some examples of what I want. I don't want to use any conditional or iterative function for the outputs.
Example 1) foreach case
foreach x [list 1 2 3] {
puts "x=$x"
}
I'd like to convert this script to have:
puts "x=1" ; puts "x=2" ; puts "x=3"
Example 2)
set A 1
if { $A == "1" } {
puts "A is 1"
} else {
puts "A is not 1"
}
I want this to be :
set A 1
puts "A is 1"
Example 3) If I face comment line or unknown command or procedure, I just want to pass it to the output.
set argument 1000
UnknownProcedure $argement
This now should be :
set argument 100
UnknownProcedure 100
Thanks in advance.
You could try trace add execution ... to commands. This is used to execute a body of code before the command itself if executed. If you can pass the arguments of your command to your trace function and also use info frame to get the proc/command name being executed, then you could use the trace function to write out a hardcoded version of the command.
See here:
https://www.tcl-lang.org/man/tcl8.6/TclCmd/trace.htm
https://wiki.tcl-lang.org/page/info+frame

How to retrieve the last command's return value in TCL interpreter?

In Tcl, if I evaluate a command, and my expression failed to store the result in a variable, other than reevaluating the command, is there a way to retrieve the last command's return value in a TCL interpreter? For example, in some lisps, the variable * is bound to the result of the last evaluation, is there something like that in TCL?
The Tcl interpreter loop — which is pretty simple minded, with very few hidden features — doesn't save the last result value for you; it assumes that if you want to save that for later, you'll do so manually (or you'll repeat the command and get the result anew so you can save it then).
If you want to save a value for later, use set. You can use * as the name of the variable (it is legal) but it's annoying in practice because the $var syntax shortcut doesn't work with it and instead you'd need to do:
% set * [expr {2**2**2**2}]; # Or whatever...
65536
% puts "the value was ${*}... this time!"
the value was 65536... this time!
% puts "an alternative is to do [set *]"
an alternative is to do 65536
This will probably be a bit annoying when typing; use a name like it instead.
% set it [expr {2**2**2**2}]; # Or whatever...
65536
% puts [string length [expr {123 << $it}]]
19731
(That last number has rather a lot of digits in it, more than I expected…)
For example, in some lisps, the variable * is bound to the result of
the last evaluation, is there something like that in TCL?
It depends, but in the non-error case, catch can be used to, well, catch the result of the last successful evaluation within the enclosed script:
proc foo {} {return FOO}
proc bar {} {return BAR}
if {![catch {
if {rand() < 0.5} {foo} else {bar}
} * opts]} {
# handle result of last cmd evaluation
puts ${*}
} else {
# handle an error
puts [dict get $opts -errorinfo]
}
If you happen to know the command names in advance, command traces might be another option.

Executing a sql procedure with parameters from Powershell

I'm completely new to Powershell so i'm a little confused about how to call a SQL procedure that takes parameters. I have opened a connection to my database successfully and i've managed to get a procedure that doesn't take parameters to work so I know that the connection is fine.
The code to add a parameter and run the query is below:
$dateToUse = Get-Date -f yyyy/MM/dd
$MysqlQuery.CommandText = "GetJourneyByDepartureDate"
$MysqlQuery.Parameters.AddWithValue("_departureDate", $dateToUse)
$queryOutput = $MysqlQuery.ExecuteReader()
Whenever I try and run my script I get an error saying
Incorrect number of arguments for PROCEDURE dbo.GetJourneyByDepartureDate; expected 1, got 0
I've had a look around trying to find a solution but I don't understand enough about Powershell to know what solutions might be correct.
Also I am unable to post the SQL query but I have managed to run the procedure many times by just running the query in HeidiSQL passing the arguement manually
EDIT:
I've now changed my code slightly, it now looks like this:
$MysqlQuery.CommandText = "GetJourneyByDepartureDate"
$MysqlQuery.Parameters.Add("#_departureDate", [System.Data.SqlDbType]::Date) | out-Null
$MysqlQuery.Parameters['#_departureDate'].Value = $dateToUse
$parameterValue = $MysqlQuery.Parameters['#_departureDate'].value
Write-Host -ForegroundColor Cyan -Object "$parameterValue";
$queryOutput = $MysqlQuery.ExecuteReader()
I'm getting the $dateToUse value output on the console in the Write-Host line but i'm still getting the same Incorrect number of arguments error as before. SP is declared as below:
CREATE PROCEDURE `GetJourneyByDepartureDate`(IN `_departureDate` DATE) READS SQL DATA
In the end I found that I needed to set the CommandType to be StoredProcedure and also I needed to add the parameter but I was missing the direction and I apparently had to add a space after the '#' but i'm not sure why. My solution is below:
$MysqlCommand = New-Object MySql.Data.MySqlClient.MySqlCommand.Connection = $connMySQL #Create SQL command
$MysqlCommand.CommandType = [System.Data.CommandType]::StoredProcedure; #Set the command to be a stored procedure
$MysqlCommand.CommandText = "GetJourneyByDepartureDate"; #Set the name of the Stored Procedure to use
$MysqlCommand.Parameters.Add("# _departureDate", [System.Data.SqlDbType]::Date) | out-Null; #Set the input and output parameters
$MysqlCommand.Parameters['# _departureDate'].Direction = [system.data.ParameterDirection]::Input; #Set the _departureDate parameter to be an input parameter
$MysqlCommand.Parameters['# _departureDate'].Value = $dateToUse; #Set the _departureDate parameter value to be dateToUse

Writing procedures in TCL

I am very new for TCL. Just I want to know that how to write TCL procedures without argument and how to call and how to execute it.
To write a procedure that doesn't take any arguments, do this:
proc someName {} {
# The {} above means a list of zero formal arguments
puts "Hello from inside someName"
}
To call that procedure, just write its name:
someName
If it was returning a value:
proc example2 {} {
return "some arbitrary value"
}
Then you'd do something with that returned value by enclosing the call in square brackets and using that where you want the value used:
set someVariable [example2]
To execute it... depends what you mean. I assume you mean doing so from outside a Tcl program. That's done by making the whole script (e.g., theScript.tcl) define the procedure and do the call, like this:
proc example3 {} {
return "The quick brown fox"
}
puts [example3]
That would then be run something like this:
tclsh8.5 theScript.tcl
You can define a procedure like this:
proc hello_world_proc {} {
puts "Hello world"
}
And you can execute it by simply writing:
hello_world_proc
If you want to use a return value of the procedure, you can do:
# Procedure declaration
proc hello_world_proc2 {} {
return "Hello world"
}
# Procedure call
puts [hello_world_proc2]
proc myProc {} {
# do something
}
# call proc
myProc
Te official Tcl website has some documentation on functions (procedures) that could help you at https://www.tcl.tk/man/tcl/TclCmd/proc.htm.
Procedure with no argument
If you don't need any argument here is how to write the procedure you want:
proc funcNameNoArgs {} {
puts "Hello from funcNameNoArgs"
}
And you can call it as follows:
funcNameNoArgs
Procedure with arguments
Now let's say you need arguments in the future. Here is the way to write that precedure in TCL:
proc funcNameWithArgs {arg1 arg2 arg3} {
puts "Hello from funcNameWithArgs "
}
You can call that function by doing:
funcName arg1 arg2 arg3
Here is a piece of code for you to try!
Remember to define functions before you call them, or you will get an error.
Try to copy paste this code in your interpreter to get started and play with it:
proc funcNameNoArgs {} {
puts "Hello from a function with no arguments"
}
funcNameNoArgs
proc funcNameWithArgs {arg1 arg2 arg3} {
puts "Hello from a function with 3 arguments"
puts $arg1
puts $arg2
puts $arg3
}
funcNameWithArgs "Argument 1" "Argument 2" "Argument 3"
Syntax of procedure
proc <Name Of procedure> {No of arguments, if u want don't need simply left empty} {
<Body>
}
Let See the Example:
Without Arguments:
proc Hello_eg { } { puts "Hello I M In procedure" }
How to run:
step 1: write tclsh on prompt
step 2: write the procedure as per above mention
step 3: write just the procedure name (i.e Hello_eg) to run the procedure
2.With Arguments:
proc Hello_Arg { first second }
{
puts "The first argument is: $first"
puts "The Second argument is: $second"
}
How to run this:
step 1: write tclsh on prompt
step 2: write the procedure as per above mention
step 3: write just the procedure name with arguments (i.e Hello_Arg Ramakant Singla) to run the procedure
It's pretty simple.
Defining :
proc myproc {} {
}
calling :
myproc
Since you are New, I advise you to go through tutorial point. They have simple and consolidated content.
Procedure is a set of statements which is being preapeated in a program.
Syntax
proc <Name> {INPUTS} {
BODY
}
Eg:
proc add {m n} {
set s 0
set s [expr $m + $n]
return $s
}
#Main Program Starts Here
set x 2
set y 3
set Result [add $x $y]
puts "$Result"
In the above example....in procedure we have provide a name (add) to the set of statements which can be call in the main program.
Any amount of arguments
What maybe would come in handy is using args.
By using args you can pass any amount of arguments to your procedure.
proc withAnyNumberOfArguments {args} {
if {$args eq ""} {
puts "got no arguments"
}
foreach arg $args {
puts "got $arg"
}
}
Optional Arguments
Another tip: Enclosing arguments with { } makes them optional arguments.
proc atLeastOneArgument {a1 {args}} {
puts -nonewline "got a1=$a1"
foreach arg $args {
puts -nonewline " and $arg"
}
puts "."
}
Default Values
If you want to have default values you can specify them as follows:
proc putsTime { {secondsSinceBeginOfEpoch "now"} } {
if {$secondsSinceBeginOfEpoch eq "now"} {
set secondsSinceBeginOfEpoch [clock seconds]
}
return [clock format $secondsSinceBeginOfEpoch]
}
Some Example Calls
1 % withAnyNumberOfArguments
got no arguments
2 % withAnyNumberOfArguments one
got one
3 % withAnyNumberOfArguments ready steady go!
got ready
got steady
got go!
4 % atLeastOneArgument "this is one argument" ;# because its in double quotes
got a1=this is one argument.
5 % atLeastOneArgument 3 2 1 go!
got a1=3 and 2 and 1 and go!.
6 % puts [formatTime]
Fri Dec 18 16:39:43 CET 2015
7 % puts [formatTime 0]
Thu Jan 01 01:00:00 CET 1970
In addition to the answers above, I would recommend using tcltutor.exe (available from http://tcltutor.software.informer.com/3.0b/) to learn TCL.
It'll have a chapter on Subroutines that'll help you define a TCL proc without and with arguments.
Regards
Sharad
To create a TCL procedure without any parameter you should use the proc keyword followed by the procedure name then the scope of your procedure.
proc hello_world {} {
// Use puts to print your output in the terminal.
// If your procedure return data use return keyword.
}
You can use the created procedure by simply calling its name:
hello_world
This solution is based on previous questions about writing procs. I personally feel this is one of the better ways to write a procedure in tcl.
Code
proc sampleProc args {
# Defaults
array set options {-device router0 -ip "10.16.1.62"}
# Read args
array set options $args
# Assign
set device $options(-device)
set ip $options(-ip)
# Usage
puts "Device under use is $device and IP is $ip"
# Return
return "${sd} :: $ip"
}
Execution
tclsh> source sampleProc.tcl
Device under use is router0 and IP is 10.16.1.62
router0 :: 10.16.1.62

evaluating an expression to true in a if statement with Tcl

I'm having serious biggies trying to figure out how to evaluate an expression in a If statement using Tcl. This is what I have:
#!/bin/sh
#The next line executes wish - wherever it is \
exec wish "$0" "$#"
set apid "/var/run/apache2.pid"
set apsta [file exist $apid]
if { $apsta == 1 }
{
set result ":)"
}
else
{
set result ":("
}
label .status -text $result
pack .status
and this is what I get from the terminal:
# wan27
Error in startup script: wrong # args: no script following " $apsta == 1 " argument
while executing
"if { $apsta == 1 }"
(file "/usr/bin/wan27" line 9)
I'm just trying to output a happy smiley if Apache is running, a sad one if Apache is stopped - based upon the boolean condition whether or not the file "/var/run/apache2.pid" exists ...
The syntax of a Tcl if statement is
if condition statement else statement
which must be on one line. Braces allow continuation across lines and their placement is mandatory:
if { $apsta == 1 } {
set result ":)"
} else {
set result ":("
}
As you have it written, Tcl sees
if { $apsta == 1 }
and stops there yielding a syntax error.
MSW have already given you the correct answer but I think a little bit more explanation is needed to clear up some other confusions you are having based on your comments.
I will first explain things using non-tcl terminology since I think it is less confusing that way.
In tcl, if is not a statement. if is a function. That is the reason why the opening brace need to be on the same line: because a newline terminates the list of arguments to a function. For example, in the following code:
a b c d
e f
the Tcl interpreter will see two function calls. The first to function a with arguments b, c and d and the second to function e with a single argumrnt f. Similarly, in the following:
if a
b
Tcl sees a call to the function if with a single argument. Since if expects at least two arguments it (not the interpreter itself) throws an error complaining about wrong number of arguments.
This also explains why there must be a space between if and its first argument. It's just because in tcl names of variables and functions are literally allowed to contain almost anything including spaces, commas and non-printing characters like NUL. For example, you can define a function called a{b}:
proc a{b} {} {puts HA!}
a{b} ;# <-- prints out HA!
So if you do something like:
if{x} {y}
tcl will complain that the function if{x} is not defined.
if is not the only thing that works like this. Tcl doesn't really have keywords, just a standard library of built-in functions like for, foreach and while. The same rules apply to all of them.
not really important:
On a side, the if function in tcl works like the ternary operator in C: it returns a value. In fact you can do the following:
# It is unfortunate that this "give" function is not built in.
# We use it to return something from if without actually
# calling return:
proc give {x} {return $x}
set something [if {$x} {give "Very true indeed."} {give "Unfortunately false."}]