Critcl : args in procedure - tcl

I would like to replace a Tcl procedure by C procedure with Critcl.
Tcl procedure :
proc myProc {args} {...}
Critcl procedure :
critcl::cproc myProc {Tcl_Interp* interp Tcl_Obj* data} ok {...}
And this is how I use it :
myProc $value_1 $value_2 $value_3 ...
My question :
How to avoid this error *wrong # args: should be "myProc data"*, so that my values are grouped in a list and assigned to data

You could try using a ccommand instead of a cproc, as that let's you get the direct array of values (provided you skip the first word, which will be the command name). There is an example of this on the wiki at https://wiki.tcl-lang.org/page/Critcl+Examples but you'll probably also need Tcl_NewListObj to actually make the list as an entity.

Related

Meaning of a proc name ending with ::

In the tk code base I found the construct:
proc ::tk::dialog::file::chooseDir:: {args} {
Normally I would expect the procedure name after the last set of :: but here it is empty. Is this some sort of constructor in a namespace?
(Might look like a trivial question but I'm not a tcl programmer and need to know it to, automatically, generate some documentation.
Some more of the code (maybe gives some background, it is the beginning of the file)
namespace eval ::tk::dialog {}
namespace eval ::tk::dialog::file {}
namespace eval ::tk::dialog::file::chooseDir {
namespace import -force ::tk::msgcat::*
}
proc ::tk::dialog::file::chooseDir:: {args} {
variable ::tk::Priv
set dataName __tk_choosedir
upvar ::tk::dialog::file::$dataName data
Config $dataName $args
...
Normally I would expect the procedure name after the last set of ::
but here it is empty
The empty string is a valid name for a procedure in Tcl (as it for variables).
% namespace eval ::tk::dialog::file::chooseDir {}
% proc ::tk::dialog::file::chooseDir:: {args} { return "called!" }
% ::tk::dialog::file::chooseDir::
called!
% namespace eval ::tk::dialog::file::chooseDir { "" }
called!
% info procs ::tk::dialog::file::chooseDir::*
::tk::dialog::file::chooseDir::
I don't know the history behind these Tk internals, but a procedure named using the empty string might be the main procedure for the same-named namespace chooseDir (as a kind of naming convention), rather than just duplicating the name: proc ::tk::dialog::file::chooseDir::chooseDir {args} {;}. Or, it is because the entire directory-picking functionality is auto_loaded, which requires a proc (command) name rather than a namespace name?
automatically, generate some documentation.
Maybe, when harvesting a Tcl interpreter for pieces to document, take the containing namespace name chooseDir as the documented name of such a procedure?

Preventing referencing in a proc?

I would like to pass to a proc a variable name and use it
inside the proc.
problem is that passing argument into the proc converts the variable to its value:
set my_value [ list eee ttt yyy ]
proc my_proc { args } {
puts "MY ARGS IS :$args\n"
}
my_proc $my_value
MY ARGS IS :{eee ttt yyy}
I would like to get:
MY ARGS IS : my_value
thanks
Uri
Tcl is strict pass-by-value in semantics (it's implementation is pass-by-immutable-reference), but the value that you pass can be a name (just don't put $ in front of it, since to Tcl that always means “read from this variable, now”). In particular, you would do just this:
my_proc my_value
If you wanted to bind that name to a local variable so you can read and write it, you'd then do something like this (inside the procedure):
proc my_proc { args } {
upvar 1 [lindex $args 0] theVar
puts "MY ARGS IS :$args"
puts "THE VARIABLE CONTAINS <$theVar>"
}
You are thinking too hard. If you want my_value to be passed in, that's exactly what you do:
my_proc my_value
Tcl is very simple in this regard: if you want the name, use the name, and if you want the value, put a $ in front of the name.

Creating functions in TCL

Can any one help me in TCL programming, I am new to TCL
I would like to create functions like
employee_data Name() Dept() Tasks() ...
suppose i need execute from above function like employee_data Name() Tasks() ...
here i want skip Dept() arguments,
I tried to create function like but it does not work out..
proc employee_data {
Name (A B C....)
Dept (a b c....)
Tasks (s d f...)
} employee_data;
proc employee_data { Name($A $B $C) Dept($a $b $b) Tasks ($s $d $f) } {
Body...
}
Thank you very much.
I believe the basic misunderstanding is how you call/invoke Tcl functions/commands.
Unlike many other languages, where you invoke a function with func(arg1,arg2,"arg3",arg4) Tcl uses func $arg1 $arg2 "arg3" $arg4, where arg1, arg2 and arg4 are variables.
To define such a function, use proc. The syntax is
proc sum {a b} {
return [expr {$a + $b}]
}
a b is the arguments list. Note that you don't need to declare the function.
I don't exactly understand what you are trying to do here, but it looks more or less like a struct/class for me.
Just so as you know, Tcl and C++ have very different approaches to values and types. In particular, Tcl works almost entirely by logically-immutable references to values that are nevertheless type-mutable, which is very different to C++ (and many other languages, to be fair). True mutator operations (such as increments) actually create copies.
Another key difference is that in Tcl, everything is done by executing commands. That includes creating other commands. That proc? It's a call to a command (called proc) which immediately creates a procedure with the given name, arguments and body. There's nothing like declaration; stuff happens when you tell the code to make it happen. This sounds rather more complicated than it is.
How to pass list values into procedures
Suppose your Name was a list, you'd then pass the whole list value in (by immutable reference, so fast and safe) and the code inside could do whatever it wants without affecting the outside world. You'd then write that like this:
# Define
proc employee_data {Name ...} {
lassign $Name A B C
# ... do other processing ...
}
# Call
set Name {Aitem Bitem Citem}
employee_data $Name ...
You could also call with immediately-defined data; Tcl's entirely happy with this:
employee_data {Aitem Bitem Citem} ...
Passing in dictionary values
Dictionaries are very much like lists, except they map keys to values instead of being sequences.
proc employee_data {Name ...} {
dict with Name {}
# ...
}
set Name {A "foo" B "bar" C "grill"}
employee_data $Name ...
You can also pass a copy of the contents of an (associative) array as a dictionary value, like this:
employee_data [dict get Name] ...
Passing references
But suppose you wanted to mutate the outside world! To do that, you have to pass the name of the variable to change. You then use upvar to bind a local variable to the caller's variable so that you can do the modifications and have them stick. The upvar command lets you do in effect call-by-name, and it's highly magical.
proc employee_data {NameVar ...} {
upvar $NameVar name
# ... accessing $name as if it was whatever variable was passed ...
}
set Name {Aitem Bitem Citem}
# Note: *not* $Name! We want the name, not the contents!
employee_data Name ...
You can think of built-in commands like set and incr as working like this. And this works for associative arrays too.

How do I remove a Tcl procedure?

How do I remove a tcl procedure?
One can
unset a variable,
override an alias with interp alias {} myproc {} otherproc,
override a proc with one defined inside another namespace with namespace import -force.
But I did not find a way to make a procedure unknown.
Use rename to delete a proc
rename myproc ""
Example:
% proc myproc {} {
puts "hello world"
}
% myproc
hello world
% rename myproc ""
% myproc
invalid command name "myproc"
%

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