summaryrefslogtreecommitdiffhomepage
path: root/tcl.html.markdown
blob: ddf53fe9b8f0106cb9588df4b9b789380547cae8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
---
language: Tcl
contributors:
    - ["Poor Yorick", "http://pooryorick.com/"]
---

Tcl was created by [John Ousterhout](http://wiki.tcl.tk/John Ousterout) as a
reusable scripting language for chip design tools he was creating.  In 1997 he
was awarded the [ACM Software System
Award](http://en.wikipedia.org/wiki/ACM_Software_System_Award) for Tcl.  Tcl
can be used both as an embeddable scripting language and as a general
programming language.  It can also be used as a portable C library, even in
cases where no scripting capability is needed, as it provides data structures
such as dynamic strings, lists, and hash tables.  The C library also provides
portable functionality for loading dynamic libraries, string formatting and
code conversion, filesystem operations, network operations, and more.

Tcl is a pleasure to program in.  Its discipline of exposing all programmatic
functionality as commands, including things like loops and mathematical
operations that are usually baked into the syntax of other languages, allows it
to fade into the background of whatever domain-specific functionality a project
needs.  Its design of exposing all values as strings, while internally caching
a structured representation, bridges the world of scripting and systems
programming in the best way.  Even Lisp is more syntactically heavy than Tcl.



```tcl
#! /bin/env tclsh

################################################################################
## 1. Guidelines 
################################################################################

# Tcl is not Bash or C!  This needs to be said because standard shell quoting
# habits almost work in Tcl and it is common for people to pick up Tcl and try
# to get by with syntax they know from another language.  It works at first,
# but soon leads to frustration with more complex scripts.
 
# Braces are just a quoting mechanism, not a code block constructor or a list
# constructor.  Tcl doesn't have either of those things.  Braces are used,
# though, to escape special characters in procedure bodies and in strings that
# are formatted as lists.


################################################################################
## 2. Syntax 
################################################################################

# Every line is a command.  The first word is the name of the command, and
# subsequent words are arguments to the command. Words are delimited by
# whitespace.  Since every word is a string, no escaping is necessary in the
# simple case.

set greeting1 Sal 
set greeting2 ut
set greeting3 ations


#semicolon also delimits commands

set greeting1 Sal; set greeting2 ut; set greeting3 ations 


# Dollar sign introduces variable substitution

set greeting $greeting1$greeting2


# Bracket introduces command substitution

set greeting $greeting[set greeting3]


# backslash suppresses the special meaning of characters

set amount \$16.42


# backslash adds special meaning to certain characters

puts lots\nof\n\n\n\n\n\nnewlines


# A word enclosed in braces is not subject to any special interpretation or
# substitutions, except that a backslash before a brace is not counted when look#ing for the closing brace
set somevar {
    This is a literal $ sign, and this \} escaped
    brace remains uninterpreted
} 

# In a word enclosed in double quotes, whitespace characters lose their special
# meaning 

set name Neo
set greeting "Hello, $name"


#variable names can be any string

set {first name} New


# The brace form of variable substitution handles more complex variable names

set greeting "Hello, ${first name}"


# The "set" command can always be used instead of variable substitution

set greeting "Hello, [set {first name}]"


# To promote the words within a word to individual words of the current
# command, use the expansion operator, "{*}".

set {*}{name Neo}

# is equivalent to

set name Neo


# An array is a special variable that is a container for other variables.

set person(name) Neo
set person(gender) male

set greeting "Hello, $person(name)"

# A namespace holds commands and variables

namespace eval people {
    namespace eval person1 {
        set name Neo
    }
}

#The full name of a variable includes its enclosing namespace(s), delimited by two colons:

set greeting "Hello $people::person::name"



################################################################################
## 3. A Few Notes 
################################################################################

# From this point on, there is no new syntax.  Everything else there is to
# learn about Tcl is about the behaviour of individual commands, and what
# meaning they assign to their arguments.


# All other functionality is implemented via commands.  To end up with an
# interpreter that can do nothing, delete the global namespace.  It's not very
# useful to do such a thing, but it illustrates the nature of Tcl.

namespace delete ::


# Because of name resolution behaviour, its safer to use the "variable" command to declare or to assign a value to a namespace.

namespace eval people {
    namespace eval person1 {
        variable name Neo
    }
}


# The full name of a variable can always be used, if desired.

set people::person1::name Neo



################################################################################
## 4. Commands 
################################################################################

# Math can be done with the "expr" command.

set a 3
set b 4
set c [expr {$a + $b}]

# Since "expr" performs variable substitution on its own, brace the expression
# to prevent Tcl from performing variable substitution first.  See
# "http://wiki.tcl.tk/Brace%20your%20#%20expr-essions" for details.


# The "expr" command understands variable and command substitution

set c [expr {$a + [set b]}]


# The "expr" command provides a set of mathematical functions

set c [expr {pow($a,$b)}]


# Mathematical operators are available as commands in the ::tcl::mathop
# namespace

::tcl::mathop::+ 5 3

# Commands can be imported from other namespaces

namespace import ::tcl::mathop::+
set result [+ 5 3]


# New commands can be created via the "proc" command.

proc greet name {
    return "Hello, $name!"
}


# As noted earlier, braces do not construct a code block.  Every value, even
# the third argument of the "proc" command, is a string.  The previous command
# could be defined without using braces at all:

proc greet name return\ \"Hello,\ \$name!


# When the last parameter is the literal value, "args", it collects all extra
# arguments when the command is invoked

proc fold {cmd args} {
    set res 0
    foreach arg $args {
        set res [cmd $res $arg]
    }
}

fold ::tcl::mathop::* 5 3 3 ;# ->  45



# Conditional execution is implemented as a command

if {3 > 4} {
    puts {This will never happen}
} elseif {4 > 4} {
    puts {This will also never happen}
} else {
    puts {This will always happen}
}


# Loops are implemented as commands.  The first, second, and third
# arguments of the "for" command are treated as mathematical expressions

for {set i 0} {$i < 10} {incr i} {
    set res [expr {$res + $i}]
}


# The first argument of the "while" command is also treated as a mathematical
# expression

set i 0
while {$i < 10} {
    incr i 2
}


# A list is a specially-formatted string.  In the simple case, whitespace is sufficient to delimit values

set amounts 10\ 33\ 18 
set amount [lindex $amounts 1]


# Braces and backslash can be used to format more complex values in a list.
# There are three items in the following 

set values {

    one\ two

    {three four}

    five\{six

}


# Since a list is a string, string operations could be performed on it, at the
# risk of corrupting the list.

set values {one two three four}
set values [string map {two \{} $values] ;# $values is no-longer a \
    properly-formatted listwell-formed list


# The sure-fire way to get a properly-formmated list is to use "list" commands
set values [list one \{ three four]

lappend values { } ;# add a single space as an item in the list


# Use "eval" to evaluate a value as a script

eval {
    set name Neo
    set greeting "Hello, $name"
}


# A list can always be passed to "eval" as a script composed of a single
# command.

eval {set name Neo}
eval [list set greeting "Hello, $name"]


# Therefore, when using "eval", use [list] to build up a desired command 

set command {set name}
lappend command {Archibald Sorbisol}
eval $command


# A common mistake is not to use list functions

set command {set name}
append command { Archibald Sorbisol}
eval $command ;# There is an error here, because there are too many arguments \
    to "set" in {set name Archibald Sorbisol}


# This mistake can easily occur with the "subst" command.

set replacement {Archibald Sorbisol}
set command {set name $replacement}
set command [subst $command] 
eval $command ;# The same error as before:  to many arguments to "set" in \
    {set name Archibald Sorbisol}


# The proper way is to format the substituted value using use the "list"
# command.

set replacement [list {Archibald Sorbisol}]
set command {set name $replacement}
set command [subst $command] 
eval $command


# It is extremely common to see the "list" command being used to properly
# format values that are substituted into Tcl script templates.  There is an
# example of this in the following replacement "while" implementation.


#get rid of the built-in "while" command.

rename ::while {}


# Define a new while command with the "proc" command.  More sophisticated error
# handling is left as an exercise.

proc while {condition script} {
    if {[uplevel 1 [list expr $condition]]} {
        uplevel 1 $script
        tailcall [namespace which while] $condition $script
    }
}
```

## Reference

[Official Tcl Documentation](http://www.tcl.tk/man/tcl/)

[Tcl Wiki](http://wiki.tcl.tk)

[Tcl Subreddit](http://www.reddit.com/r/Tcl)