From a7dc8b2f4c349d00754d346c78672844523b42ba Mon Sep 17 00:00:00 2001 From: Poor Yorick Date: Thu, 1 Jan 2015 21:41:21 -0700 Subject: add Tcl document --- tcl.html.markdown | 372 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 372 insertions(+) create mode 100755 tcl.html.markdown (limited to 'tcl.html.markdown') diff --git a/tcl.html.markdown b/tcl.html.markdown new file mode 100755 index 00000000..32619b7c --- /dev/null +++ b/tcl.html.markdown @@ -0,0 +1,372 @@ +--- +language: Tcl +contributors: + - ["Poor Yorick", "http://pooryorick.com/"] +filename: learntcl +--- + +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 + } +} +``` + + -- cgit v1.2.3 From 335d618b1a7ef1793ba30402101c58438bd44603 Mon Sep 17 00:00:00 2001 From: Poor Yorick Date: Thu, 1 Jan 2015 21:48:42 -0700 Subject: add reference --- tcl.html.markdown | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'tcl.html.markdown') diff --git a/tcl.html.markdown b/tcl.html.markdown index 32619b7c..ddf53fe9 100755 --- a/tcl.html.markdown +++ b/tcl.html.markdown @@ -2,7 +2,6 @@ language: Tcl contributors: - ["Poor Yorick", "http://pooryorick.com/"] -filename: learntcl --- Tcl was created by [John Ousterhout](http://wiki.tcl.tk/John Ousterout) as a @@ -369,4 +368,10 @@ proc 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) -- cgit v1.2.3 From a80663a4ceeadaa813e17918123eff837e91fc51 Mon Sep 17 00:00:00 2001 From: Poor Yorick Date: Fri, 2 Jan 2015 07:56:48 -0700 Subject: better verbiage, add more commands. --- tcl.html.markdown | 159 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 59 deletions(-) (limited to 'tcl.html.markdown') diff --git a/tcl.html.markdown b/tcl.html.markdown index ddf53fe9..5402ce04 100755 --- a/tcl.html.markdown +++ b/tcl.html.markdown @@ -49,8 +49,10 @@ programming in the best way. Even Lisp is more syntactically heavy than Tcl. # 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. +# whitespace. Since every word is a string, in the simple case no special +# markup such as quotes, braces, or backslash, is necessary. Even when quotes +# are used, they are not a string constructor, but just another escaping +# character. set greeting1 Sal set greeting2 ut @@ -58,27 +60,34 @@ 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$greeting3 -set greeting $greeting1$greeting2 +# Bracket introduces command substitution. The result of the command is +# substituted in place of the bracketed script. When the "set" command is +# given only the name of a variable, it returns the value of that variable. +set greeting $greeting1$greeting2[set greeting3] -# Bracket introduces command substitution -set greeting $greeting[set greeting3] +# Command substitution should really be called script substitution, because an +# entire script, not just a command, can be placed between the brackets. The +# "incr" command increments the value of a variable and returns its value. +set greeting $greeting[ + incr i + incr i + incr i +] # 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 @@ -89,55 +98,48 @@ set somevar { 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 +# 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: +#The full name of a variable includes its enclosing namespace(s), delimited by two colons: set greeting "Hello $people::person::name" @@ -146,20 +148,19 @@ 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. 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. - +# 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 @@ -168,7 +169,6 @@ namespace eval people { # The full name of a variable can always be used, if desired. - set people::person1::name Neo @@ -178,7 +178,6 @@ set people::person1::name Neo ################################################################################ # Math can be done with the "expr" command. - set a 3 set b 4 set c [expr {$a + $b}] @@ -189,56 +188,52 @@ set c [expr {$a + $b}] # 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!" } +#multiple parameters can be specified +proc greet {greeting name} { + return "$greeting, $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: +# rewritten to not use braces at all: +proc greet greeting\ name return\ \"Hello,\ \$name! -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} { @@ -250,7 +245,6 @@ if {3 > 4} { # 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}] } @@ -258,7 +252,6 @@ for {set i 0} {$i < 10} {incr i} { # The first argument of the "while" command is also treated as a mathematical # expression - set i 0 while {$i < 10} { incr i 2 @@ -266,14 +259,14 @@ while {$i < 10} { # 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 - +# Braces and backslash can be used to format more complex values in a list. A +# list looks exactly like a script, except that the newline character and the +# semicolon character lose their special meanings. This feature makes Tcl +# homoiconic. There are three items in the following list. set values { one\ two @@ -286,8 +279,7 @@ set values { # Since a list is a string, string operations could be performed on it, at the -# risk of corrupting the list. - +# risk of corrupting the formatting of the list. set values {one two three four} set values [string map {two \{} $values] ;# $values is no-longer a \ properly-formatted listwell-formed list @@ -295,12 +287,10 @@ set values [string map {two \{} $values] ;# $values is no-longer a \ # 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" @@ -309,20 +299,17 @@ eval { # 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 - +# A common mistake is not to use list functions when building up a command set command {set name} append command { Archibald Sorbisol} eval $command ;# There is an error here, because there are too many arguments \ @@ -330,7 +317,6 @@ eval $command ;# There is an error here, because there are too many arguments \ # This mistake can easily occur with the "subst" command. - set replacement {Archibald Sorbisol} set command {set name $replacement} set command [subst $command] @@ -340,7 +326,6 @@ eval $command ;# The same error as before: to many arguments to "set" in \ # 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] @@ -348,24 +333,80 @@ 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. +# format values that are substituted into Tcl script templates. There are +# several examples of this, below. -#get rid of the built-in "while" command. +# The "apply" command evaluates a string as a command. +set cmd {{greeting name} { + return "$greeting, $name!" +}} +apply $cmd Whaddup Neo + + +# The "uplevel" command evaluates a script in some enclosing scope. +proc greet {} { + uplevel {puts "$greeting, $name"} +} + +proc set_double {varname value} { + if {[string is double $value]} { + uplevel [list variable $varname $value] + } else { + error [list {not a double} $value] + } +} + +# The "upvar" command links a variable in the current scope to a variable in +# some enclosing scope +proc set_double {varname value} { + if {[string is double $value]} { + upvar 1 $varname var + set var $value + } else { + error [list {not a double} $value] + } +} + + +#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 } } + + +# The "coroutine" command creates a separate call stack, along with a command +# to enter that call stack. The "yield" command suspends execution in that +# stack. +proc countdown {} { + #send something back to the initial "coroutine" command + yield + + set count 3 + while {$count > 1} { + yield [incr count -1] + } + return 0 +} +coroutine countdown1 countdown +coroutine countdown2 countdown +puts [countdown 1] ;# -> 2 +puts [countdown 2] ;# -> 2 +puts [countdown 1] ;# -> 1 +puts [countdown 1] ;# -> 0 +puts [coundown 1] ;# -> invalid command name "countdown1" +puts [countdown 2] ;# -> 1 + + ``` ## Reference -- cgit v1.2.3 From aac20efb70dbd10383c9bfa4dd9108d8a4fda9ce Mon Sep 17 00:00:00 2001 From: Poor Yorick Date: Fri, 2 Jan 2015 08:19:41 -0700 Subject: Reworked summary --- tcl.html.markdown | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) (limited to 'tcl.html.markdown') diff --git a/tcl.html.markdown b/tcl.html.markdown index 5402ce04..44805b5c 100755 --- a/tcl.html.markdown +++ b/tcl.html.markdown @@ -13,15 +13,43 @@ 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. +code conversion, filesystem operations, network operations, and more. +Various features of Tcl stand out: + +* Convenient cross-platform networking API + +* Fully virtualized filesystem + +* Stackable I/O channels + +* Asynchronous to the core + +* Full coroutines + +* A threading model recognized as robust and easy to use + + +If Lisp is a list processor, then Tcl is a string processor. All values are +strings. A list is a string format. A procedure definition is a string +format. To achieve performance, Tcl internally caches structured +representations of these values. The list commands, for example, operate on +the internal cached representation, and Tcl takes care of updating the string +representation if it is ever actually needed in the script. The copy-on-write +design of Tcl allows script authors can pass around large data values without +actually incurring additional memory overhead. Procedures are automatically +byte-compiled unless they use the more dynamic commands such as "uplevel", +"upvar", and "trace". + +Tcl is a pleasure to program in. It will appeal to hacker types who find Lisp, +Forth, or Smalltalk interesting, as well as to engineers and scientists who +just want to get down to business with a tool that bends to their will. 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. It's syntax, which is even +lighter that that of Lisp, just gets out of the way. + + -- cgit v1.2.3 From 79b730dcaa8994cb6b58af1e25a5aa9e06f48471 Mon Sep 17 00:00:00 2001 From: Poor Yorick Date: Sun, 4 Jan 2015 23:00:23 -0700 Subject: add filename: learntcl.tcl --- tcl.html.markdown | 893 +++++++++++++++++++++++++++--------------------------- 1 file changed, 447 insertions(+), 446 deletions(-) (limited to 'tcl.html.markdown') diff --git a/tcl.html.markdown b/tcl.html.markdown index 44805b5c..f2d92fcd 100755 --- a/tcl.html.markdown +++ b/tcl.html.markdown @@ -1,446 +1,447 @@ ---- -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. -Various features of Tcl stand out: - -* Convenient cross-platform networking API - -* Fully virtualized filesystem - -* Stackable I/O channels - -* Asynchronous to the core - -* Full coroutines - -* A threading model recognized as robust and easy to use - - -If Lisp is a list processor, then Tcl is a string processor. All values are -strings. A list is a string format. A procedure definition is a string -format. To achieve performance, Tcl internally caches structured -representations of these values. The list commands, for example, operate on -the internal cached representation, and Tcl takes care of updating the string -representation if it is ever actually needed in the script. The copy-on-write -design of Tcl allows script authors can pass around large data values without -actually incurring additional memory overhead. Procedures are automatically -byte-compiled unless they use the more dynamic commands such as "uplevel", -"upvar", and "trace". - -Tcl is a pleasure to program in. It will appeal to hacker types who find Lisp, -Forth, or Smalltalk interesting, as well as to engineers and scientists who -just want to get down to business with a tool that bends to their will. 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. It's syntax, which is even -lighter that that of Lisp, just gets out of the way. - - - - - -```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, in the simple case no special -# markup such as quotes, braces, or backslash, is necessary. Even when quotes -# are used, they are not a string constructor, but just another escaping -# character. - -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$greeting3 - - -# Bracket introduces command substitution. The result of the command is -# substituted in place of the bracketed script. When the "set" command is -# given only the name of a variable, it returns the value of that variable. -set greeting $greeting1$greeting2[set greeting3] - - -# Command substitution should really be called script substitution, because an -# entire script, not just a command, can be placed between the brackets. The -# "incr" command increments the value of a variable and returns its value. -set greeting $greeting[ - incr i - incr i - incr i -] - - -# 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 -################################################################################ - -# All other functionality is implemented via commands. 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. - - -# 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!" -} - -#multiple parameters can be specified -proc greet {greeting name} { - return "$greeting, $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 -# rewritten to not use braces at all: -proc greet greeting\ 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. A -# list looks exactly like a script, except that the newline character and the -# semicolon character lose their special meanings. This feature makes Tcl -# homoiconic. There are three items in the following list. -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 formatting of 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 when building up a command -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 are -# several examples of this, below. - - -# The "apply" command evaluates a string as a command. -set cmd {{greeting name} { - return "$greeting, $name!" -}} -apply $cmd Whaddup Neo - - -# The "uplevel" command evaluates a script in some enclosing scope. -proc greet {} { - uplevel {puts "$greeting, $name"} -} - -proc set_double {varname value} { - if {[string is double $value]} { - uplevel [list variable $varname $value] - } else { - error [list {not a double} $value] - } -} - - -# The "upvar" command links a variable in the current scope to a variable in -# some enclosing scope -proc set_double {varname value} { - if {[string is double $value]} { - upvar 1 $varname var - set var $value - } else { - error [list {not a double} $value] - } -} - - -#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 - } -} - - -# The "coroutine" command creates a separate call stack, along with a command -# to enter that call stack. The "yield" command suspends execution in that -# stack. -proc countdown {} { - #send something back to the initial "coroutine" command - yield - - set count 3 - while {$count > 1} { - yield [incr count -1] - } - return 0 -} -coroutine countdown1 countdown -coroutine countdown2 countdown -puts [countdown 1] ;# -> 2 -puts [countdown 2] ;# -> 2 -puts [countdown 1] ;# -> 1 -puts [countdown 1] ;# -> 0 -puts [coundown 1] ;# -> invalid command name "countdown1" -puts [countdown 2] ;# -> 1 - - -``` - -## Reference - -[Official Tcl Documentation](http://www.tcl.tk/man/tcl/) - -[Tcl Wiki](http://wiki.tcl.tk) - -[Tcl Subreddit](http://www.reddit.com/r/Tcl) +--- +language: Tcl +contributors: + - ["Poor Yorick", "http://pooryorick.com/"] +filename: learntcl.tcl +--- + +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. +Various features of Tcl stand out: + +* Convenient cross-platform networking API + +* Fully virtualized filesystem + +* Stackable I/O channels + +* Asynchronous to the core + +* Full coroutines + +* A threading model recognized as robust and easy to use + + +If Lisp is a list processor, then Tcl is a string processor. All values are +strings. A list is a string format. A procedure definition is a string +format. To achieve performance, Tcl internally caches structured +representations of these values. The list commands, for example, operate on +the internal cached representation, and Tcl takes care of updating the string +representation if it is ever actually needed in the script. The copy-on-write +design of Tcl allows script authors can pass around large data values without +actually incurring additional memory overhead. Procedures are automatically +byte-compiled unless they use the more dynamic commands such as "uplevel", +"upvar", and "trace". + +Tcl is a pleasure to program in. It will appeal to hacker types who find Lisp, +Forth, or Smalltalk interesting, as well as to engineers and scientists who +just want to get down to business with a tool that bends to their will. 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. It's syntax, which is even +lighter that that of Lisp, just gets out of the way. + + + + + +```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, in the simple case no special +# markup such as quotes, braces, or backslash, is necessary. Even when quotes +# are used, they are not a string constructor, but just another escaping +# character. + +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$greeting3 + + +# Bracket introduces command substitution. The result of the command is +# substituted in place of the bracketed script. When the "set" command is +# given only the name of a variable, it returns the value of that variable. +set greeting $greeting1$greeting2[set greeting3] + + +# Command substitution should really be called script substitution, because an +# entire script, not just a command, can be placed between the brackets. The +# "incr" command increments the value of a variable and returns its value. +set greeting $greeting[ + incr i + incr i + incr i +] + + +# 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 +################################################################################ + +# All other functionality is implemented via commands. 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. + + +# 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!" +} + +#multiple parameters can be specified +proc greet {greeting name} { + return "$greeting, $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 +# rewritten to not use braces at all: +proc greet greeting\ 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. A +# list looks exactly like a script, except that the newline character and the +# semicolon character lose their special meanings. This feature makes Tcl +# homoiconic. There are three items in the following list. +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 formatting of 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 when building up a command +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 are +# several examples of this, below. + + +# The "apply" command evaluates a string as a command. +set cmd {{greeting name} { + return "$greeting, $name!" +}} +apply $cmd Whaddup Neo + + +# The "uplevel" command evaluates a script in some enclosing scope. +proc greet {} { + uplevel {puts "$greeting, $name"} +} + +proc set_double {varname value} { + if {[string is double $value]} { + uplevel [list variable $varname $value] + } else { + error [list {not a double} $value] + } +} + + +# The "upvar" command links a variable in the current scope to a variable in +# some enclosing scope +proc set_double {varname value} { + if {[string is double $value]} { + upvar 1 $varname var + set var $value + } else { + error [list {not a double} $value] + } +} + + +#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 + } +} + + +# The "coroutine" command creates a separate call stack, along with a command +# to enter that call stack. The "yield" command suspends execution in that +# stack. +proc countdown {} { + #send something back to the initial "coroutine" command + yield + + set count 3 + while {$count > 1} { + yield [incr count -1] + } + return 0 +} +coroutine countdown1 countdown +coroutine countdown2 countdown +puts [countdown 1] ;# -> 2 +puts [countdown 2] ;# -> 2 +puts [countdown 1] ;# -> 1 +puts [countdown 1] ;# -> 0 +puts [coundown 1] ;# -> invalid command name "countdown1" +puts [countdown 2] ;# -> 1 + + +``` + +## Reference + +[Official Tcl Documentation](http://www.tcl.tk/man/tcl/) + +[Tcl Wiki](http://wiki.tcl.tk) + +[Tcl Subreddit](http://www.reddit.com/r/Tcl) -- cgit v1.2.3 From da58d73ad0a257d0502554bb77d14e186a2eeee4 Mon Sep 17 00:00:00 2001 From: Chunyang Xu Date: Mon, 9 Mar 2015 13:57:30 +0800 Subject: [tcl/en] Fix typos --- tcl.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tcl.html.markdown') diff --git a/tcl.html.markdown b/tcl.html.markdown index f2d92fcd..198f675e 100755 --- a/tcl.html.markdown +++ b/tcl.html.markdown @@ -169,7 +169,7 @@ namespace eval people { #The full name of a variable includes its enclosing namespace(s), delimited by two colons: -set greeting "Hello $people::person::name" +set greeting "Hello $people::person1::name" @@ -189,7 +189,7 @@ set greeting "Hello $people::person::name" namespace delete :: -# Because of name resolution behaviour, its safer to use the "variable" command to declare or to assign a value to a namespace. +# Because of name resolution behaviour, it's 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 -- cgit v1.2.3