230 likes | 417 Views
Tcl and Otcl Tutorial Part II. Internet Computing Laboratory @ KUT Youn-Hee Han. Adding new commands to Tcl. In Tcl, There are no reserved words (like if and while) as exist in C, Java, etc. Everything is a command!!! Example. proc sum {arg1 arg2} { set x [expr {$arg1 + $arg2}];
E N D
Tcl and Otcl TutorialPart II Internet Computing Laboratory @ KUT Youn-Hee Han
Adding new commands to Tcl • In Tcl, There are no reserved words (like if and while) as exist in C, Java, etc. • Everything is a command!!! • Example proc sum {arg1 arg2} { set x [expr {$arg1 + $arg2}]; return $x } puts " The sum of 2 + 3 is: [sum 2 3]\n\n" proc for {a b c} { puts "The for command has been replaced by a puts"; puts "The arguments were: \n$a\n$b\n$c\n" } for {set i 1} {$i < 10} {incr i} Introduction to Tcl and OTcl
Arguments of proc • Default Arguments • By declaring “args” as the last argument, it can take a variable number of arguments. proc justdoit {a {b 1} {c -1}} { puts "a=$a, b=$b, c=$c" } justdoit 10 justdoit 10 20 justdoit 10 20 30 proc example {first {second ""} args} { if {$second eq ""} { puts "There is only one argument and it is: $first" return 1 } else { if {$args eq ""} { puts "There are two arguments - $first and $second" return 2 } else { puts "There are many arguments - $first and $second and $args" return "many" } } } set count1 [example ONE] set count2 [example ONE TWO] set count3 [example ONE TWO THREE ] set count4 [example ONE TWO THREE FOUR] puts "The example was called with $count1, $count2, $count3, and $count4 Arguments" Introduction to Tcl and OTcl
Scope of Variable • “global” command • It will cause a variable in a local scope (inside a procedure) to refer to the global variable of that name. • “upvar” command • It ties the name of a variable in the current scope to a variable in a different scope. • This is commonly used to simulate pass-by-reference to procs. proc SetPositive {variable value } { upvar $variable myvar if {$value < 0} { set myvar [expr {-$value}] } else { set myvar $value } return $myvar } SetPositive x 5 SetPositive y -5 puts “x : $x y: $y" proc SetPositive {variable value } { if {$value < 0} { set variable [expr {-$value}] } else { set variable $value } return $variable } SetPositive x 5 SetPositive y -5 puts "x : $x y: $y" myvar is a reference to variable Introduction to Tcl and OTcl
Data Structure - list • by setting a variable to be a list of values • set lst {{item 1} {item 2} {item 3}} • set lst [split "item 1.item 2.item 3" "."] • set lst [list "item 1" "item 2" "item 3"] set x "a b c" puts "Item at index 2 of the list {$x} is: [lindex $x 2]\n" set y [split 7/4/1776 "/"] puts "We celebrate on the [lindex $y 1]'th day of the [lindex $y 0]'th month\n" set z [list puts "arg 2 is $y" ] puts "A command resembles: $z\n" set i 0 foreach j $x { puts "$j is item number $i in list x" incr i } Introduction to Tcl and OTcl
Adding & Deleting members of a list • Commands • concat, lappend, linsert, lreplace, lset set b [list a b {c d e} {f {g h}}] puts "Treated as a list: $b\n" set b [split "a b {c d e} {f {g h}}"] puts "Transformed by split: $b\n" set a [concat a b {c d e} {f {g h}}] puts "Concated: $a\n" lappend a {ij K lm} ;# Note: {ij K lm} is a single element puts "After lappending: $a\n" set b [linsert $a 3 "1 2 3"] ;# "1 2 3" is a single element puts "After linsert at position 3: $b\n" set b [lreplace $b 3 5 "AA" "BB"] puts "After lreplacing 3 positions with 2 values at position 3: $b\n" Introduction to Tcl and OTcl
String Commands • Example if {[string match f* foo]} { puts "Match" } if {[string match f?? foo]} { puts "Second Match" } if {[string match f foo]} { puts "Third Match" } set var [glob /var/*] puts $var set string "this is my test string" puts "There are [string length $string] characters in \"$string\"" puts "[string index $string 1] is the second character in \"$string\"" puts "\"[string range $string 5 10]\" are characters between the 5'th and 10'th" Return names of files that match patterns Introduction to Tcl and OTcl
Other String Commands • Other String Commands • string comparestring1string2 • Compares string1 to string2 and returns: • -1 ..... If string1 is less than string2 • 0 ........ If string1 is equal to string2 • 1 ........ If string1 is greater than string2 • These comparisons are done alphabetically, not numerically - in other words "a" is less than "b", and "10" is less than "2". • string firststring1string2 • Returns the index of the character in string1 that starts the first match to string2, or -1 if there is no match. • string laststring1string2 • Returns the index of the character in string1 that starts the last match to string2, or -1 if there is no match. Introduction to Tcl and OTcl
Other String Commands • Example: Other String Commands set fullpath "/usr/home/clif/TCL_STUFF/TclTutor/Lsn.17" set relativepath "CVS/Entries" set directorypath "/usr/bin/" set paths [list $fullpath $relativepath $directorypath] foreach path $paths { set first [string first "/" $path] set last [string last "/" $path] if {$first != 0} { puts "$path is a relative path" } else { puts "$path is an absolute path" } } set c_result [string compare $fullpath $directorypath] puts $c_result Introduction to Tcl and OTcl
String format • format formatString arg1 arg2 ... argN • s... Data is a string • d... Data is a decimal integer • x... Data is a hexadecimal integer • o... Data is an octal integer • f... Data is a floating point number • -... Left justify the data in this field • +... Right justify the data in this field • Example: String format set labels [format "%-20s %+10s " "Item" "Cost"] set price1 [format "%-20s %10d Cents Each" "Tomatoes" "30"] set price2 [format "%-20s %10d Cents Each" "Peppers" "20"] set price3 [format "%-20s %10d Cents Each" "Onions" "10"] set price4 [format "%-20s %10.2f per Lb." "Steak" "3.59997"] puts "\n Example of format:\n" puts "$labels" puts "$price1" puts "$price2" puts "$price3" puts "$price4" Introduction to Tcl and OTcl
Regular Expression • Example set sample "Where there is a will, There is a way." # # Match the first substring with lowercase letters only # set result [regexp {[a-z]+} $sample match] puts "Result: $result match: $match" # # Replace a word # regsub "way" $sample "lawsuit" sample2 puts "New: $sample2" # # Use the -all option to count the number of "characters" # puts "Number of characters: [regexp -all {[^ ]} $sample]" Introduction to Tcl and OTcl
Associative Array (=hash tables) • Tcl, like most scripting languages (Perl, Python, PHP, etc...) supports associative arrays (also known as "hash tables") in which the index value is a string. • When an associative array name is given as the argument to the global command, all the elements of the associative array become available to that proc set name(first) "Mary" set name(last) "Poppins" puts "Full name: $name(first) $name(last)" proc addname {first last} { global name incr name(ID) set id $name(ID) set name($id,first) $first set name($id,last) $last } global name set name(ID) 0 addname Mary Poppins addname Uriah Heep addname Rene Descartes addname Leonardo "da Vinci" puts $name(1,first) puts $name(1,last) puts $name(2,first) puts $name(2,last) puts $name(3,first) puts $name(3,last) puts $name(4,first) puts $name(4,last) Introduction to Tcl and OTcl
More Array Examples - 1 • Examples: Array command array set array1 [list {123} {Abigail Aardvark} \ {234} {Bob Baboon} \ {345} {Cathy Coyote} \ {456} {Daniel Dog} ] foreach {name value} [array get array1] { puts "Data on \"$name\": $value" } puts "Array1 has [array size array1] entries\n" puts "Array1 has the following entries: \n [array names array1] \n" puts "ID Number 123 belongs to $array1(123)\n" if {[array exist array1]} { puts "array1 is an array" } else { puts "array1 is not an array" } if {[array exist array2]} { puts "array2 is an array" } else { puts "array2 is not an array" } Introduction to Tcl and OTcl
More Array Examples - 2 • Examples: Array command • Examples: Array as a argument of proc array set array1 [list {123} {Abigail Aardvark} \ {234} {Bob Baboon} \ {345} {Cathy Coyote} \ {456} {Daniel Dog} ] foreach name [array names array1] { puts "Data on \"$name\": $array1($name)" } foreach name [lsort [array names array1]] { puts "Data on \"$name\": $array1($name)" } proc print12 {a} { puts "$a(1), $a(2)" } set array(1) "A" set array(2) "B" print12 array proc print12 {array} { upvar $array a puts "$a(1), $a(2)" } set array(1) "A" set array(2) "B" print12 array Pass by name Introduction to Tcl and OTcl Error: an array does not have a value!!!
File Access 101 • Examples: File Access # Count the number of lines in a text file set infile [open "myfile.txt" r] set number 0 # gets with two arguments returns the length of the line, # -1 if the end of the file is found while { [gets $infile line] >= 0 } { incr number } close $infile puts "Number of lines: $number" # Also report it in an external file set outfile [open "report.out" w] puts $outfile "Number of lines: $number" close $outfile Introduction to Tcl and OTcl
Source Modularization • Examples: sourcedata.tcl • Examples: sourcemain.tcl # Example data file to be sourced set scr [info script] proc testproc {} { global scr puts "testproc source file: $scr" } set abc 1 return set aaaa 1 set filename "sourcedata.tcl" puts "Global variables visible before sourcing $filename:" puts "[lsort [info globals]]\n" if {[info procs testproc] eq ""} { puts "testproc does not exist. sourcing $filename" source $filename } puts "\nNow executing testproc" testproc puts "Global variables visible after sourcing $filename:" puts "[lsort [info globals]]\n" Introduction to Tcl and OTcl
Otcl Tutorial • OTcl Example: # Create a class call "mom" and add a member function call "greet" Class mom mom instproc greet {} { $self instvar age_ puts "$age_ years old mom say…" } # Create a child class of "mom" called "kid" and overide the member function "greet" Class kid -superclass mom kid instproc greet {} { $self instvar age_ puts "$age_ years old kid say…" } # Create a mom and a kid object set each age set a [new mom] $a set age_ 45 set b [new kid] $b set age_ 15 # Calling member function "greet" of each object $a greet $b greet $a set new_variable 111 puts [$a set new_variable] As an ordinary NS user, the chances that you will write your own object might be rare. However, since all of the NS objects that you will use in a NS simulation programming, whether or not they are written in C++ and made available to OTcl via the linkage or written only in OTcl, are essentially OTcl objects, understanding OTcl object is helpful. Introduction to Tcl and OTcl
Otcl Tutorial • Comparison with C++ (1/3) • Instead of a single class declaration in C++, write multiple definitions in OTcl. • Each method definition (with “instproc”) adds a method to a class. • Each instance variable definition (with set or via “instvar” in a method body) adds an instance variable to an object. • Instead of a constructor in C++, write an “init” instproc in OTcl. • Instead of a destructor in C++, write a “destroy” instproc in OTcl. • Unlike constructors and destructors, “init” and “destroy” methods do not combine with base classes automatically. • They should be combined explicitly with “$self next”. Introduction to Tcl and OTcl
Otcl Tutorial • Comparison with C++ (2/3) Class mom mom instproc greet {} { $self instvar age_ puts "$age_ years old…" } mom instproc init {} { puts “in mom’s init” } Class kid -superclass mom kid instproc greet {} { $self instvar age_ puts "$age_ years old…" } kid instproc init {} { puts “in kid’s init” $self next } set a [new mom] set b [new kid] Class mom mom instproc greet {} { $self instvar age_ puts "$age_ years old…" } mom instproc init {} { puts “in mom’s init” } Class kid -superclass mom kid instproc greet {} { $self instvar age_ puts "$age_ years old…" } set a [new mom] set b [new kid] $a set age_ 10 $b set age_ 20 $a greet $b greet puts [$a set age_] Class mom mom instproc greet {} { $self instvar age_ puts "$age_ years old…" } mom instproc init {} { puts “in mom’s init” } Class kid -superclass mom kid instproc greet {} { $self instvar age_ puts "$age_ years old…" } kid instproc init {} { puts “in kid’s init” } set a [new mom] set b [new kid] Introduction to Tcl and OTcl
Otcl Tutorial • Comparison with C++ (3/3) • Unlike C++, OTcl methods are always called through the object. • Avoid using static methods and variables, since there is no exact analogue in OTcl. • Place shared variables on the class object and access them from methods by using $class. • The name “self”, which is equivalent to “this” in C++, may be used inside method bodies. • Unlike C++, OTcl methods are always virtual. Introduction to Tcl and OTcl
Otcl Example • Otcl Example [ns for beginner p. 13] set realA [new Real 12.3] set realB [new Real 0.5] $realA sum $realB $realA multiply $realB $realA divide $realB Class Real Real instproc init {a} { $self instvar value set value $a } Real instproc sum {x} { $self instvar value set op "$value + [$x set value] = \t" set value [expr $value + [$x set value]] puts "$op $value" } Real instproc multiply {x} { $self instvar value set op "$value * [$x set value] = \t" set value [expr $value * [$x set value]] puts "$op $value" } Real instproc divide {x} { $self instvar value set op "$value / [$x set value] = \t" set value [expr $value / [$x set value]] puts "$op $value" } Introduction to Tcl and OTcl
Otcl Example • Otcl Example [ns for beginner p. 13] Class Integer -superclass Real Integer instproc divide {x} { $self instvar value set op "$value / [$x set value] = \t" set d [expr $value / [$x set value]] set value [expr round($d)] puts "$op $value" } set integerA [new Integer 12] set integerB [new Integer 5] set integerC [new Integer 7] $integerA multiply $integerB $integerB divide $integerC Class father father instproc init {args} { $self set var_ 0 puts “hello” eval $self next $args } father ff puts [ff info vars] puts [ff set var_] puts [ff info class] puts [father info instances] Introduction to Tcl and OTcl