#!/usr/bin/tclsh
set n 42
puts -nonewline "Guess the number ? "
flush stdout
scan [gets stdin] "%d" v
if {$v < 0} {
puts "Only positive numbers"
return
}
if {$n == $v} {
puts "Good job!";
} else {
set h [ expr ($v > $n) ? $v - $n : $n - $v]
puts "Keep trying!."
puts "The nymber is [expr {$v > $n ? "HIGHER" : "LOWER"}]"
puts -nonewline "HINT : "
if {$h < 5} {puts "TOO HOT!"
} elseif {$h < 10} {puts "HOT!"
} elseif {$h < 15} {puts "WARM"
} else {puts "COLD"}
}TCL provides a good set of instructions for building our conditions.
In addition to the ternary operator with the classic syntax, it offers
if-elseif-else blocks with a C-style syntax, using
{} to group instructions.
DID YOU KNOW
The position of the curly braces matters. The opening braces must be on the same line as the clause they belong to (
if,elseiforelse). Similarly, the closing braces must be on the same line as the clauses you want to chain (elseiforelse). The last brace}can be placed on a separate line.
TCL offers the switch statement and, like
bash, works directly on strings of characters (typical of
this language). The switch command in TCL has the
peculiarity that it offers different options to determine which case
should be executed:
-nocase. Ignores uppercase and lowercase letters.-exact. Cases are compared exactly.-glob. Allows the use of wildcards to specify the cases.-regexp. Allows the use of regular expressions in the cases.-matchvar varName. Only works with-regexpand allows us to indicate a variable where the parts of the regular expression that match will be stored.-indexvar varName. Same as above, but stores the start and end indices of each occurrence in the indicated variable.--. Used to indicate the end of the options when multiple are used.
A normal example of switch would be the following:
scan [gets stdin] "%s" v
switch $v {
"ciao" -
"bye" {puts "CU" }
"hello" {puts "Hi!!" }
default {puts "Who cares?" }
}We can use the - character to indicate that the command
associated with a particular case is the same as that of the next case….
Look at the ciao case in the example above.
TCL allows us to use variables as conditions for the cases, but in
this case we must use " instead of {} to
enclose our cases, or write all the cases on one line.
set foo "hello"
switch $v "ciao" - "bye" {puts "CU"} $foo {puts "Hi!"} \
default {puts "who cares?")or
set foo "hello"
switch $v "
\"ciao\" -
\"bye\" {puts \"CU\" }
$foo {puts \"Hi!!\" }
default {puts \"Who cares?\" } "Note how it is necessary to escape all quotes within the cases.
I’M A NEWBIE
In most languages we use some character to delimit strings of characters, usually double quotes
"or single quotes'. The difference is often that one allows variable expansion (in languages that support that capability) and the other takes the string as is. In languages like C/C++/Java, single quotes are used to represent characters.But what happens if we want our string of characters to contain quotes?… Something like
"Hello "fulanito""… as you can see, the quotes that we open with the word fulanito will be considered the end of the string"Hello "… This will normally produce an error. In those cases, it is necessary to escape the special characters like quotes. In practically all programming languages, this is achieved by preceding the special character with the\character. Thus, our string would be written as"Hello \"fulanito\"".And if… the
\character also needs to be escaped, so you will see, especially in windows strings containing\\when defining file paths.
The reason is that if we use curly braces the string is not expanded and therefore the condition we think we are using is not correct. In our example using the curly braces:
set foo "hello"
switch $v {
"ciao" -
"bye" {puts "CU" }
$foo {puts "Hi!!" }
default {puts "Who cares?" }
}If we give v the value hello in the example
above, the switch block will print
A quien le importa?. But if we give it the value
$foo, we will get the desired result.
You can check this interactively in the tcl shell:
% set foo "hello"
hello
% set v $foo
hello
% set v "$foo"
hello
% set v {$foo}
$fooAs you can see, the variable foo is substituted when
used directly or within a string of characters, however, when we use it
within a block, what we get is the literal name we wrote
$foo in our case.
DID YOU KNOW
TCL does not offer functions to read specific data types directly from a file. The way to do it is to read a complete line using
[gets stdin]and then use thescanfunction to get the type we want. Thegetsfunction works the same as thegetsin C and thescanfunction works the same as thesscanfin C.
TCL does not support the definition of constants, although there are different ways to achieve that behavior. The simplest way is to use uppercase naming conventions, as in other languages, but you can also use a trace, as follows:
set CONSTANTE 123
trace add variable CONSTANTE write {apply {args {
global CONSTANTE
set CONSTANT 123
error "may not change constant"
}}}A trace is code that runs when a certain event occurs in the program.
In this example, when we try to write to the CONSTANTE
variable, we ignore the new value and set the constant value we want
again and display an error… since the fact that a program attempts to
modify a constant is a logical error that should be corrected.
Summary
- Supports
if ... [elsif] ...[else] ... - Supports ternary operator
(cond) ? true_value : false_value - Does not support boolean type:
==0 -> FALSE and !=0 TRUE - Supports
switch - Does not natively support constants