Escolar Documentos
Profissional Documentos
Cultura Documentos
COMPUTER SCIENCE DEPARTMENT
A LOOK AT TCL
A paper presented to:
DAVID HANSEN
In partial fulfillment of the requirements for the course:
STRUCTURES OF PROGRAMMING LANGUAGES
(CSIS 420)
ZACHARY HAYES
November 29, 2006
TABLE OF CONTENTS
1.0 Introduction 1
2.0 Historical Background 1
3.0 Syntactic Structure 2
3.1 Words 2
3.2 Commands 3
3.3 Evaluation 3
3.4 Substitution 4
3.4.1 Backslash Substitution 4
3.4.2 Command Substitution 4
3.4.3 Variable Substitution 5
3.4.4 Order of Substitution 5
3.4.5 Substitution and Word Boundaries 5
3.5 Double Quotes 6
3.6 Braces 6
3.7 Comments 6
4.0 Variables 7
4.1 Basic Variables 7
4.2 Abstract Data Types 8
4.2.1 Arrays 8
4.2.2 Lists 9
5.0 Flow of Control 9
5.1 Eval Command 10
6.0 SubProgramming 10
7.0 Personal Experience 11
Appendix A: Example Tcl Code A1
A.1.1: n!A1
A.2.1 Structured Information SorterA2
A.3.1 Random Text Generator A3
ABSTRACT
Tcl was developed by John Ousterhout in the early 1980’s. He never expected it to grow
as much as it has. Tcl continues to attract more uses each year and has received the ACM
Software System Award for "a software system that has had a lasting influence". Being
an embeddable language Tcl has many new extensions continually coming out every
year. However no one can replace the easy to learn, general package, of Tcl. Tcl has all
that you would need to develop full blown applications. Over the course of the paper I
will provide a brief look into Tcl /Tk with an emphasis in Tcl so that we may understand
the phenomenon that is Tcl.
1
1.0 Introduction
Have you ever been so frustrated with your own, poorly written, code? If so did
you develop your own language based off that aggravation? Tcl, pronounced “tickle,”
was originally born out of frustration by programmers devising their own “poorly
written” languages intended to be embedded into applications. 1 Tcl is a very simple
scripting language that can be picked up in a matter of hours by anyone familiar with
programming. Tcl (Tool Command Language) received its name based on its intended
usage as an embeddable command language. 2
Tcl is considered a weak functional language. 3 This is because TCL has many
features that could be considered imperative. With the right extensions, one could easily
make it object oriented, or even logical, if the extension were written. Tcl has higher
order functions and functional abstractions built into the language; however, Tcl is not
widely used in this manner. Tcl started out as an experiment because someone was
embarrassed by his code. Tcl has many similarities to LISP, C, and the UNIX shell. 4
2.0 Historical Background
Professor John Ousterhout at the University of California at Berkley wrote Tcl in
the early 1980’s. The idea for Tcl grew out of Ousterhout’s work designing tools for
integrated circuits. At that time, there was not much invested in the command languages
used during development; most were weak, quirky, nonreusable languages. Every tool
ended up with its own uniquely written command language, which Ousterhout found
embarrassing. 5
In 1987, Ousterhout got the idea for an embeddable command language. Thus
began his work to create an interpreted language with library packages that could be
reused for many different applications; he also envisioned generic facilities, such as
variables, procedures and control structures. As Ousterhout explains:
The notion of embeddability is one of the most unique aspects of Tcl, and it led me to the
following three overall goals for the language:
1) The language must be extensible: it must be very easy for each application to add its
own features to the basic features of the language, and the applicationspecific
features should appear natural, as if they had been designed into the language from
the start.
2) The language must be very simple and generic, so that it can work easily with many
different applications and so that it doesn’t restrict the features that applications can
provide.
3) Since most of the interesting functions will come from the application, the primary
purpose of the language or to integrate or “glue together” the extensions. Thus the
language must have good facilities for integration. 6
1
John Ousterhout Tcl Developer Xchange “History of Tcl” October 2005, 28 October 2006, ActiveState
http://www.tcl.tk/about/history.html
2
Ibid.
3
Wiki.tcl.tk “Tcl Heritage” 16 July 2006. 28 October 2006 http://wiki.tcl.tk/985
4
Ibid.
5
Ousterhout http://www.tcl.tk/about/history.html
6
Ousterhout http://www.tcl.tk/about/history.html
2
After Ousterhout stopped working on designing tools, Tcl became a personal academic
experiment. Little did he know how well it would expand.
In 1990 Tcl became open to the public after Ousterhout presented a paper on Tcl
at the UNENIX Conference and found many people were interested in getting a copy of
Tcl. Shortly after the conference he began working on Tk, a graphical user interface
extension to Tcl, which was also available to the public. From 1989 to 1993, Tcl/Tk
popularity grew an order of magnitude each year, expanding a dozen users to several tens
of thousands by 1993. This growth was due to the fact that Tk was the easiest way to
create graphic user interfaces in UNIX (which at the time was the only thing Tcl/Tk ran
on) and also because of Tcl’s embeddable nature. 7
A good portion of development on Tcl actually took place in 1994 when
Ousterhout left his position at Berkeley and began working for Sun Microsystems in
order to make Tcl a universal scripting language for the Internet. In 2005, Ousterhout
recalled some of the advancements made during his time at Sun:
The additional resources provided by Sun allowed us to make major improvements to Tcl
and Tk. Scot Stanton and Ray Johnson ported Tcl and Tk to Windows and the Macintosh,
so that Tcl became an outstanding crossplatform development environment; today, more
than twothirds of Tcl downloads are for Windows. Jacob Levy and Scott Stanton
overhauled the I/O system and added socket support, so that Tcl could easily be used for
a variety of network application. Brian Lewis built a bytecode compiler for Tcl scripts,
which provide speedups of as much as a factor of 10x. Jacob Levy implemented SafeTcl,
a powerful security model that allows untrusted scripts to be evaluated safely. We added
many other smaller improvements, such as dynamic loading, namespaces, time and date
support, binary I/O, additional file manipulation commands and an improved font
mechanism. 8
In 1998, Ousterhout left Sun and started his own business called Scriptics to focus
entirely on Tcl; within a month, half of the Sun Tcl team had joined him and began
development on TclPro, a retail version of Tcl. In the spring of 1998, Tcl won the ACM
Software System Award; awarded each year for a software system that has had a lasting
influence. 9
3.0 Syntactic Structure
There are eleven important rules that define the syntax of the Tcl language. These
eleven rules define the core of the language, if one masters these rules; he is on the way
to mastering Tcl. The purpose of these rules is to help the programmer understand how
the language works, variable declaration, control structures, and processes.
3.1 Words
7
John Ousterhout Tcl Developer Xchange “History of Tcl”, October 2005. 28 October 2006, ActiveState.
http://www.tcl.tk/about/history.html
8
Ibid.
9
Ibid.
3
Tcl code consists of Strings; each word in the String is called a “word.” Words of
a command are separated by white space, with the exception of newlines which indicate
the conclusion of a command. 10 Each word may have an arbitrary string value, and the
white space is not part of the word unless quoted. 11
Aword
“This is a word”
Multiple words
3.2 Commands
Everything in Tcl is a string containing commands. Each command consists of
one or more words with the first word being the name of the command, and each
additional word being the arguments to the command. Commands are separated by
semicolons and newlines unless the String is quoted.
3.3 Evaluation
Tcl evaluates command in a twostep process, parsing and execution. 12 In the
parsing step Tcl interprets the syntactic rules and divides every command into words and
perform substitutions. Every command is parsed in exactly the same way; during the
process the interpreter does not give any meaning to the value of the words. The parser
simply replaces variables, such as $a; however the interpreter does not know or care
what the variable is.
The execution step of the evaluation assigns meaning to the words. As stated
above, the first word in a command is the name of the command being executed. During
the execution step the interpreter checks to see if a command by that name is defined.
Tcl invokes a command, passing each additional word to the command procedure. Then
the procedure interprets the words as it pleases. This process is shown in figure 1.
10
Develop Connection “Tcl(n): Tcl BuiltIn Commands,” November 6, 2006
http://developer.apple.com/documentation/Darwin/Reference/ManPages/mann/Tcl.ntcl.html
11
John Ousterhout, Tcl and Tk Toolkit (Partial Draft). AddisonWesley Publishing Company, Inc 1993, 26
12
Ibid. 26
4
Figure 3.1 Tcl command evaluation. 13
3.4 Substitution
One of the most important aspects of Tcl is substitution. There are three types of
substitutions: backslash substitution, command substitution, and variable substitution.
Substitution simply replaces some word with some other value. Substitution can occur at
any point in a command, including the name of the command; there can be an arbitrary
number of substitutions within a single word or command. 14
3.4.1 Backslash Substitution
Backslash (‘\’) substitution in Tcl is exactly like how Java/Ctype languages
handle substitution. In most cases, the symbol following the backslash will appear as an
ordinary character in a word. For example “\{“ appears as a literal “{“ in the word.
There is nothing special about this type of substitution: it is mainly used for formatting
words, e.g., when printing a dollar amount “\$” would be used for a $ to literally appear.
3.4.2 Command Substitution
Command substitution causes a command to be executed by another command.
set x [expr 1 + 3]
13
Ibid 27
14
Ibid 28
5
Is an example of this; the first command sets a variable x to the result of the expression
[expr 1 + 3]. Any character between the brackets ([ ]) must constitute a valid Tcl
command. Command substitutions may appear anywhere in a word and there may be
more than one substitution in a single word. 15 The substitution of commands is done
recursively by the Tcl interpreter. 16 An example of this can be found in the Random Text
Generator discussed in Appendix A.3.
3.4.3 Variable Substitution
Words that have a leading dollar sign (‘$’) are interpreted as variable after the set
command has been issued.
set a 3; puts “$a”
Sets the variable ‘a’ to 3 and prints it out. Notice in the print statement how the ‘a’ has a
leading $, therefore it replaces $a with 3 and prints 3. Similar to command substitution,
variable substitution may appear anywhere in a word, and there may be more than one
substitution in a single word. 17
3.4.4 Order of Substitution
Substitution can be confusing if one is not used to it. However,
Ousterhout discusses two rules that explain how substitution is performed:
A typical scenario is for a users to be surprised at the behavior of a script because a
substitution didn’t occur when the user expected it to happen, or a substitution occurred
when it wasn’t expected. However, I think you’ll find Tcl’s substitution mechanism to be
simple and predictable if you just remember two related rules:
1. Tcl parses a command and makes substitutions in a single pass from left to
right. Each character is scanned exactly once.
2. At most, a single layer of substitution occurs for each character; the result of
one substitution is not scanned for further substitution.
Tcl substitutions are simpler and more regular than you may be used to if you’ve
programmed with UNIX shells (particularly csh) 18
So each substitution occurs lefttoright and each one is evaluated before continuing. For
example:
set y [set x 0][incr x][incr x]
(Note: incr. increases value of x by 1.) This example will always set the variable ‘y’ to
the value 012. This tells us a lot about the language and its scope. 19
3.4.5 Substitution and Word Boundaries
15
Ibid. 29
16
Developer Connection “Tcl(n): Tcl BuiltIn Commands” November 6, 2006
17
Ibid.
18
John Ousterhout, Tcl and the Tk Toolkit (Partial Draft) AddisonWesley Publishing Company, Inc 1993,
34.
19
Developer Connection “Tcl(n): Tcl BuiltIn Commands” November 6,2006
http://develper.apple.com/documentation/Darwin/Reference/ManPages/mann/Tcl.ntcl.html
6
Substitutions do not affect the word boundaries of a command. During the
substitution process, the value that is being substituted becomes part of the word it is next
to, even if the substitution contains special characters, such as white space. 20
3.5 Double Quotes
There are times when a programmer wants a word to contain white space, e.g.
when trying to set a variable to a string of words. This is accomplished by placing double
quotes around the words. Double quotes are not the only way to do this; it is important to
recognize this since there are different interpretations depending on how words are
connected, either with double quotes or with braces.
If the first character of a word is a double quote (“) then the word is terminated by
the next double quote character. If any special character appears in between the two
double quotes (semicolons, closing brackets, white space, etc). It is treated as any other
ordinary characters and literally included in the word. All three types of Tcl substitution
also take place while in between double quotes. 21
3.6 Braces
The alternative to double quotes is the brace (‘{‘). Similar to double quotes, the
word will terminate by the matching closing brace. Unlike the double quotes, braces may
be nested. The main difference between the double quote and the brace lies with
substitution. No substitutions are performed on any characters in the word when using
braces. Everything loses its special interpretation while in the braces, meaning the word
typed between the braces is the literal word you get. 22 Braces are usually only used in
special cases, such as the use of the eval command.
3.7 Comments
A comment always begins with a hash mark (#) at the beginning of a line; note
that the beginning of a line follows a new line character or a semicolon. The hash mark
must be the very first nonblank character on the line. This is very similar to how
comments are done in languages such as Python except that comments must be on a new
empty line. 23
An interesting side effect of comments is if you have special characters inside a
comment, the interpreter will not always behave as expected, thinking the special
character is not inside of a comment. It is preferred to put comments in a particular form:
# [this is a comment]
20
Ibid.
21
Ibid.
22
Ibid.
23
John Ousterhout, Tcl and Tk Toolkit (Partial Draft) AddisonWesley Publishing Company Inc. 1993, 33
7
The reason for this is to eliminate problems caused by a special character within the
comment.
4.0 Variables
It is not uncommon for people to call Tcl and a string oriented language, and for
good reason. In Tcl, every single data type is a string on the Command String layer; this
includes: numbers, characters, lists, code, and dictionaries. 24 The interpreter reads these
strings and depending on what kind of command is being executed, it interprets the string
as a different type, such as an integer. Even though there is only one data type in Tcl
there are two different kinds of variables: basic variables, such as traditional strings, and
arrays and lists. 25
4.1 Basic Variables
Basic variables are very simple; they consist of only two things, a name and a
value. Both things can be arbitrary strings. Some examples of variable names and
variable values are:
“This is a Variable”
!@#
22
All of these are treated as strings and any of them could be the variable name or
variable value. 26 There are few constraints on either the variable name or variable value.
This means the variable names may be as long as one likes and may contain nearly any
character; an exception is that variables can not start with ‘{‘, unless the variable name is
enclosed in quotes. To access a variable with a unique name, the $ is placed in front of
the variable name. Like JavaScript or PHP, Tcl has dynamic type binding; this permits
the programmer to not specify the type when declaring a variable.
Tcl uses the command set to create, read, and modify variables. The set
command takes one or two parameters, each yield a different result. The first argument is
always the name of the variable. The second argument is an optional value for the
variable. If no second argument is given, set reads the variable and returns the value it
holds, if any. This is a key command to Tcl that is often used. Here is an example of the
set command:
set a {Eggs: $2.18/dozen}
>> Eggs: $2.18/dozen
set a
>> Eggs: $2.18/dozen
set a 44
24
Salvatore Sanfilippo Tcl Wise: Guide to the Tcl Programming Language (PreRelease)
http://www.invece.org/tclwise/frontcover.html
25
John Ousterhout, Tcl and Tk Toolkit (Partial Draft) AddisonWesley Publishing Company Inc. 1993, 37
26
Ibid. 37
8
>> 44
In the above sample, the code sets ‘a’ to the string “Eggs: $2.18/dozen”, then reads the
value of ‘a’ and finally modifies the value, changing it to the string “44”. 27
Tcl variables can represent anything: numbers, list, scripts, etc.; however, they are
always stored as strings. Tcl is a typeless language, so there is no need to declare the
variables before setting them. 28 This makes Tcl variables very easy to understand,
because variable interpretation is done under the covers by Tcl.
4.2 Abstract Data Types
Tcl has two abstract data types, the Array and the List. These two abstract data
types are at the very core of the language, allowing the programmer to keep collections of
strings in a certain format and use them in their respective ways.
4.2.1 Arrays
The Array is a collection of elements with a name and a value. The name of an
array element also has two parts, the name of the array and the name of the element
within the array. Similar to basic variable array names and element names, the value may
be any arbitrary string. Many programmers associate the Tcl array with an associative
array, hash map, or dictionary which often appears in other languages. 29 Similar to the
basic variable, you use the command set to assign a value to the array:
array set “capital(New Mexico)” “Santa Fe”
>> Santa Fe
As expected, you may think this is exactly the same as a basic variable, the variable
name is “capital(New Mexico)” and the variable value is “Santa Fe” and you would be
absolutely correct. The difference between the two is the commands that can be used on
the variable. For example there is a copy function that can be applied to arrays:
array set B [array get A]
Means get the array A and set it to B. This is just one of the many helpful commands that
are associated with arrays. 30
Arrays are singularly dimensioned; however, there is a way to represent arrays as
multidimensioned. The idea behind this is to create an array and set the name of the
element to:
set “matrix(index1,index2)”
27
John Ousterhout, Tcl and Tk Toolkit (Partial Draft) AddisonWesley Publishing Company Inc. 1993, 37
28
Ibid. 38
29
Ibid. 39
30
Wiki.tcl.tk “Tcl Heritage” 16 July 2006. 28 October 2006 http://wiki.tcl.tk/532
9
This is actually an array with the key being “index1,index2”. 31
4.2.2 Lists
The other type of structure is the list, which is simply a collection of strings. This
allows the user to collect any number of values in a single location. Lists are represented
as strings with special structures, so one can store lists into a variable, nest them into
another list, and even type them to commands. In other words, a list is simply a string
separated by spaces or tabs.
set myList [list this is hello world]
>> this is hello world
lsort myList
>> hello is this world.
There are many special features that can be only performed on lists, such as sorting,
getting the length, or getting a certain element with the list. 32 Unlike most traditional list
we can access them by index with the lindex command, for example:
lindex “this is a list” 1
>> is
lindex “this is a list” end
>> list
The above example grabs an element from a list. Notice that list can be set to a variable
or indexed on the fly. Also, indexing starts at zero, similar to languages such as Java.
We also have a keyword, “end,” which is the index to the end of the list. The Tcl list has
many unique commands built in, making lists very powerful tools.
5.0 Flow of Control
The flow of control statements in Tcl are very similar to the control structures found
in C programming language and command line languages like csh. These statements
include, if, while, for, foreach, switch, and eval. The major difference is that each one is
a command that takes a different number and type of arguments.
if {cond_1} {script_1} elseif {cond_2} {script_2} else
{script_3}
This is an example of the if command in Tcl, which takes an arbitrary number of
arguments (words) that are parsed in a way that control flow similar to the if statement in
C. Similar to the looping commands, they are commands and take arguments which the
Tcl interpreter parser breaks up and executes like their C counterparts.
31
John Ousterhout, Tcl and Tk Toolkit (Partial Draft) AddisonWesley Publishing Company Inc. 1993, 41
32
Ibid. 5152
10
5.1 Eval Command
One of the more unique control structures is the eval command. The purpose of
the eval command is for creating and executing Tcl scripts on the fly. A Tcl script is
multiple Tcl commands put together. The most important use of eval is to force another
level of parsing. As mentioned earlier, Tcl parses and substitutes only once; however
with the eval command multiple levels of parsing can be achieved. Suppose one wanted
to remove a list of variables:
set myList [list varA varB ...]
foreach I $myList {unset $i}
becomes:
set myList [list varA varB ...]
eval unset $myList
with the eval command a command can be executed over an entire list, if set up
properly. 33 Many Tcl’ers (a nickname for those that use Tcl) think that this is a dangerous
or bad practice because of its double substitution; however, it does simplify some
operations in the language. 34
6.0 SubProgramming
Most usable Tcl programs use procedures. Procedures provide a quick and easy way
to prototype new features in applications. Tcl procedures make for easy reuse.
Procedures are similar to methods or functions as seen in other languages, with similar
syntax as Java.
proc name {argList} {script}
Often times Tcler’s will rewrite procedures that run often in C to increase the
performance of the given procedure. Custom made procedures with the eval command
make a very powerful combination.
The scope of a variable inside of a procedure is always local to the procedure
including the arguments that are passed into the procedure, which means the value must
be returned for the value to leave the procedure. This can be done in two ways, explicitly
with the command return, or implicitly by defaulting to the result of the last line executed
in the procedure.
There are many unique things that a programmer can do with procedures and also
many exceptions to the scoping of procedures. For example, one can create a global
variable with the keyword “global”, but you must type “global varName in any procedure
that will know of the value. Other keywords include: upvar or uplevel, which are used
33
John Ousterhout, Tcl and Tk Toolkit (Partial Draft) AddisonWesley Publishing Company Inc. 1993, 67
68
34
Wiki.tcl.tk “Tcl Heritage” 16 July 2006. 28 October 2006 http://wiki.tcl.tk/1017
11
for accessing variables outside of the scope of the procedure. These keywords can be
used for writing custom control structures. 35
7.0 Personal Experience
Tcl is an amazingly easy language to learn and develop software with, even more so
then Python, which is often considered an easy language. Over the course of three
months, I have learned a lot more about programming through writing some very simple
programs in Tcl. I have enjoyed learning Tcl more than any other programming language
because of its simplicity, and how easy it was to learn and understand commands.
One of the more interesting things I learned about the language is that it is very
expandable and easy to change the use statements to better fit my individual style. For
example, if I do not like the “if” keyword for an 'if' control structure in Tcl, I can change
it to the “hi” keyword by:
rename if hi
So, a programmer would be able to make the syntax more understandable to the user.
This can be very good for writability but by doing so you sacrifice readability making it
nearly impossible for others to read. Although it is very neat, I would suggest sticking to
the command names that are built into the language.
Active Tcl, the distribution I used, has a builtin Tcl interpreter for the Linux
command line. This allows users to execute Tcl commands on the fly from the command
line, making testing things in Tcl very simple. However it is not the only way to execute
a Tcl program; the commandline interpreter has an optional argument, which is a name
of a Tcl file that you want to execute. These are done using the tclsh <filename.tcl> in
the Linux command line. There are Windows distributions of Tcl; however, for my
experience I stuck to Linux.
Tcl is an incredible language whose popularity has grown dramatically ever since
its release. I have only scratched the surface of all the language can do. I would
encourage anyone who is interested to advance their knowledge of Tcl/Tk, for you may
see it in your future work place.
35
John Ousterhout, Tcl and Tk Toolkit (Partial Draft) AddisonWesley Publishing Company Inc. 1993, 69
75
A1
Appendix A: Example Tcl Code
The following are some basic example of what code looks like in Tcl, using some
very basic problems. Tcl code can be written on a single line if one wishes however for
clarity I will try to break it up the best I can so you can clearly see some of the amazing
features of Tcl.
A.1.1: n!
Problem: A recursive factorial program that accepts a single integer n as input and
outputs n! Input is passed to the program as a commandline parameter.
A.1.2 Solution
###################################################
# A procedure that find the factorial of a number
#
# INPUT: n, the number we are getting the factorial for
# OUTPUT: the factorial of n
###################################################
proc fact n {
#if they put a negative number no
#solution exist
if { $n < 0 } { return "NonExistent" }
#check if the number is the base case,1.
if { $n == 1 || $n == 0 } {return 1}
#call itself recursively multiplying the solution by
#the current number
return [expr $n * [fact [expr $n1]]]
}
#check if the user gave an argument via command line
#if not: print a usage statement
#otherwise: get the factorial of the number
if {$argc != 1} {
#prints a usage statement to the console
puts "Usage: tclsh fractorial.tcl \$num"
} else {
#set the number to the user inputted value
set num [expr [lindex $argv 0]]
#print out to the console what the factorial of
# n is.
puts "The factorial of $num is [fact $num]"
}
A.1.3 Sample Inputs
$ tclsh factorial.tcl
$ tclsh factorial.tcl 5
$ tclsh factorial.tcl 5
A2
A.1.4 Sample Outputs
Usage: tclsh fractorial.tcl $num
The factorial of 5 is 120
The factorial of 5 is NonExistent
A.2.1 Structured Information Sorter
Problem: A program that keeps track of information about Persons. A Person has a
“character string” attribute called name and an “integer” attribute called age. The
program should reads a commadelimited name/age pairs from a file and populate the
program with a collection of Persons. It then sort the set by name, outputting the name of
each Person in sorted order, and output the average age of all the Persons.
A.2.2 Solution
#create a list of people
set people [list]
#initialize variables
set ageSum 0
set averageAge 0
set size 0
#Constants
set _NAME 0
set _AGE 1
#Check that a file was given
#if not: print usage statement
if {$argc != 1} {
puts "Usage: tclsh db.tcl \$filename"
} else {
#check to see if the file given exist,
#if not: print "file does not exist"
if {[file exists [lindex $argv 0]]} {
#open a file (file name that is given)
set filename [lindex $argv 0]
set infile [open $filename r]
#go through the file reading each line.
while { [gets $infile line] >=0 } {
#for each line trim all leading and trailing white
#space and then split the line at the ','s and
#add the data to the people list
lappend people [split [string trim $line " "] ',']
}
#make a copy of people that is sorted (sort the people by name)
set sortedPeople [lsort index $_NAME $people]
#get the size of the list (# of people in list)
set size [llength $sortedPeople]
A3
#add up all the peoples ages
for {set i 0} {$i < $size} {incr i} {
set ageSum [expr $ageSum + [lindex [lindex $sortedPeople $i]
$_AGE]]
}
#get the averageAve
#Note: * 1.0 on the bottom makes it not round
set averageAge [expr ($ageSum) / ($size * 1.0)]
#print out the names of the people in the list
puts "PEOPLE IN LIST"
puts ""
for {set i 0} {$i < $size} {incr i} {
puts [lindex [lindex $sortedPeople $i] $_NAME]
}
#print the average Age of the People in my Collection
puts "The average age of the people in the list is: $averageAge"
} else {
#no file exist let user know
puts "No such file exists"
}
}
A.2.3 Sample Input File
Hansen,7
Smith,82
Flintstone,23
Schlablotnik,39
Doe,45
Smith,19
Jones,34
A.2.4 Sample Output File
PEOPLE IN LIST
Doe
Flintstone
Hansen
Jones
Schlablotnik
Smith
Smith
The average age of the people in the list is: 35.5714285714
A.3.1 Random Text Generator
Problem: use grammars to generate somewhat random output (in contrast to a compiler
which is a sentence recognizer). The idea is that we can take a grammar where each
A4
string of the form <string> is a nonterminal symbol that can be replaced using one of the
productions in the grammar. The file is filled with 'productions' such as:
{
<conjunction>
and ;
but ;
yet ;
}
Where:
· each production is bracketed with {}
· the first line in each production holds the name of the nonterminal lefthandside
of the production (i.e., <conjunction> in the example above)
· each of the possible productions follows, terminated by a ';' (though shown on
separate lines this is not a requirement)
So the production above corresponds to <conjunction> ::= and | but | yet. Note
that the first production in the grammar file will always be the 'start' symbol for the
grammar defined by that file.
The program reads one of these grammar file (provided as a commandline argument)
and then generates text by starting with the start symbol and generating output by
replacing each nonterminal with a randomly chosen production for that nonterminal.
Obviously the production chosen may be a mixture of terminals and nonterminals so the
process continues until there are no more nonterminals to process. In addition, we can
weight the probability of a particular production being chosen by repeating it more than
once in the list of productions for a particular nonterminal. Productions can be
recursive, but must have at least one nonrecursive form to prevent infinite loops.
A.3.2 Solution
#imports the Stack namespace
source Stack.tcl
#return true if word is a nonterminal symbol
proc isNonTerminal word {
return [regexp \<*\> $word]
}
#return true if word is a nonterminal symbol
proc isTerminal word {
return [expr ![isNonTerminal $word]]
}
# [sets up our associative array]
proc getMap {filename} {
set map [list]
set options [list]
set _ON 1
set _OFF 0
set flag $_OFF
set text ""
set infile [open $filename r]
A5
# [go through the file reading each line.]
while { [gets $infile line] >=0 } {
# [starts the grammar parsing]
if [expr ![string compare [string trim $line " "] "\{"]] {
set flag $_ON
set start $_ON
set text ""
set $options [list]
} else {
# [if its the first line after we begin this is a terminal]
if {$flag && $start} {
lappend map [string trim $line " "]
set start $_OFF
} elseif $flag {
set text ""
set options [list]
set text [string trim $line " "]
# [for each line after the starting line, add ]
# [the line into a list]
while {[gets $infile line] >=0 && $line != "\}"} {
set text [concat $text [string trim $line " "]]
}
# [associate the nonterminal symbol with the list we created]
set options [split $text ";"]
set size [llength $options]
lappend map [lrange $options 0 [expr $size 2]]
set flag $_OFF
}
}
}
return $map
}
set generatedText ""
#Check that a file was given
#if not: print usage statement
if {$argc != 1} {
puts "Usage: tclsh db.tcl \$filename"
} else {
#check to see if the file given exist,
#if not: print "file does not exist"
if {[file exists [lindex $argv 0]]} {
#open a file (file name that is given)
set filename [lindex $argv 0]
# [set up the associative array]
set list [getMap $filename]
set startSymbol [lindex $list 0]
array set map $list
} else {
puts "No file exists by that name"
}
# [add the start symbol to the stack]
Stack::push $startSymbol
# [while the stack is not empty randomly generate text]
A6
while {![Stack::empty]} {
# [if the next thing is a nonterminal]
if [isNonTerminal [Stack::peek]] {
# [get an item off the stack]
set current $map([Stack::pop])
set currentSize [llength $current]
# [randomly grab one of the expression associated to our ]
# [nonterminal]
set rndNum [expr int(rand() * $currentSize)]
set innerSize [llength [lindex $current $rndNum]]
# [add each item onto the stack]
for {set i [expr $innerSize1]} {$i >= 0} {set i [expr $i 1]} {
Stack::push [lindex [lindex $current $rndNum] $i]
}
} else {
# [set up the generated text]
set generatedText [concat $generatedText " "]
set generatedText [concat $generatedText [Stack::pop]]
}
}
# [print out generated text]
puts $generatedText
}
A.3.3 Sample Grammar
Super Hero Acticle
by Zachary A. Hayes (zahayes@georgefox.edu)
{
<start>
<headline> <details> . ;
}
{
<headline>
HEROS ARE BUSY THIS WEEK SAVING <Object> ! ;
<Hero> DOES IT AGAIN ! ;
<Hero> SAVES THE DAY ! ;
<Hero> LONGTIME NO SEE ! ;
ALL HAIL <Hero> SAVER OF <Object> ! ;
}
...
...
A.3.4 Sample Output
The Incredible Hulk SAVES THE DAY ! Shanna Duckett uses beans to attack
benches . Captain America drives in but just then Shredder attacks
Sacramento, California . Teenage Mutant Ninja Turtles uses levitation
against Cobra Commander stopping him/her but just then Apokolips and
Doctor Doom uses spork, not quite a spoon or a fork, to attack The
A7
Empire State Building . Zachary Hayes uses mental power against Kingpin
stopping him/her
BIBLIOGRAPHY
Active State: Dynamic Tools for Dynamic Languages . 2006 . ActiveState Software Inc .
28 October 2006 . http://www.activestate.com/Products/ActiveTcl/
Ousterhout, John . Tcl Developer Xchange “History of Tcl” . October 2005 . 28 October
2006 . ActiveState . http://www.tcl.tk/about/history.html
Ousterhout, John. Tcl and the Tk Toolkit (Partial Draft). AddisonWesley Publishing
Company Inc , 1993 http://ftp.dct.ufms.br/windows/graphlet/tcl_p1.pdf
Wikipedia: The Free Encyclopedia “Tcl” . 28 October 2006 . Wikimedia Foundation Inc .
28 October 2006 . http://en.wikipedia.org/wiki/Tcl
Sanfilippo, Salvatore . Tcl Wise: Guide to the Tcl Programming Language(PreRelease/
Incomplete). http://www.invece.org/tclwise/frontcover.html November 6, 2006
Developer Connection “Tcl(n): Tcl BuiltIn Commands” November 6, 2006 .
http://developer.apple.com/documentation/Darwin/Reference/ManPages/mann/Tc
l.ntcl.html