Page contents
if 0 {Introduction edit
MiHa 2015-06-13: HelloWorld-programs are supposed to be the most simple, working programs of a given language.But I want to extend such a HelloWorld-program to a one-page - reference-card,where all the essential features of the language are shown.
Several short programs would be ok, too.
If possible, while doing something useful (and/or funny).Tcl by itself (without Tk) is quite simple
, so an amount of code to fill about one printed page should be enough. (The layout may need to be tweaked, e.g. printing front and back, landscape, and in 2-4 columns:)Basic Tcl Commands to cover:
- Comments
/ statements - Output: puts / -nonewline
- Numeric variables: set
- multiple statements / assignments in one line
- proc / return - for functions
- basic flowcontrol:
- foreach
- String variables / quoting
- catch
- exit
- input: gets, eof, scan / checking the input
This is an important topic, but likely too much for one page. - global / $::var
- upvar / Using upvar with an array

- string-operations (e.g. find/extract/replace char in a string, append, delete/split ...)
- data structures:
- file-operations / open, close / glob
- reading files: Additional file commands / read / how do I read and write files in Tcl
- Indexed file reading
- split: Splitting by whitespace / regexp / Braintwisters: awksplit / cmdSplit
- awk / How can I do this awk like operation in Tcl / grep / A grep-like utility / fileutil / sed
- proc with a variable number of arguments / default values / args
- packages and namespaces
- eval
- interp
- lambda
- regexp - this is very likely too complex to cover as just one small example on a general introduction page.
- switch
- unknown
- uplevel
- comments are commands, so quotes and braces inside need to be balanced
see Why can I not place unmatched braces in Tcl comments - when to use / not to use "$" with variablenames ( set i 1; puts $i; incr i $i )
Program 1 - puts edit
# HelloWorld001.tcl - 2015-06-13 - http://wiki.tcl.tk/41268 # Output a string to terminal: puts "Hello, World!" ### END ###
Program 2 - set, incr, catch, if, exit edit
# HelloWorld002 - 2015-06-25
# http://ideone.com/ZWCbmF
# Assign value to variables, and output:
set a "The answer is" ;# assign a constant text
set x 42 ;# assign a constant number
set n $x ;# assign contents of a variable
puts $a
puts $x
puts "n = $n"
incr n ;# add 1 to a numeric variable
incr n 2 ;# add 2 to a numeric variable
catch { incr a } ;# try a command, catch and ignore errors
if { [ catch {incr a} ] } { ;# catch error, and do something:
puts "!! Cannot increment variable containing a string: '$a' !!"
#exit 1 ;# exit program with an errorcode
}
puts "$a now $n"
# END #Output 2The answer is 42 n = 42 !! Cannot increment variable containing a string: 'The answer is' !! The answer is now 45
Program 3 - clock, timedate, if, else edit
# HelloWorld003.tcl - MiHa - 2015-06-13
# http://wiki.tcl.tk/41268 / http://ideone.com/xl0IBI
# Query the time (cs as a number, td and hh as a string),
# output depending on the value of the hour:
set cs [clock seconds] ;# seconds since 1970-01-01
set td [clock format $cs -format "%Y-%m-%d %H:%M:%S" ] ;# timedate
set hh [clock format $cs -format %H ] ;# hours (00-23)
puts "cs=$cs td='$td' hh=$hh"
if { $hh < "12" } {
puts -nonewline "Good morning, "
} else {
puts -nonewline "Hello, "
}
puts "World!"
# END #Output 3cs=1434926575 td='2015-06-21 22:42:55' hh=22 Hello, World!
Program 4 - clock, if/else/elseif edit
# HelloWorld004.tcl - MiHa - 2015-06-21
# http://wiki.tcl.tk/41268 / http://ideone.com/Llp8Os
# Query the hour from the clock,
# output text depending on the value of the hour:
set cs [clock seconds] ;# seconds since 1970-01-01
set hh [clock format $cs -format %H ] ;# hours (00-23)
puts "cs=$cs hh=$hh"
if { $hh < "12" } {
puts -nonewline "Good morning, "
} elseif { $hh > "18" } {
puts -nonewline "Good evening, "
} else {
puts -nonewline "Hello, "
}
puts "World!"
# END #Output 4cs=973531773 hh=17 Hello, World!and
cs=1434927642 hh=23 Good evening, World!
Program 5 - string compare edit
# HelloWorld005 - 2015-06-23
# http://ideone.com/OJoort
# Comparing strings:
set hh "20"
set tx "Hello"
if { $hh < "12" } { set tx "Good Morning" }
if { $hh > "18" } { set tx "Good Evening" }
puts "It is $hh:00 --> $tx, World !"
#.Output 5It is 20:00 --> Good Evening, World !
Program 6 - proc/return edit
# HelloWorld006 - 2015-06-23
# http://ideone.com/GBiMab
# Comparing strings, proc as function
proc greeting {hh} {
set gr "Hello"
if { $hh < "12" } { set gr "Good Morning" }
if { $hh == "12" } { set gr "Happy Lunchtime" }
if { $hh > "18" } { set gr "Good Evening" }
return $gr
}
set hh "12"
set tx [greeting $hh]
puts "It is $hh:00 --> $tx, World !"
#.Output 6It is 12:00 --> Happy Lunchtime, World !
Program 7 - proc, while, gets edit
# HelloWorld007 - 2015-06-23
# http://ideone.com/mcV6YL
# Comparing strings, proc as function, input in while-loop
proc greeting {hh} {
# This proc returns a result as soon as a match is found:
set gr "Hello"
if { $hh < "12" } { return "Good Morning" }
if { $hh == "12" } { return "Happy Lunchtime" }
if { $hh > "24" } { return "Goodbye" }
if { $hh > "18" } { return "Good Evening" }
return $gr
}
set hour "99" ;# start with any value that keeps the loop going
while { $hour > "0" } {
puts -nonewline "Enter hour, 0 to quit: "
set hour [gets stdin]
puts $hour
puts "It is $hour:00 --> [greeting $hour], World !"
}
puts "Bye!"
#.Output 7Enter hour, 0 to quit: 1 It is 1:00 --> Good Morning, World ! Enter hour, 0 to quit: 11 It is 11:00 --> Good Morning, World ! Enter hour, 0 to quit: 12 It is 12:00 --> Happy Lunchtime, World ! Enter hour, 0 to quit: 15 It is 15:00 --> Hello, World ! Enter hour, 0 to quit: 17 It is 17:00 --> Hello, World ! Enter hour, 0 to quit: 18 It is 18:00 --> Hello, World ! Enter hour, 0 to quit: 19 It is 19:00 --> Good Evening, World ! Enter hour, 0 to quit: 25 It is 25:00 --> Goodbye, World ! Enter hour, 0 to quit: 0 It is 0:00 --> Good Morning, World ! Bye!
Program 8 - for-with-integer, format edit
# HelloWorld008 - 2015-06-23
# http://ideone.com/lKo08L
# Comparing strings, proc as function, for-loop, format
proc greeting {hh} {
# This proc returns a result as soon as a match is found:
set gr "Hello"
if { $hh < "12" } { return "Good Morning" }
if { $hh == "12" } { return "Happy Lunchtime" }
if { $hh > "24" } { return "Goodbye" }
if { $hh > "18" } { return "Good Evening" }
return $gr
}
puts "Greeting:"
for {set h 0} {$h<=25} {incr h} {
#set hour $h ;# Tcl converts number to string, as needed
#set hour [format "%2d" $h] ;# format as numeric string with 2 digits
set hour [format "%02d" $h] ;# format as 2 digits with leading 0
puts "at $hour:00 --> [greeting $hour], World !"
}
puts "Done."
#.Output 8Greeting: at 00:00 --> Good Morning, World ! at 01:00 --> Good Morning, World ! at 02:00 --> Good Morning, World ! at 03:00 --> Good Morning, World ! at 04:00 --> Good Morning, World ! at 05:00 --> Good Morning, World ! at 06:00 --> Good Morning, World ! at 07:00 --> Good Morning, World ! at 08:00 --> Good Morning, World ! at 09:00 --> Good Morning, World ! at 10:00 --> Good Morning, World ! at 11:00 --> Good Morning, World ! at 12:00 --> Happy Lunchtime, World ! at 13:00 --> Hello, World ! at 14:00 --> Hello, World ! at 15:00 --> Hello, World ! at 16:00 --> Hello, World ! at 17:00 --> Hello, World ! at 18:00 --> Hello, World ! at 19:00 --> Good Evening, World ! at 20:00 --> Good Evening, World ! at 21:00 --> Good Evening, World ! at 22:00 --> Good Evening, World ! at 23:00 --> Good Evening, World ! at 24:00 --> Good Evening, World ! at 25:00 --> Goodbye, World ! Done.
Program 9 - expr, format edit
# HelloWorld009.tcl - 2015-06-23 # http://ideone.com/kgfFX1 # calculations using expr, formatting numbers set x 3.0 set y 7.0 set distance [expr sqrt($x * $x + $y * $y)] set dist2 [format %9.2f $distance] ;# format as float with 2 decimal digits puts "x=$x y=$y distance=$distance ==> $dist2" #.Output 9
x=3.0 y=7.0 distance=7.615773105863909 ==> 7.62
Program 10 - proc, expr, format, for-with-float, output-as-table edit
# HelloWorld010.tcl - 2015-06-23
# http://ideone.com/Pjrz4x
# calculations using expr, formatting numbers/strings as table
proc distance {x y} {
# calculate, return result as number
return [expr sqrt($x * $x + $y * $y)]
}
proc ff {num} {
# format number as float with 4 decimal digits
set f [format %9.4f $num]
return $f
}
proc fs {tx} {
# format text with fixed width, for use as header
return [format %9s $tx]
}
proc showDistance {x y} {
# calculate, format numbers, output / return nothing
set distance [format %9.4f [expr sqrt($x * $x + $y * $y)]]
puts "x=[ff $x] y=[ff $y] distance=$distance"
}
showDistance 1.0 1.0
set x 2.0; set y 5.0;
showDistance $x $y
set x 5.0; set y 12.0; showDistance $x $y
puts "\nTable:" ;# newline
puts "[fs x] [fs y] [fs distance]"
puts "[fs =] [fs =] [fs ========]"
for {set x 0.0} {$x<=11.0} {set x [expr $x+2.5]} {
for {set y 11.5} {$y<13.0} {set y [expr $y+0.5]} {
#puts "$x $y"
puts "[ff $x] [ff $y ] [ff [distance $x $y ] ]"
}
puts ""
}
puts "Done."
#.Output 10x= 1.0000 y= 1.0000 distance= 1.4142
x= 2.0000 y= 5.0000 distance= 5.3852
x= 5.0000 y= 12.0000 distance= 13.0000
Table:
x y distance
= = ========
0.0000 11.5000 11.5000
0.0000 12.0000 12.0000
0.0000 12.5000 12.5000
2.5000 11.5000 11.7686
2.5000 12.0000 12.2577
2.5000 12.5000 12.7475
5.0000 11.5000 12.5399
5.0000 12.0000 13.0000
5.0000 12.5000 13.4629
7.5000 11.5000 13.7295
7.5000 12.0000 14.1510
7.5000 12.5000 14.5774
10.0000 11.5000 15.2398
10.0000 12.0000 15.6205
10.0000 12.5000 16.0078
Done.Program 11 - foreach, for, list/lappend/llength/lindex edit
# HelloWorld011.tcl - 2015-06-24
# http://ideone.com/Ia463h
# foreach, list,lappend,llength,lindex:
set deck {} ;# create empty list
puts "Deck of cards:"
foreach rank { A 2 3 4 5 6 7 8 9 10 J Q K } { ;# Ace 2 .. 10 Jack Queen King
foreach suit { S H D C } { ;# Spades Hearts Diamonds Clubs
set card "$rank$suit"
puts -nonewline " $rank-$suit:$card "
lappend deck $card ;# add card to deck
}
puts ""
}
puts "\nThe list with the deck of cards has [llength $deck] elements:"
for {set i 0; set n 0} {$i < [llength $deck]} {incr i; incr n} {
if { $n >= 8 } { puts ""; set n 0 } ;# newline after 8 cards
if { $n == 4 } { puts -nonewline " " } ;# extra space after 4 cards
set c [lindex $deck $i] ;# get element #i from the list
puts -nonewline "$i: $c "
}
puts "\nDone."
#.Output 11Deck of cards: A-S:AS A-H:AH A-D:AD A-C:AC 2-S:2S 2-H:2H 2-D:2D 2-C:2C 3-S:3S 3-H:3H 3-D:3D 3-C:3C 4-S:4S 4-H:4H 4-D:4D 4-C:4C 5-S:5S 5-H:5H 5-D:5D 5-C:5C 6-S:6S 6-H:6H 6-D:6D 6-C:6C 7-S:7S 7-H:7H 7-D:7D 7-C:7C 8-S:8S 8-H:8H 8-D:8D 8-C:8C 9-S:9S 9-H:9H 9-D:9D 9-C:9C 10-S:10S 10-H:10H 10-D:10D 10-C:10C J-S:JS J-H:JH J-D:JD J-C:JC Q-S:QS Q-H:QH Q-D:QD Q-C:QC K-S:KS K-H:KH K-D:KD K-C:KC The list with the deck of cards has 52 elements: 0: AS 1: AH 2: AD 3: AC 4: 2S 5: 2H 6: 2D 7: 2C 8: 3S 9: 3H 10: 3D 11: 3C 12: 4S 13: 4H 14: 4D 15: 4C 16: 5S 17: 5H 18: 5D 19: 5C 20: 6S 21: 6H 22: 6D 23: 6C 24: 7S 25: 7H 26: 7D 27: 7C 28: 8S 29: 8H 30: 8D 31: 8C 32: 9S 33: 9H 34: 9D 35: 9C 36: 10S 37: 10H 38: 10D 39: 10C 40: JS 41: JH 42: JD 43: JC 44: QS 45: QH 46: QD 47: QC 48: KS 49: KH 50: KD 51: KC Done.
Program 12 - foreach 2, unicode-chars, string/append, lappend, array/parray edit
# HelloWorld012.tcl - 2015-06-24
# http://ideone.com/uKSgZR
# foreach, unicode-chars, append, lappend, array,parray
set deckStr "" ;# create empty string
set deckList {} ;# create empty list
array set deckArray {} ;# create empty array
puts "Deck of cards:"
set i 0
# see also: http://wiki.tcl.tk/26403 : [HTML character entity references]
# Spades Hearts Diamonds Clubs
foreach {suit sym} { S \u2660 H \u2665 D \u2666 C \u2663 } {
foreach rank { A 2 3 4 5 6 7 8 9 10 J Q K } { ;# Ace 2 .. 10 Jack Queen King
incr i
set card "$rank$sym"
puts -nonewline " $rank$suit=$card "
append deckStr $card ;# add card to string
lappend deckList $card ;# add card to list
set deckArray($i) $card ;# add card to array
}
puts ""
}
set maxCard $i
puts "\ndeckStr : $deckStr" ;# note: no spaces between
puts "S) card #3 : [string range $deckStr 4 5]" ;# 0-1 2-3 4-5 ...
puts "\ndeckList : $deckList"
puts "L) card #3 : [lindex $deckList 2]" ;# index is zero-based
puts "\nparray:"
parray deckArray ;# show all elements, unsorted
puts "A) card #3 = $deckArray(3)"
puts "\nDone."
#.Output 12Deck of cards: AS=A♠ 2S=2♠ 3S=3♠ 4S=4♠ 5S=5♠ 6S=6♠ 7S=7♠ 8S=8♠ 9S=9♠ 10S=10♠ JS=J♠ QS=Q♠ KS=K♠ AH=A♥ 2H=2♥ 3H=3♥ 4H=4♥ 5H=5♥ 6H=6♥ 7H=7♥ 8H=8♥ 9H=9♥ 10H=10♥ JH=J♥ QH=Q♥ KH=K♥ AD=A♦ 2D=2♦ 3D=3♦ 4D=4♦ 5D=5♦ 6D=6♦ 7D=7♦ 8D=8♦ 9D=9♦ 10D=10♦ JD=J♦ QD=Q♦ KD=K♦ AC=A♣ 2C=2♣ 3C=3♣ 4C=4♣ 5C=5♣ 6C=6♣ 7C=7♣ 8C=8♣ 9C=9♣ 10C=10♣ JC=J♣ QC=Q♣ KC=K♣ deckStr : A♠2♠3♠4♠5♠6♠7♠8♠9♠10♠J♠Q♠K♠A♥2♥3♥4♥5♥6♥7♥8♥9♥10♥J♥Q♥K♥A♦2♦3♦4♦5♦6♦7♦8♦9♦10♦J♦Q♦K♦A♣2♣3♣4♣5♣6♣7♣8♣9♣10♣J♣Q♣K♣ S) card #3 : 3♠ deckList : A♠ 2♠ 3♠ 4♠ 5♠ 6♠ 7♠ 8♠ 9♠ 10♠ J♠ Q♠ K♠ A♥ 2♥ 3♥ 4♥ 5♥ 6♥ 7♥ 8♥ 9♥ 10♥ J♥ Q♥ K♥ A♦ 2♦ 3♦ 4♦ 5♦ 6♦ 7♦ 8♦ 9♦ 10♦ J♦ Q♦ K♦ A♣ 2♣ 3♣ 4♣ 5♣ 6♣ 7♣ 8♣ 9♣ 10♣ J♣ Q♣ K♣ L) card #3 : 3♠ parray: deckArray(1) = A♠ deckArray(10) = 10♠ deckArray(11) = J♠ deckArray(12) = Q♠ deckArray(13) = K♠ .. deckArray(48) = 9♣ deckArray(49) = 10♣ deckArray(5) = 5♠ deckArray(50) = J♣ deckArray(51) = Q♣ deckArray(52) = K♣ deckArray(6) = 6♠ deckArray(7) = 7♠ deckArray(8) = 8♠ deckArray(9) = 9♠ A) card #3 = 3♠ Done.
Program 13 - Read file, whole edit
From How do I read and write files in Tcl :# HelloWorld013.tcl - 2018-04-13
# https://ideone.com/aQYnBa !! doesn't run - no files allowed !!
catch {console show} ;## show console when running from tclwish
catch {wm withdraw .}
# Slurp up the whole data file (only use this for 'small' files):
set fp [open "somefile.txt" r]
set file_data [read $fp]
close $fp
# Split file_data into lines:
set data [split $file_data "\n"]
# Process each line of data:
set ln 0
foreach line $data {
incr ln
# Processing: ignore comment-lines
set p [string first "#" $line] ;# look for comment-char
if {$p == 0} { continue } ;# found '#' at start of line: skip
puts "$ln: $line"
}
#.Output 131: xx 2: yy
Program 14 - Read file line-by-line, split into fields edit
# HelloWorld014.tcl - 2018-04-14
catch {console show} ;## show console when running from tclwish
catch {wm withdraw .}
set filename "somefile.txt"
set fh [open $filename]
set NR 0
# Read file line-by-line
while {[gets $fh line]>=0} { ;# gets returns length of line, -1 means eof
incr NR ;# number-of-record, means linenumber
# split line into a list of fields, at whitespace
# (the following three lines show different ways to do this)
set fld [split $line] ;# creates extra (empty) items if there is multiple whitespace
set fld [list {*}$line] ;# the string in line must be in the form of a proper list
set fld [regexp -all -inline {\S+} $line] ;# slow, but avoids the problems in the above variants
set NF [llength $fld] ;# number-of-fields
set f3 [lindex $fld 2] ;# zero-based
if 0 { ;## debug: list fields
foreach word $fld { puts -nonewline " <<$word>>" }
puts "."
}
# print line if value of 3rd field is greater than 6
if {$f3 > 6} { puts "$NR: $line" }
}
close $fh
#.Output 141: xxx 2: yyy 3: zzz
more programs edit
... * http://ideone.com/1t0KK7
Output 13xx
Some ideas:
- Table of primes
- as list / array
- Dice-rolling
- with min/max/average
- Number of days between dates
**Program 1x - xx**
# HelloWorld01x.tcl - 2015-06-24 #. '''Output 1x'''
xx
Remarks edit
This is the Alpha-version, there will be bugs, so use with caution...
See also:
- ClockDemo

- Whitejack
- tcltutorial
- http://www.tcl.tk/man/tcl8.5/tutorial/tcltutorial.html

- http://www.tcl.tk/man/tcl8.5/TclCmd/Tcl.htm


