Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Curious about Tcl 1

Status
Not open for further replies.

MissouriTiger

Programmer
Oct 10, 2000
185
US
Hi there, I'm sticking my head in from a neighboring forum.

I'm a programming student, and am curious to know more about Tcl. I've read the stock/terse descriptions posted on the WWW, but want a little more info. I'd be grateful if someone would answer a few questions.

What kinds of things is Tcl good for (strengths & weaknesses). How does it compare to Perl?

Where do Tk and Expect come in?

I'm learning Java, and am finding it rather unwieldy when it comes to string manipulation. I'd like to find a more adept tool for working with strings. I'm really curious about utilizing multiple programming languages in a single project. Although I've worked with a few different languages, thus far I only used more than one language standard situations such as ASP development, or using SQL to hit a DB. I hear Perl & Tcl both referred to as "glue" languages that can connect disparate programs...

Well, I have ideas about writing an application in more than one language, taking advantage of the best features of each. How practical would it be for me to use Tcl for parsing strings (as part of a front end) before passing them on to a Java application? It seems like a pretty tricky prospect. Is it possible to hand data back & forth between the two directly in memory?

Any elucidation would be much appreciated.

_______________________________________
Constructed from 100% recycled electrons
 
Hi
You got the most of the information abt Tcl.
Okay Tcl is a RAD Tool.
U can use this tcl to build prototype of the application.
Tk is a Graphical Components.
You can use tk to build GUI Components or use existing ones.

Weakness as such i don't know. It is powerful tool to work with.
As u said it a glue language. You can use with other languages.
Any specific things u want know
Just ask me

Shyam Shyam
 
If you haven't already done so, I'd recommend visiting the Tcl Developer Xchange web site at
It provides a Yahoo-like catalog of information for Tcl, inlcuding extensions, tools, documentations, etc. In particular, the "Advocacy" navigation tab takes you to a section describing some of the advantages of Tcl.

For my money, some of the big "wins" for Tcl are:
[ul][li]Native Unicode support for internationalized applications[/li]

[li]Very easy GUI development with the Tk extension (and yes, Perl and Python have swiped Tk for their own use, but I still find Tcl's integration with Tk the easiest to use)[/li]

[li]Very easy network development with built-in TCP/IP support[/li]

[li]A built-in event loop, making event-driven programming a snap[/li]

[li]The ability, as an interpreted language to build and/or evaluate commands dynamically (This is great in conjunction with network-based applications. When I get to implement both sides of the conversation, I like to design messages as Tcl commands that I can execute on the receiving side. Which brings up the point of...)[/li]

[li]The ability to create "slave" interpreters, including safe slave interpreters for executing untrusted code (much like a Java sandbox model)[/li]

[li]Um... more that I'm forgetting at this moment...[/li][/ul]
As for your question regarding Tcl/Java integration, it's easy with the TclBlend extension. Check out for more information. But basically, TclBlend allows you to create Java objects, invoke methods, access data members, etc. from your Tcl script. Fairly easily, too. Here's an example from Steve Ball's book Web Tcl Complete in which he accesses a MD5 Java class as is (no code added on the Java side to interact with Tcl):

Code:
package require java
proc MD5 {message} {
    set md5id [java::new MD5]
    $md5id init
    $md5id updateASCII $message
    $md5id finish
    return [$md5id toString]
}

Hope this helps! - Ken Jones, President
Avia Training and Consulting
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
I am looking into tcl/tk (actually maybe just tk) as well. I have been told to stay away from tcl/tk when using it with another lanaguge(C/C++/Java) becuase it lacks performance and is very slow. Yet, some apps created in TCL that i have come across seem to be fast.

Avaitraining you noted that GUI developement is VERY easy. Would it be wise to use tcl/tk to build GUIs in C++ instead of using the OS' API? For example writing a win32 app in C++ with the win32 GUI coded in tcl/tk.

 
AviaTraining, thank you so much for taking the time to post such a thorough reply. I will explore the references you suggested.

Muchos Gratitudos! _______________________________________
Constructed from 100% recycled electrons
 
In reply to mitch_:

I've found that the people who say that Tcl is too slow fall into 2 categories:
[ol][li]Those who last used Tcl at version 7.6 or before[/li][li]Those who are highly partisan supporters of a scripting language that begins with the letter "P" :)[/li][/ol]
My opinion is that a programming language is simply a tool, and that the most reasonable approach is to use the tool most suitable to the job at hand. It's just that I've found Tcl to be a particularly useful tool for a variety of purposes, in part because of the reasons I listed above.

So, let's address the speed issue. First of all, versions of Tcl before 8.0 could be quite slow. Two reasons. One was that all data really, really was stored as strings. This changed in 8.0 where internally, information is stored in "dual-ported objects," which have both a string representation and a native representation. Tcl does a "lazy conversion" between the two formats on an as-needed basis, which speeds up math and list operations quite a bit relative to pre-8.0 versions.

The second reason that Tcl was slow was that it really, really did parse each line each time it came across it. Which meant that if you executed a procedure or a loop, Tcl parsed the contents over and over and over again. But as of version 8.0, Tcl implemented a byte-code compiler. The first time Tcl encounters a code block, it parses it and stores the byte-code version. The next time Tcl encounters the code block, it just executes the byte-code compiled version rather than re-parsing it all. We got a big performance win here as well.

Unfortunately, a lot of the scripting language "comparison" pages you see out there still refer to pre-8.0 versions of Tcl. And a lot of people keep parroting the information they heard 5 or 6 years ago, that "Tcl is slow."

Having said that, Tcl is an interpreted language, just like Perl and Python. And a program written in an interpreted language will never run as fast as a program written in a compiled language like C/C++. Just the nature of the beast. On the other hand, processors have gotten so fast these days, that is doesn't matter what language the program's written in, it usually runs fast enough. In fact, with a GUI-based program -- no matter what language it's written in -- most of the time the program is just sitting around waiting for the user to interact with it.

Another reason Tcl/Tk seems fast for GUI programs is that the actual implementation of the interface code is in C. So when you create and manipulate widgets, that's all handled at the C-level internally. It's just the actions that are performed in response to user actions (e.g., what does your program do after a user clicks a button) that is implemented in your Tcl code.

So, what tasks is Tcl not well-suited for? Two areas come to mind:
[ul][li]Heavy-duty math (e.g., big matrix manipulation, statistical analysis, etc.)[/li][li]Systems programming (device drivers, etc.)[/li][/ul]
But that doesn't mean that we have to toss Tcl out completely. Tcl is an extensible language, so we can implement the math-heavy or systems-control functions in C or Java, and then expose these functions as Tcl commands. We gain both the rapid application development and flexibility advantages of Tcl and the speed and fine control of C/Java.

How would I go about actually implementing a GUI-based project these days? Keeping in mind my Tcl bias :) I'd probably do something like this:

[ol][li]Get my preliminary specs based on the requirements docs (if they exist) or interviews with the project team.[/li]
[li]Whip up a prototype in Tcl. Depending on the complexity of the interface, you should be able to do this within 1 day to 1 week. Use it to get feedback on the UI design and the general product functionality.[/li]
[li]Based on the feedback, put together my implementation specs and get sign-off. This might take some iterations with the prototyping stage to get general agreement on features.[/li]
[li]Productize my interface in Tcl/Tk, which shouldn't be too difficult given the prototype.[/li]
[li]Start implementing functionality in Tcl, except for functionality I know can't or shouldn't be. Examples would be systems/hardware interaction code, heavy-duty math, and existing C/Java libraries.[/li]
[li]Write whatever C or Java code I knew I needed.[/li]
[li]Use TclBlend to incorporate the Java into my Tcl scripts.[/li]
[li]Use SWIG ( to generate "wrapper" functions for my C code and any existing C libraries to expose the C functions as Tcl commands.[/li]
[li]Do performance testing. If I find any bottlenecks attributable to my Tcl code, I'd try to optimize my Tcl implementations. Only if it was proven that my Tcl versions were too slow would I look at implementing those sections in C/Java. But in most cases, it turns out that it's fast enough![/li]
[li]Etc., etc., with the rest of the standard development process.[/li]
[/ol]
So in essence, I'd take a Tcl-centric approach to development because of its speed of development and flexibility, and fall-back to C/Java only when necessary. Tcl also lends itself to easy white-box and black-box testing (especially when the tests are driven by Tcl or Expect scripts!). In fact, I know of several organizations that use Tcl/Expect as their test harness, even for C/Java libraries; they just use Swig or TclBlend to expose the library's functionality into a more easily tested form. - Ken Jones, President
Avia Training and Consulting
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
My main problem with Tcl, that there is no complex data structures (hash of hash...) because there are no references. Everything is stored in strings, that's why everything is slow... :(
 
kgergely wrote:

Everything is stored in strings, that's why everything is slow...

This is exactly what I was talking about in my previous post about people parroting old information they've heard about Tcl. Although, to the Tcl script writer, it looks as though everything is stored as a string, as of Tcl 8.0, Tcl internally uses the "dual-ported objects" I described in my earlier post. Tcl 8.0 was released August 18, 1997, so it isn't as though this is new information; but you sure don't hear much about it on the various Perl vs. Tcl or Python vs. Tcl comparison pages that partisan supporters of other scripting languages make available.

As to kgergely's comment:

My main problem with Tcl, that there is no complex data structures (hash of hash...) because there are no references.

Not true. Consider:
[ul][li]The name of a variable can be any string value (yes, even a NULL string)[/li][li]The value of a variable can be any string value[/li][/ul]
And so, it looks as though the value of a value can be the name of another variable. Which indeed it can. You just need to force an extra round of variable substitution with the set command. (Calling set with only one argument causes it to return the value of the variable given.) Thus in the following, the variable var is functioning similarly to a pointer, holding a reference to the variable whose name is x:

[tt]% set x "The value of x"
The value of x
% set var x
x
% puts "The value of \"x\" is: [ignore][set $var][/ignore]"
The value of "x" is: The value of x[/tt]

You can "pass by reference" to a procedure by passing the name of the variable as an arguments, and then use upvar within the procedure to create an alias to the variable passed. (Check out the documentation for a complete description of upvar.) So, we could write a little procedure like this:

[tt]% proc printit {varname} {
upvar $varname var
puts "You passed in the variable $varname"
puts "The value of $varname is $var"
}
% printit x
You passed in the variable x
The value of x is The value of x
[/tt]

And so you can store the name of an array variable as the value of another variable, you can create lists of array names, etc. as complex as you like.

If you want to start putting together some more complex data structures, here are some ideas:

[ol][li]Store the information in an array using a technique I call "compound keys." Say that for a company I want to store the name and salary of all of my employees in a data structure. Using the employee IDs as unique identifiers for the employees, I can store each employee name and salary as separate elements in the array by concatenating the employee ID to a "field name" like this:

[tt]set id 0007
set emp($id-name) "Ken J."
set emp($id-salary) "10000"
set id 0020
set emp($id-name) "Lee B."
set emp($id-salary) "12000"[/tt][/li]
[li]Store the information for each record as a list in an array (that is, create an array of lists). Using the same example as above, we could store the employee's name and salary as a 2-element list, and use the employee IDs as my array keys. For example:

[tt]set emp(0007) [list "Ken J." 10000]
set emp(0020) [list "Lee B." 12000][/tt][/li]
[li]Use a separate array for each item of information, and coordinate the information with common keys. So continuing our above example, create separate name and salary arrays, and use the employee IDs as keys for both arrays:

[tt]set name(0007) "Ken J."
set salary(0007) 10000
set name(0020) "Lee B."
set salary(0020) 12000[/tt][/li]
[li]If you're really craving the types of nested structures you can create in C, then I highly recommend getting the Tcl extension [ignore][incr Tcl][/ignore]. [ignore][incr Tcl][/ignore] adds object-oriented programming support to Tcl. You can create classes, create objects from classes, use inheritence, etc. But for the job at hand, we could ignore most of the object-oriented hooha and simply create data structures as classes with only public data members. Using our classic employee database example, we can do this:

[tt]% package require Itcl
3.2
% ::itcl::class Employee {
public {
variable name
variable salary
}

# The following constructor is optional,
# but lets us initialize data members
# when creating the object

constructor {args} {
eval configure $args
}
}
% Employee 0020 -name "Ken J." -salary 10000
0020
% Employee 0007 -name "Lee B." -salary 12000
0007
% 0020 cget -name
Ken J.
% 0007 cget -salary
12000[/tt]

You could create arrays or lists of these "structured objects", store the names of other structured objects as values to get nested structures, etc.[/li][/ol]
Okay, anyone else want to tell me you can't do data structures in Tcl? :) - Ken Jones, President
Avia Training and Consulting
866-TCL-HELP (866-825-4357) US Toll free
415-643-8692 Voice
415-643-8697 Fax
 
Just a note on the tcl extension; Expect since you asked for it and no one mentioned it..
It adds a subset of four base commands to the(really three)
tcl command set and allows for quick and efficient interaction with ordinarily difficult to automate programs and procedures.
For systems work this tool is invaluable.

As an example:
A procedure from a script that monitors logfiles and
reacts by sending intelligent mail.
I wouldn't have the first idea how to do this in C, but
it is very easy here.

proc my_warn { db } {
set timeout 40
set all {}
set our_pots [open "$db" r]
while {[gets $our_pots L] != -1} {
lappend all $L
}
trouble $all

foreach P [lsort $all] {
spawn netcat -vv $P 25
set proc_id($P) $spawn_id
puts "[array size proc_id]"
expect {
-i $proc_id($P) -re "(220).+" {
send_user "$expect_out(buffer)\n"
switch -re -- $expect_out(buffer) .*pat1.* {
send_user "It is mailer at $P\n"
mail_proc -sendmail $proc_id($P)
del_array_val $proc_id$P)
} .*pat2.* {
send_user "It is mailer at $P\n"
mail_proc -postfix $proc_id($P)
del_array_val $proc_id($P)
} .*pat3.* {
send_user "It is mailer at $P\n"
mail_proc -msmail $proc_id($P)
del_array_val $proc_id($P)
}

timeout {
puts "Host $P does not respond.."
continue
}
}
}
}

 
Sorry for not to read the whole thread.
Ok, you can trick with variable names, but the namespace will be dusted, and you must take care the variable names.
When using the array(key1-key2) technique, it is not so efficient to search.
And listing all the key1-s? brrrr

Storing arrays in strings also not very efficient, because has the overhead, that you must build your data (at least the code is not so clean... & threads, event driven programming... unconsistent data).
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top