Tcl Programming: Theory & Practice Presented By: Sunil Ramesh Origins of Tcl ⋋-Calculus - 1930 LISP - 1950 TCL - 1990 Alonzo Church, Princeton John McCarthy, Lab, Stanford AI C - 1970 John Ousterhout, UC Berkeley Dennis Ritchie, Bell Labs 2 Theory Part 1 Lambda Calculus Anything which can be computed can be computed using the lambda calculus - Church’s Thesis Church’s Lambda Calculus 1 • Highly theoretical basis for programming languages • Based on “Lambda” – λ – λ is what is used to define an “anonymous” function – Grammar • λargVarNameList.expression • argVarNameList is the list of variables • expression denotes the return value of lambda • About State – The only state allowed is the current list of function aliases* • Example: f = λx.x2 g = λx.f(x)+1 – Thus, g(x) = x2 + 1, and g(5) = 26 4 *It is said that Church was initially opposed to this idea, but it was forced on him by his student, Alan Turing. Church’s Lambda Calculus 2 • Two kinds of statements – Function declarations – lambda abstraction • Ex: λx.x+2 - a function with 1 argument that returns the sum of the argument and 2 • Ex: λx,y.x*y - a function with two arguments that returns the product of two given arguments – Function applications – lambda application • Ex: (λx.x+2)(3) – will return 5 • Ex: (λx,y.x+y)(3,5) – will return 8 – Complex applications • (λx.x+(λx,y.x+y)(4,3)) 1 - will return 8 • If you are interested in more: – Representation of numbers: Church Numerals 5 LISP - Lambda Calculus Realized • Church’s proposition finally realized in an implementation called LISP – list processor • Uses prefix notation! • Function add2: – Lambda calculus: λx.x+2 – Scheme (dialect of LISP): (define (f x) (+ x 2)) • Alternatively (and closer to λ): (define f (lambda (x) (+ x 2))) • “f is a function: takes one argument: returns the sum of the argument and 2 – Optimizations: • (lambda (x) (+ x 2)) and (lambda (y) (+ y 2)) equivalent • Usage: – (f 2) -> will evaluate to 4 – ((lambda (x) (+ x 2)) 3) -> will evaluate to 5 6 Theory Part 2 List Languages LISP, Scheme, and Tcl are common examples of List-centric languages We will use Scheme to illustrate the salient features and derivations of the List abstraction. Pairs • Pair – a construct with exactly 2 elements car cdr • Constructing a pair – (define a (cons 1 2)) will yield a 1 2 • Referencing “left” and “right” elements – (car a) will yield 1 – (cdr a) will yield 2 8 Pairs Implementation • Pairs are implemented using λ-calculus, too! • Pair construction is a contract “C” – Cons: T1, T2 -> C such that: – Car: C -> T1 – Cdr: C -> T2 • Let’s see some code… (define cons (lambda (x y) (define select (lambda (m) (cond ((= m 0) x) ((= m 1) y)))) select)) 9 (define (car z) (z 0)) (define (cdr z) (z 1)) Lists • Implementation of pairs has no bearing on “type” of the elements of the pair. • Can an element be a pair itself? Sure! • Lists are realized easily: a 1 2 3 4 • (define a (cons 1 (cons 2 (cons 3 (cons 4 nil))))) • How to retrieve values? 1 = (car a) 2 = (car (cdr a)) …… Built-in, called (cadr a) 10 Abstraction: Clumsiness to Grace a 1 2 3 4 • The above list can also be declared by (Scheme): – (define a (list 1 2 3 4)) • In Tcl: – Declaration: set a [list 1 2 3 4] – Accessing: The “value” of the list will be in “$a” – More later… 11 List Operations • Length of a list (Scheme) - llength (define (llength lst) (if (null? lst) 0 (+ 1 (llength (cdr lst))))) • Index in a list (Scheme) - lindex (define (lindex lst idx) (if (= 0 idx) (car list) (lindex (cdr lst) (- idx 1)))) • These same functions (and more) are built-in in Tcl 12 Practice Part 1 Introduction to Tcl Constants • In Tcl, all free constants are strings • Upshot – abc is the same as “abc” – “5” is the same as 5 • <, >, == ,<= and >= compare numerically – If any of the arguments are non-numbers, errors are thrown • Strings can also be compared literally: – string compare string1 string2 14 Variables • A Tcl variable is a C-style name, which satisfies the regular expression: – {[A-Za-z_][A-Za-z_0-9]*} • Examples: – iterator – loopInit – _ErrorCount76 • Non-examples: – 78Cool – ~notAVariable 15 Variables, Contd. • “set” command – Usage: set <varname> <value> – In most other languages, <varname> = <value> – Artifact of basis on LISP-like PLs (define varname value) • Example: – set a 5 – puts $a puts = putString – exactly like C’s • Will print out 5 • What’s with the $ ? – $<varname> is the value of a variable with name varname • Weird… – set a a will set the string “a” to the variable a 16 Output to screen • puts lets the programmer send output to the screen • Example: – puts 5 – puts $a – puts “The value of variable a is $a” • Variables can be freely placed in a puts string • Any way to suppress the new line? – puts –nonewline “Enter some number:” – Caveat: Most Operating System implementations use \n to trigger a flush of the buffer. In most cases, after a puts –nonewline, adding flush stdout is necessary 17 Comments • Comments are C-shell and Perl style, and start with a #. The rest of the line is part of the comment • Example 1: comment on its own line # I will now set the variable a to 5 set a 5 • Comments after a statement need a slight change • Example 2: comment after a statement set a 5 ;# I just set the variable a to 5 • We are essentially ending the current statement with the ; The rest of the line is the comment. 18 Math expressions • expr is used for evaluating math expressions • Usage: expr <expression> • Examples: – expr 5+3 will evaluate to 8 – expr 5*(7+3) will evaluate to 50 • General Rule of Thumb – Anything in <expression> is exactly the same as it would appear in C. If an expression is valid in C, then it is valid after expr – The only thing to remember is replacing all variable names with $<varname>, but this is generally not an issue 19 Setting results of Evaluation • [<expression>] denotes the value after evaluation of an expression • Example: – set a [expr 5+6] will set the “result” of the expr to a – set b [SomeFunction 6] will set the “return value” of “SomeFunction” to b • Careful! – [set a [expr 5+6]] will result in a syntax error, because 11 is not a function! 20 Keyboard Input • gets is a built-in Tcl command which allows for keyboard input by user • Example: puts “Please enter your name: “ set userName [gets stdin] puts “Your name is $userName” • Example: puts “Enter a number: “ set input [gets stdin] set output [Add2 $input] puts “$input plus 2 is $output” 21 Programming Assignment # 1 • Write a program that asks the user for two numbers and prints the average of the two numbers. • Sample Output: 22 Solution to PA # 1 23 Conditionals - if • Syntax: if { condition } { action1 } else { action2 } • Example: if { $a > 2 } { puts “$a is greater than 2” } else { puts “$a is not greater than 2” } • There is no option as far as bracket style is concerned – it is enforced like above 24 Conditionals – on the condition • A condition is exactly as it would appear in C • Any nonzero number is taken to be true • Examples: if { $a > 5 } if { $a > $b } if { ($a > 5) || ($b < 3) || ($c != $d) } if { $a } If { !$done } • C rule of thumb – The condition works exactly as in C 25 Conditionals - elseif • Used for chaining if statements • Example: if { $a > 0 } { puts “$a is a positive number” } elseif { $a < 0 } { puts “$a is a negative number” } else { puts “$a is zero” } 26 Incr – Incrementing/Decrementing • incr is an overloaded version of C’s ++,--,+=,-= • Syntax: incr varName ?offset=1 • Examples: incr i ;# Will increase i by one, the default incr i -1 ;# Will reduce i by one incr i 3 ;# Will increase i by three incr i 0 ;# Will not change I • Common mistake: – incr $i 2 will cause a syntax error. We need to the variable name to incr, not the value of the variable! 27 Loops - while • The while loop is exactly the same as it is in C! • Syntax: while { condition } { action } • Example: set i 1 while { $i <= 10 } { puts “On iteration $i of 10” incr i } 28 Loops - for • The for loop is exactly the same as it is in C! • Syntax: for { initCond } { condition } { update } • Example: for { set i 1 } { $i <= 10 } { incr i } { puts “On iteration $i of 10” } 29 Programming Assignment # 2 • Write a program that keeps asking user for numbers till the blank string is seen, and prints the average of the numbers: • Sample Output: 30 Solution to PA # 2 31 Procedures • By example: proc Add2 { number } { set a [expr $number+2] return $a } • “proc” is a reserved word, and it denotes the start of a procedure • { number } this is a list of variables • return $a will return the value stored in a • A procedure MUST be defined before being called. – No prototypes! – Except in Itcl, more later 32 Procedures: Optional Parameters • Optional Parameters are very easy to set up in Tcl • By Example: Proc Add { number { by 1 } } { return [expr $number+$by] } • The variable by takes on a default of 1 unless specified otherwise in the function call Add 1 Add 1 2 Add 1 –1 33 ;# Will return 2 ;# Will return 3 ;# Will return 0 Global Scope • Scope works the same as in C except for one thing: accessing global variables inside procedures – Global variables have to be explicitly declared as such inside a procedure • Example: set errorCount 0 … proc TriggerError { errorString } { global errorCount puts “Error: $errorString” incr errorCount } 34 Lists in Tcl • A list is declared using the list built-in function: • Example: set a [list 1 2 3 4] • The same can also be written as: set a { 1 2 3 4 } • Retrieving an element within a list: lindex • lindex is 0-based, just like C set b [lindex $a 3] ;# b has the value 4 set b [lindex $a end] ;# b will have value 4 set b [lindex $b 0] ;# b will have the value 1 35 List Operations • concat : Concatenate two lists set b [concat [list 1 2 3 4] [list 5 6 7]] b will be { 1 2 3 4 5 6 7 } • lappend : Append value at the end of list – By Name set a [list 1 2 3] lappend a 4 – Now a will be { 1 2 3 4 } – Note: lappend takes a list Name, not a list • llength : Return the length of a list – llength [list 1 2 3] will be 3 – llength [list] will be 0 • Many others… Read any Tcl book 36 Looping over lists - foreach • Because looping over lists is a common operation, there is a built-in construct to make this easier • By Example: proc PrintList { inputList } { foreach element $inputList { puts $element } } • element takes on the value of each of the members of the list* 37 *In Perl, element would be a reference to the member of the list. Any update to element would change the list. Not so in Tcl… Programming Assignment # 3 • Write a procedure reverseList that reverses a given list, and returns the reversed list. 38 Solution to PA # 3 39 Arrays • All Arrays in Tcl are one-dimensional and associative – called a hash in other PLs • We will see later how more dimensions can be “induced” over single dimensional arrays • By example: set myArray(0) 1 set myArray(1) 2 set myArray(2) 3 puts $myArray(0) puts $myArray(1) 40 Arrays, contd. • The “keys” to arrays need not be natural numbers • Arrays are used mainly to achieve key/data pairs • Example: set address(“sunil”) “cupertino” set address(“dan”) “berkeley” set address(“praveen”) “san jose” puts $address(“sunil”) puts $address(“dan”) … 41 Arrays – Multiple Dimensions • Since arrays are associative, we can form a “composite key” by choosing a delimiter like , • Example: set addresses(“sunil”,”street”) “meteor” set addresses(“sunil”,”city”) “cupertino” set addresses(“dan”,”street”) “hearst” set addresses(“dan”,”city”) “berkeley” puts $addresses(“dan”,”street”) … 42 Arrays – Retrieving all keys • array names arrayName will return a list of all keys associated with the array • By Example: set myArray(0) 1 set myArray(“chocolate”) “chip” set keyList [array names myArray] ;# keyList will be { 0 chocolate } • Common iteration technique: foreach key [array names myArray] { set value $myArray($key) # Now $key and $value might be used for any action necessary… } 43 Arrays – One Major Drawback • Arrays cannot be passed by value to and from other procedures! • Why? – Internally, each element of an array is just another variable. Arrays happen to be a special case where all the variables start with the same letters, and contain a “(“ after the first name • Give up? – Don’t! There is pass-by-reference; we will get to it later… 44 Regular Expressions • • • • Regular Expressions are used to match patterns Invocation: regexp <regexp> $var Returns 1 if $var matches <regexp>, 0 otherwise Simple Sub-string Examples: regexp {mcd} “mcdata” regexp {cda} “mcdata” regexp {mcdata} “mcdata” regexp {macdata} “mcdata” regexp {mc data} “mcdata” 45 ;# 1 ;# 1 ;# 1 ;# 0 ;# 0 Regular Expressions, contd. • Grouping – Subsections of regular expressions are grouped using parentheses () – Ex: • regexp {(mcdata)(colorado)} mcdatacolorado ;# 1 • Multiple matching choice: Enclose in [ ] – regexp {[0123456789]} $var – Will match any one of 0-9 in $var • regexp {[0123456789]} mcdata7 • regexp {[0123456789]} mcdata 46 ;# 1 ;# 0 Regular Expressions, contd. • Range Specification – Within [ ], ranges can be used instead of verbatim – Ex: regexp {[A-Zu-z3-9]} … • Quick Class Exercise – Write a regular expression to match standard California Vehicle Number Plates – The first digit is a nonzero number, followed by 3 uppercase letters, followed by 3 more numbers regexp {[1-9][A-Z][A-Z][A-Z][0-9][0-9][0-9]} 47 Regular Expressions, contd. • Matching beginning and end of input – Robust regular expressions are written to take everything into account, from beginning to the end of input – Not all situations call for such strict regular expressions, but it useful to know how to write them nevertheless • • • • ^ matches beginning of string $ matches end of string {^mcdata$} will ONLY match “mcdata” {^[0-9]$} will ONLY match a string containing exactly 1 digit • {^[0-9]} will ONLY match a string starting with a digit 48 Regular Expressions, contd. • Matching “any” character – “any” character is matched with “.” • {^.[0-9]} will match any string with a digit as the second character • How to match . or [ or ^ or $, etc. – All regular expression characters can be escaped using \ – {^\.\[$} will match ONLY the string “.[“ – A backslash may itself be escaped – {\\} will match any string that contains a \ 49 Regular Expressions, contd. • Group Modifiers •* – Denotes at least 0 of • Ex: {[0-9]*} means match if at least 0 digits • Note: will always also match empty string! •+ – Denotes at least 1 of • Ex: {[0-9]+} means match if at least 1 digit • Will never match empty string •? – Denotes either exactly 0 or exactly 1 of (or “optionally”) • Ex: {^[0-9]?} means match if first digit is present or not 50 Programming Assignment # 4 • Update PA#2 to validate input. • I will try to break your program! My Solution: {^-?([0-9])+(\.([0-9])+)?$} 51 Passing by Reference • Tcl has a very powerful call-by-reference model – More appropriately called: call-by-name • Illustrate by example: Suppose I want to write incr proc Incr { varName { by 1 } } { upvar $varName var set var [expr $var+$by] return $var } set i 1 Incr i ;# Will have the desired effect • Notice that we are passing the variable to the procedure “by name” 52 Passing by Reference, contd. • upvar aliases a variable in the current scope to a variable in another scope, usually the calling scope. • upvar ?level=1 varName localVar • When localVar is updated, the variable with the name “varName” is updated in the scope specified. • upvar is a very difficult concept to grasp completely the first time around, so if you plan on passing by reference, read Welch’s book. 53 Practice Part 2 Introduction to ITcl Itcl = [incr Tcl] • • • • Itcl is the Object-oriented version of Tcl Itcl does for Tcl what C++ does for C Provides manageability for large-scale projects Supports multiple-inheritance, except in a degenerate case • Itcl manifests itself as a package that can be brought into the standard Tcl environment – Simply insert: package require Itcl namespace import -force itcl::* 55 Objects • Objects = Data + Procedures* • Traditionally, data structures were separate from the procedures that acted upon them • The Object-Oriented Paradigm (OOP) is the drive to combine the data and procedures into one package. Object Data 56 Procedures *We owe this succinct definition to Grady Booch in his book: Object Oriented design with applications Defining Objects - Classes class Car { variable year variable color variable doors variable cylinders method Drive { } { puts “I am driving!!” } } 57 The object “type” is Car year is an “attribute” Keep track of color Same with doors Number of cylinders A Car can “do” this: It can Drive Declaring Objects - constructor • In order to be able to declare objects, we need to define a special method within the class that is called when we “create” or “construct” the object class Car { constructor { inYear inColor inDoors inCylinders } { set year $inYear set color $inColor set doors $inDoors set cylinders $inCylinders }… } • Here, we populate the variables inside the class with what we get during “creation” 58 Declaring Objects - Instantiation • We can proceed to declare a Car by: Car sunilCar 1997 Biege 4 4 • We can also perform the Drive operation on the object just declared by: sunilCar Drive 59 Inheritance • What happens when we realize that we have more attributes that are specific to say, a Toyota? • Declare a new class and rewrite all the basic attributes for that class over again? • Yes and No!! • Write a new class, but “use” the attributes already given to us by the already existing class. – We can do this because a Toyota is but a special case of a Car. – “A Toyota IS A Car” – This IS A relationship drives inheritance! 60 Base/Member Initialization Class Toyota { inherit Car ; variable exhaustType constructor {inYear inColor inDoors inCylinders inExType } { Car::constructor $inYear $inColor $inDoors $inCylinders } { set exhaustType $inExType } } Toyota myCar 1997 Beige 4 4 RearSingle myCar Drive • Can a Toyota Drive? We did not teach it! •Sure it can! It inherited Car 61 Questions ? • The dumbest question is the one not asked… - Aristotle 62 Thanks !