GUI Scripting: JavaScript, Smalltalk, Tcl, AutoHotkey

a side-by-side reference sheet

grammar and invocation | variables and expression | arithmetic and logic | strings | regexes | dates and time | arrays | dictionaries | functions | execution control | exceptions | streams | files | file formats | directories | processes and environment | libraries and namespaces | objects | inheritance and polymorphism | reflection | gui | net and web

javascript smalltalk tcl autohotkey
version used
ECMAScript 5 Pharo 3.0 8.5 1.1
show version
ECMAScript 5 compatibility SmalltalkImage current aboutThisSystem.

at command line:
$ ./pharo Pharo.image printVersion
$ tclsh
% info tclversion
msgbox % a_ahkversion
grammar and invocation
javascript smalltalk tcl autohotkey
$ tclsh foo.tcl > autohotkey foo.ahk
Javascript Console:

  Chrome (Mac): ⌥⌘J
  Chrome (Win): Ctrl+Shift+J
  Firefox (Mac): ⌥⌘K
  Firefox (Win): Ctrl+Shift+K
$ tclsh
command line program
$ Pharo --headless Pharo.image eval '1 + 1.' none none
statement separator ; or newline

newline not separator inside (), [], {}, "", '', or after binary operator

newline sometimes not separator when following line would not parse as a valid statement
period: . newline or ;

newline not a separator inside {}, "", [] or after backslash: \
sometimes newline

newline does not terminate statement:

  (1) inside parens
  (2) when following line starts with binary operator
block delimiters
{} [ ] {} or "" { }
regions which define lexical scope top level:
  html page

are expressions statements
yes no no
end-of-line comment
// comment no # comment ; comment
multiple line comment /* line
another line */
another comment
if (0) {
  commented out
  can contain {} if balanced
another comment
variables and expressions
javascript smalltalk tcl autohotkey
local variable var x = 1;

var y = 2, z = 3;
# set variable inside procedure:
proc foo {args} {
  set x 1
global variable // assign without using var
g = 1;

function incr_global () { g++; }
# set variable outside procedure:
set g 1

proc incr_global {} {
  global g
  incr g
assignment x = 1; a := 1. set x 1 s1 := PATH
s2 := "foo bar"

; traditional style:
s1 = %PATH%
s2 = foo bar
parallel assignment
none none lassign {1 2 3} x y z

# 3 is discarded:
lassign {1 2 3} x y

# z is set to "":
lassign {1 2} x y z
tmp = x;
x = y;
y = tmp;
lassign "$x $y" y x none
compound assignment
arithmetic, string, bit
+= -= *= /= none %=
<<= >>= &= |= ^=
+= -= *= /= //=
<<= >>= &= |= ^=
increment and decrement var x = 1;
var y = ++x;
var z = --y;
++i --i

i++ i--
variable declaration
null nil "" ""
null test
v === null v = nil v eq "" v == ""

; traditional style:
v =
undefined variable
undefined evaluates as nil error evaluates as empty string
conditional expression
x > 0 ? x : -x x > 0 ifTrue: [x] ifFalse: [0 - x] expr $x > 0 ? $x : -$x x > 0 ? x : -x
arithmetic and logic
javascript smalltalk tcl autohotkey
true and false
true false true false 1 0 1 0

true false
falsehoods false null undefined "" 0 NaN false 0 "false" "no"
most strings cause error in boolean context; nonzero numbers are true
0 ""
logical operators
&& || ! & | not && || ! and or not

&& || !
relational expression if {$x > 3} {…}
# outside of conditionals use expr:
expr $x > 3
relational operators
=== !== < > >= <=

perform type coercion:
== !=
= ~= > < >= <= == != > < >= <=

# string comparison:
eq ne
== != > < >= <=

case insensitive equality:
min and max Math.min(1, 2, 3)
Math.max(1, 2, 3)

Math.min.apply(Math, [1, 2, 3])
Math.max.apply(Math, [1, 2, 3])
expr min(1, 2, 3)
expr max(1, 2, 3)
arithmetic expression
1 + 3

"Binary operators are evaluated left to right.
This is 20:"

1 + 3 * 5
expr 1 + 3
# expr not needed in conditionals:
if {1 + 3} {}
1 + 3
arithmetic operators
addition, subtraction, multiplication, float division, quotient, remainder
+ - * / none % + - * / // \\ + - * none / % + - * / // none **

modulo function: mod(m, n)
integer division
Math.floor(x / y) 7 // 3 expr $x / $y 7 // 3
integer division by zero
returns assignable value Infinity, NaN, or -Infinity depending upon whether dividend is positive, zero, or negative.

There are literals for Infinity and NaN.
ZeroDivide exception error evaluates to empty string
float division
13 / 5 7 / 3 asFloat.

"exact rational:"
7 / 3
expr $x * 1.0 / $y 7 / 3
float division by zero
same behavior as for integers ZeroDivide exception returns assignable value Inf if dividend is positive and -Inf if negative. Raises error if dividend is zero.

There is a literal for
evaluates to empty string
Math.pow(2, 32) 2 raisedTo 32 expr 2 ** 32
expr pow(2, 32)
2 ** 32
Math.sqrt(2) 2 sqrt expr sqrt(2) sqrt(2)
sqrt -1
NaN raises DomainError error evaluates to empty string
transcendental functions Math.exp Math.log Math.sin Math.cos Math.tan Math.asin Math.acos Math.atan Math.atan2 exp ln
sin cos tan
arcSin arcCos arcTan
exp log sin cos tan asin acos atan atan2

# how to use math functions:
expr exp(2)
expr atan2(1, 1)
::tcl::mathfunc::exp 2
::tcl::mathfunc::atan2 1 1
exp ln
sin cos tan
asin acos atan
transcendental constants Math.PI
Float pi
Float e
expr 4 * atan(1)
expr exp(1)
float truncation
round towards zero, round to nearest integer, round down, round up
3.14 asInteger
3.14 rounded
3.14 ceiling
31.4 floor
expr int(3.1)
expr round(3.1)
expr floor(3.1)
expr ceil(3.1)
absolute value
Math.abs(-3) -7 abs expr abs(-7) abs(-7)
integer overflow
all numbers are floats converted to LargePositiveInteger or LargeNegativeInteger arbitrary length integers since 8.5 signed modular arithmetic
float overflow
Infinity Float infinity or Float infinity negated error evaluates to string value such as:
random integer, uniform float Math.floor(Math.random() * 100)
rnd := Random new.

rnd next.
(rnd nextInt: 100) - 1.
expr int(rand() * 100)
expr rand()
; store results in n and x:
random, n, 0, 99
random, x, 0.0, 1.0
seed random numbers
none rnd := Random new.
rnd :seed 17.
expr srand(17) random, , 17
bit operators
<< >> & | ^ ~ 5 bitShift: 1
5 bitShift: -1
5 bitAnd: 1
5 bitOr: 1
5 bitInvert
<< >> & | ^ ~ << >> & | ^ ~
binary, octal, and hex literals none
052 // deprecated
convert integer to and from string with radix
javascript smalltalk tcl autohotkey
string type
string literal "don't say \"no\""
'don\'t say "no"'
'don''t say "no"'. "don't say \"no\""
{don't say "no"}
"don't say ""no"""
newline in literal yes no

" print newline in Transcript:"
Transcript cr.
literal escapes single and double quotes:
\b \f \n \r \t \v \uhhhh \xhh \" \' \\
none in double quotes:
\a \b \f \n \r \t \v \\ \" \oooo \uhhhh \xhh
variable interpolation // None; use string concatenation.
// Both of these expressions are '11':

1 + "1"
"1" + 1
set count 3
set item "ball"
"$count ${item}s"
string concatenate s = "Hello, " + "World!"; 'hello, ', 'world' set s1 "Hello, "
set s2 "World!"
set s $s1$s2
"hello, " . "world"
string replicate
var hbar = Array(80).join("-"); set hbar [string repeat "-" 80]
string join
["do", "re", "mi"].join(" ") join [list "do" "re" "mi"] " "
// [ "do", "re", "", "mi", "" ]:
"do re  mi ".split(" ")

// [ "do", "re", "mi", "" ]:
"do re  mi ".split(/\s+/)
split "do re mi"
format string // None; use string concatenation.
// Evaluates to "12.35":

set fmt "lorem %s %d %.2f"
format $fmt "ipsum" 13 3.7
translate case
to upper, to lower
'hello' asUppercase
'HELLO' asLowercase
string toupper "lorem"
string tolower "LOREM"
s1 := "Hello"
stringupper, s2, s1
stringlower, s3, s2
trim " lorem ".trim()
# some browsers:
" lorem".trimLeft()
"lorem ".trimRight()
string trim " lorem "
string trimleft " lorem"
string trimright "lorem "
pad none format "%10s" "lorem"
format "%-10s" "lorem"
string to number 7 + parseInt("12", 10)
73.9 + parseFloat(".037")

// 12:
// NaN:
12' asInteger + 7 # use expr to interpret as numbers:
set x "12"
expr 7 + $x
set y ".037"
expr 73.9 + $y
number to string
"value: " + 8 7 printString, ' items' all values are strings
prefix and suffix test "foobar".startsWith("foo")
"lorem".length 'hello' byteSize string length "lorem" strlen("hello")
index of substring // returns -1 if not found:
"lorem ipsum".indexOf("ipsum")
'foo bar' indexOfAnyOf: 'bar' string first "ipsum" "lorem ipsum" ; returns 5:
instr("foo bar", "bar")
extract substring "lorem ipsum".substr(6, 5)
"lorem ipsum".substring(6, 11)
'foo bar' copyFrom: 5 to: 7 string range "lorem ipsum" 6 10 substr("foo bar", 5, 3)
character literal $A
character lookup "lorem ipsum"[6]
chr and ord String.fromCharCode(65)
65 asCharacter
$A asciiValue
format %c 65
scan A %c ascii_value
to array of characters "abcd".split("") split "abcd" ""
regular expressions
javascript smalltalk tcl autohotkey
regex match if (s.match(/1999/)) {
if [regexp -- {1999} $s] {
  puts "party!"
literal, custom delimited literal /lorem|ipsum/
character class abbreviations and anchors . \d \D \s \S \w \W char class abbrevs:
. \d \D \s \S \w \W

anchors: ^ $ \A \m \M \y \Y \Z
anchors ^ $ \b \B
case insensitive match test "Lorem".match(/lorem/i) regexp -nocase -- {lorem} "Lorem"
modifiers g i m -all -expanded -indices -inline
-line -lineanchor -linestop -nocase
substitution s = "do re mi mi mi";
s.replace(/mi/g, "ma");
set s "do re mi mi mi"
regsub -all -- "mi" $s "ma"
match, prematch, postmatch m = /\d{4}/.exec(s);
if (m) {
  match = m[0];
  # no prematch or postmatch
group capture rx = /^(\d{4})-(\d{2})-(\d{2})$/;
m = rx.exec('2009-06-03');
yr = m[1];
mo = m[2];
dy = m[3];
set s "2009-06-03"
set rx {^(\d{4})-(\d{2})-(\d{2})$}
regexp -- $rx $s - yr mo dy
named group capture
scan var a = "dolor sit amet".match(/\w+/g);
in regex, in substitution string
/(\w+) \1/.exec("do do")

"do re".replace(/(\w+) (\w+)/, '$2 $1')
regexp -- {(\w+) \1} "do do"

set rx {(\w+) (\w+)}
regsub -all -- $rx "do re" {\2 \1}
dates and time
javascript smalltalk tcl autohotkey
broken-down datetime type
current date/time var t = new Date(); Date today.
Time now.
set t [clock seconds]
to unix epoch, from unix epoch Math.round(t.getTime() / 1000)

var epoch = 1315716177;
var t2 = new Date(epoch * 1000);
set t2 1315716177
current unix epoch (new Date()).getTime() / 1000
strftime set fmt "%Y-%m-%d %H:%M:%S"
clock format $t -format $fmt
strptime none
parse date w/o format var t = new Date("July 7, 1999"); set t [clock scan "July 7, 1999"]
get date parts t.getFullYear()
t.getMonth() + 1
t.getDate() // getDay() is day of week
clock format $t -format "%Y"
clock format $t -format "%m"
clock format $t -format "%d"
get time parts t.getHours()
clock format $t -format "%H"
clock format $t -format "%M"
clock format $t -format "%S"
build date/time from parts var yr = 1999;
var mo = 9;
var dy = 10;
var hr = 23;
var mi = 30;
var ss = 0;
var t = new Date(yr, mo - 1, dy, hr, mi, ss);
result of date subtraction number containing time difference in milliseconds
add time duration var t1 = new Date();
var delta = (10 * 60 + 3) * 1000;
var t2 = new Date(t1.getTime() + delta);
local timezone
timezone name; offset from UTC; is daylight savings?
none after 500
javascript smalltalk tcl autohotkey
literal a = [1, 2, 3, 4] nums := OrderedCollection new.
nums add: 1; add: 2; add: 3; add: 4.

"creates immutable array:"
nums := #(1 2 3 4)
set a [list 1 2 3 4]
set a {1 2 3 4}
size a.length nums size llength $a
empty test // TypeError if a is null or undefined:
a.length === 0
lookup a[0] nums at: 1 lindex $a 0
update a[0] = "lorem" # provide start and end index:
# of elements to replace:

set a [lreplace $a 1 1 "lorem"]
out-of-bounds behavior returns undefined returns ""
index of element
first and last occurrence
// returns -1 if not found:
[6, 7, 7, 8].indexOf(7)
[6, 7, 7, 8].lastIndexOf(7)
lsearch {6 7 7 8} 7
lindex [lsearch -all {6 7 7 8} 7] end
# returns -1 if not found
slice // select 3rd and 4th elements:
["a", "b", "c", "d"].slice(2, 4)
nums copyFrom: 2 to: 3 lrange $a 1 2
slice to end ["a", "b", "c", "d"].slice(1) lrange {"a" "b" "c" "d"} 1 end
concatenation a = [1, 2, 3].concat([4, 5, 6]); set a [concat {1 2 3} {4 5 6}]
copy a = [1, 2, [3, 4]];
a2 = a;
a3 = a.slice(0);
a4 = JSON.parse(JSON.stringify(a));
manipulate back of array a = [6, 7, 8];
i = a.pop();
a := OrderedCollection new.
a add: 6; add: 7; add: 8.

a add: 9.
a removeLast.
set a {6 7 8}
lappend a 9
set i [lindex $a end]
set a [lreplace $a end end]
manipulate front of array a = [6, 7, 8];
i = a.shift();
a := OrderedCollection new.
a add: 6; add: 7; add: 8.

a addFirst: 5.
a removeFirst.
set a {6 7 8}
set a [concat {5} $a]
set a [lassign $a i]
array iteration [1, 2, 3].forEach(function(n) {
nums do: [:o| Transcript show: o printString; cr] foreach i $a { puts $i }
reverse var a = [1, 2, 3];
set a {1 2 3}
set a [lreverse $a]
sort var a = [3, 1, 4, 2];
set a {3 1 4 2}
set a [lsort $a]
dedupe lsort -unique {1 2 2 3}
nums includes: 7 expr {7 in $a}
expr {7 ni $a}
intersection package require struct::set

::struct::set intersect {1 2} {2 3}
union package require struct::set

::struct::set union {1 2} {2 3 4}
relative complement package require struct::set

::struct::set difference {1 2 3} {2}
// callback gets 3 args:
// value, index, array { return x * x })
#(1 2 3) collect: [ :o | o*o ] package require struct::list

proc sqr {x} {return [expr $x * $x]}
::struct::list map {1 2 3} sqr
a.filter(function(x) { return x > 1 }) #(1 2 3) select: [:o | o > 1] package require struct::list

proc gt1 {x} {return [expr $x > 1]}
::struct::list filter {1 2 3} gt1
a.reduce(function(m, o) {
    return m + o;
  }, 0)
#(1 2 3) inject: 0 into: [:m :o| m + o] package require struct::list

::struct::list fold {1 2 3} 0
universal test
#(1 2 3 4) allSatisfy: [:o | o even]
existential test
var a = [1, 2, 3, 4];
var even = function(x) {
  return x % 2 == 0;

#(1 2 3 4) anySatisfy: [:o | o even]
javascript smalltalk tcl autohotkey
d = {"t": 1, "f": 0};
// keys do not need to be quoted if they
// are a legal JavaScript variable name
and not a reserved word
h := Dictionary new add: 't'->1; add: 'f'->0; yourself set d [dict create t 1 f 0]
dictionary size
var size = 0;
for (var k in d) {
  if (d.hasOwnProperty(k)) size++;
h size dict size $d
h at: 't' dict get $d t
update d["t"] = 2;
d.t = 2;
dict set d t 2
missing key behavior
var d = {};
// sets s to undefined:
var s = d["lorem"];
// adds key/value pair:
d["lorem"] = "ipsum";
raises exception error
is key present
d.hasOwnProperty("t"); dict exists $d t
delete delete d["t"];
delete d.t;
dict unset d t
for (var k in d) {
  use k or d[k]
h keysAndValuesDo: [:k :v| code ] foreach {k v} $d {
keys and values as arrays h keys
h values
javascript smalltalk tcl autohotkey
define function add(x, y) {
  return x+y;
add := [ :a :b | a + b ] proc add { x y } {
  expr $x + $y
add(x, y) {
  return x + y
call add(1, 2) add value: 1 value: 2 # statement position:
add 1 2

# argument position:
set a [ add 1 2 ]
x := add(1, 2)
missing argument behavior set to// undefined raises BlockClosure exception error error
extra argument behavior ignored raises BlockClosure exception error error
default argument none proc log {x {base 10 }} { } fapprox(x, y, eps=0.001) {
  return abs(x - y) < eps
named parameters none
variadic function args in arguments[0], arguments[1], … with number of args in arguments.length last arg contains list of remaining values|f(args*) {
  return args.maxindex()
pass by reference swap(byref v1, byref v2) {
  tmp := v1
  v1 := v2
  v2 := tmp
return value Return arg or undefined. If invoked with new and return value not an object, returns this. return arg or empty string argument of return
nested function defined when containing function executes; visible outside containing function
anonymous function literal var sqr = function(x) { return x*x; } set sqr {{x} {return [expr $x*$x]}}
call anonymous function
sqr(2) apply $sqr 2
function with private state function counter() {
  counter.i += 1;
  return counter.i;

counter.i = 0;
closure function make_counter() {
  var i = 0;

  return function() {
    i += 1;
    return i;
execution control
javascript smalltalk tcl autohotkey
if if (0 == n) {
  alert("no hits");
} else if (1 == n) {
  alert("1 hit");
} else {
  alert(n + " hits");
msg := [ :s | Transcript show: s. Transcript cr ]

n = 0
ifTrue: [
  msg value: 'no hits' ]
ifFalse: [
  n = 1
  ifTrue: [
    msg value: '1 hit' ]
  fFalse: [
    msg value: n printString, ' hits' ]].
if { 0 == $n } {
  puts "no hits"
} elseif { 1 == $n } {
  puts "1 hit"
} else {
  puts "$n hits"
if (n = 0) {
  msgbox % "zero hits"
else if (n = 1) {
  msgbox % "one hit"
else {
  msgbox % n . " hits"
switch switch (n) {
case 0:
  alert("no hits\n");
case 1:
  alert("one hit\n");
  alert(n + " hits\n");
while while (i < 100) {
  i += 1;
[ i < 100 ]
whileTrue: [
  i := i + 1 ].
while { $i < 100 } {
  incr i
break/continue break continue break continue exit 0
for for (var i = 0; i < 10; i++) {
1 to: 100 do: [ :i |
  msg value: i printString ].
for {set i 0} {$i < 10} {incr i} {
  puts $i
javascript smalltalk tcl autohotkey
base exception Any value can be thrown.
predefined exceptions Error
raise exception throw new Error("bad arg"); Exception raiseSignal: 'bam!'. error "bad arg"
catch-all handler
try {
catch (e) {
  alert("risky failed: " + e.message);
uncaught exception behavior stderr and exit
re-raise exception try {
  throw new Error("bam!");
catch (e) {
  throw e;
global variable for last exception none
define exception function Bam(msg) {
  this.message = msg;

Bam.prototype = new Error;
handle exception try {
  throw new Bam("bam!");
catch (e) {
  if (e instanceof Bam) {
  else {
    throw e;
[ o risky ] on: Exception do: [ :ex |
  Transcript show: 'risky failed' ]
catch risky retval
if { retval != 0 } {
    puts "risky failed"
finally block
try {
finally {
javascript smalltalk tcl autohotkey
standard file handles stdin
read line from stdin gets stdin line
end-of-file behavior
chomp string trimright $line "\r\n"
write line to stdout puts "Hello, World!"
write formatted string to stdout
open file for reading set f [open "/tmp/foo"]
open file for writing set f [open "/tmp/foo" "w"]
set file handle encoding
open file for appending
close file
close $f
close file implicitly
i/o error
encoding error
read line
gets $f
iterate over file by line while { [gets $f s] >= 0 } {
  use s
read file into array of strings
read file into string set s [ read $f]
write string
puts -nonewline $f "lorem ipsum"
write line
flush file handle flush $f
end-of-file test
get and set file handle position
open temporary file
in memory file
javascript smalltalk tcl autohotkey
file exists test, file regular test file exists "/etc/hosts"
file isfile "/etc/hosts"
file size
is file readable, writable, executable
set file permissions set s "/tmp/foo"
file attributes $s -permissions 0755
last modification time
copy file, remove file, rename file file copy "/tmp/foo" "/tmp/bar"
file delete "/tmp/foo"
file rename "/tmp/bar" "/tmp/foo"
create symlink, symlink test, readlink
generate unused file name set tmp [::fileutil::tempfile foo]
set f [open $tmp "w"]
puts $f "lorem ipsum"
close $f
puts "tmp file: $tmp"
file formats
javascript smalltalk tcl autohotkey
parse json var s1 = '{"t":1,"f":0}';
var d1 = JSON.parse(s1);
generate json var d2 = {'t': 1, 'f': 0};
var s2 = JSON.stringify(d1);
javascript smalltalk tcl autohotkey
working directory
get and set
build pathname file join "/etc" "hosts"
dirname and basename file dirname "/etc/hosts"
file tail "/etc/hosts"
absolute pathname
iterate over directory by file
glob paths
make directory file mkdir "/tmp/foo/bar"
recursive copy
remove empty directory file delete "/tmp/foodir"
remove directory and contents file delete -force "/tmp/foodir"
directory test
file isdirectory "/tmp"
generate unused directory
system temporary file directory
processes and environment
javascript smalltalk tcl autohotkey
command line arguments [lindex $argv 0]
[lindex $argv 1]
environment variable
get, set
get pid, parent pid
exit 0
external command exec ls
command substitution set f [ open |ls ]
read f
libraries and namespaces
javascript smalltalk tcl autohotkey
load library source foo.tcl
add 3 7
load library in subdirectory
hot patch
load error
main routine in library
library path none
library path environment variable TCLLIBPATH
library path command line option
simple global identifiers
multiple label identifiers
label separator ::
namespace declaration namespace
child namespace declaration
unqualified import of namespace
unqualified import of definitions
list installed packaged, install a package
javascript smalltalk tcl autohotkey
define class
function Int(i) {
  this.value = i === undefined ? 0 : i;
create object
var i = new Int();
var i2 = new Int(7);
instance variable visibility public
get and set instance variable
var v = i.value;
i.value = v + 1;
define method
// inside constructor: = function(v) {
  return this.value + v;

// outside constructor: = function (v) {
  return this.value + v;
invoke method;
inheritance and polymorphism
javascript smalltalk tcl autohotkey
overload operator
javascript smalltalk tcl autohotkey
object id
inspect type
typeof([]) === 'object'
basic types number

# these evaluate as 'object':
inspect class // returns prototype object:
'hello' class
inspect class hierarchy var pa = Object.getPrototypeOf(o)
//prototype's of prototype object:
var grandpa = Object.getPrototypeOf(pa)
has method?
o.reverse && typeof(o.reverse) === 'function'
message passing
not a standard feature
eval('1 + 1')
list object methods
1 class selectors.
list object attributes
list loaded libraries
list loaded namespaces
inspect namespace
var d = {"lorem": 1, "ipsum": [2, 3]};
console.log(JSON.stringify(d, null, 2));
source line number and file name
command line documentation
javascript smalltalk tcl autohotkey
pop-up box var app = Application.currentApplication()
app.includeStandardAdditions = true
app.displayAlert('hi world')
package require Tk

wm title .
grid [ttk::frame .f -padding "10 10 10 10"]
grid [ttk::label .f.t -text "hi world"]
msgbox % "hi world"
text entry
net and web
javascript smalltalk tcl autohotkey
get local hostname, dns lookup, reverse dns lookup
http get
http post
serve working directory
absolute url
from base and relative url
parse url
url encode/decode
html escape
escape character data, escape attribute value, unescape html entities
base64 encode/decode
____________________________________________ ____________________________________________ ____________________________________________ ____________________________________________


version used

The version of the language used for verifying the examples in the reference sheet.

show version

How to get the version.

Grammar and Invocation


The customary name of the interpreter and how to invoke it.

command line program

How to pass a single command to be executed as a command line argument.

statement separator

How the parser determines the end of a statement.


Code fragments such as

1 + 1


[expr 1 + 1]

result in invalid command name errors when used as statements.

The following is a valid statement:

expr 1 + 1

The above cannot be used as an argument to a command without putting it inside square brackets, however.

Since the constructs which can be used as statements and the constructs which can be used in the positions where expressions are normally used are disjoint, we claim that expressions are not statements in Tcl.

block delimiters

How blocks are delimited.


The block delimiters {} and "" are the same as the string delimiters. Double quotes "" cause variable interpolation and as a result they are not often used to delimit blocks.

The following three lines of code behave the same:

if {true} {puts "true"}

if "true" "puts \"true\""

if "true" "puts {true}"

are expressions statements

Whether an expression can be used where a statement is expected.

to end-of-line comment

How to make the remainder of the line a comment.

multiline comment

How to comment out multiple lines.


The method described requires that there not be an unmatched right curly bracket in the comment.

Variables and Expressions

are identifiers case sensitive


How to assign a value to a variable.

parallel assignment

How to assign values to variables in parallel.


How to exchange the values held by two variables.

compound assignment

The compound assignment operators for arithmetic, string, and bit operations

increment and decrement

The C-style increment and decrement operators which can be used in expressions.

variable declaration

How to declare a variable.


The null literal.


Tcl has has no null value.

null test

How to test if a value is null.

undefined variable

The value of an undefined variable, or the behavior if there is no such value.


The following test can be used to determine if a variable is defined:

expr ![info exists v]

Arithmetic and Logic

true and false

The literals for true and false.


Values which are false in conditional expressions.


0 is false and all other numeric values are true. For non-numeric strings, "no" and "false" are false, and "yes" and "true" are true. The comparison is case insensitive. All other non-numeric strings raise an error when evaluated in a boolean context.

logical operators

Logical and, or, and not.

conditional expression

The syntax for a conditional expression.

relational expression


To evaluate a relational expression outside of the the conditional of an if statement, the expr command can be used.

Use square brackets to make an expression an argument of a command:

puts [expr $x>1]

relational operators


The eq and ne operators always perform comparisons on their operators as strings. If the arguments are numeric, they are converted to a standard floating point representation.

% expr {"0" eq "00"}
% expr {"0" == "00"}

The == and != operators try to convert their arguments to a numeric form for the purpose of comparison. String comparison is used when no numeric conversion is possible:

% expr {"lorem" == "ipsum"}

The relational operators can be invoked as commands in the following manner:

% ::tcl::mathop::== 1 1
% ::tcl::mathop::!= 1 1
% ::tcl::mathop::> 1 1
%::tcl::mathop::< 1 1
% ::tcl::mathop::>= 1 1
% ::tcl::mathop::<= 1 1
% ::tcl::mathop::eq "lorem" "ipsum"
%::tcl::mathop::ne "lorem" "ipsum"


<> is a synonym for !=.

convert from string

convert to string

arithmetic expressions

How to evaluate an arithmetic expression.


Arithmetic expressions are normally evaluated with the expr command. However, the conditional argument of an if statement is always evaluated as an expression.

arithmetic operators

The operators for addition, subtraction, multiplication, float division, integer division, modulus, and exponentiation. Some languages provide a function pow instead of an operator for exponentiation.


Arithmetic operators are normally used as arguments to expr, but commands also exist for each of them:


integer division

How to perform integer division.

float division

How to perform floating point division, even if the operands might be integers.

arithmetic functions

Functions for computing square root, natural exponent, natural logarithm, sine, cosine, tangent, arcsine, arccosine, arctangent, and atan2.

The trigonometric functions are all in radians. atan2 takes two arguments which are the x and y co-ordinates of a vector in the Cartesian plane. It returns
the angle to the positive x-axis made by the vector.

arithmetic truncation

division by zero

integer overflow

float overflow

sqrt -2

The result of taking the square root of -2.

random integer, uniform float

The examples show how to generate a uniform random integer in the range from 0 to 99, inclusive; how to generate a uniform float in the range 0.0 to 1.0; how to generate a float from a standard normal distribution

seed random numbers

bit operators


string literal

The syntax for a string literal and how to escape the delimiter.

newline in literal

Whether a newline character sequence can be included in a string.

For all the languages described in this reference sheet a string literal is permitted to encompass multiple lines in the source code and the resulting string will contain the same number of lines.


Character escape sequences which can be used in string literals.

variable interpolation

How to interpolate variables in a string.


How to get the length of a string.

index substring

How to find the index of the start of a substring in a string.

extract substring

string concatenation

The string concatenation operator.


How to split a string into an array of strings.


split takes an optional 2nd argument which is a string containing the characters to split on. split can only split on characters, not strings or regular expressions. For each pair of adjacent splitting characters in the input string, there will be an empty string in the result list.


How to concatenate the elements of an array into a string with a separator.



How to create a string using a printf style format.

case manipulation


pad on right, pad on left

string to number


All values are strings. The expr function will concatenate the arguments together and then evaluate the string as a numerical expression. If all the numbers are integers, the expression is computed using integer arithmetic. Otherwise floating point arithmetic is used. The variables can contain compound arithmetic expressions; the following script outputs 10:

set a "7+3"
puts [expr $a]

Regular Expressions

regex match

How to test whether a regular expression matches a string.



modifier description
-all causes regexp to return number of matches in string; causes regsub to replace all occurrences of match
-expanded ignore whitespace in patten
-indices modifies group capture: returns start and end indices of the substring instead of the substring itself
-inline return the total match and each of the group captures as a list. Normally the number of matches is returned
-line same as using -lineanchor and -linestop
-lineanchor causes ^ and $ to match the beginning and ending of lines (\A and \Z still match beginning and ending of string)
-linestop causes . to not matcch a newline
-nocase makes matching case insensitive

single substitution

How to replace the first occurrence of a pattern in a string.


To replace only the first occurrence of the pattern, omit the -all flag:

set s "do re mi mi mi"
regsub "mi" $s "ma"

global substitution

How to replace all occurrences of a pattern in a string.

Dates and Time

The Unix epoch is the number of seconds since January 1, 1970 UTC. In the case of Lua, the native date/time object is the Unix epoch, so no conversion is needed.



Tcl arrays are associative arrays. The dict type is new in Tcl 8.5. See the documentation for array and dict.

array literal

Array literal syntax.

array size

How to get the number of elements in an array.

array lookup

How to access a value in an array by index.


Does not support negative indices. To change the 2nd element in the list a to 8, use

lset a 1 8

lset will not increase the size of the list if the index is out of bounds. For more list manipulation commands see

array slice

How to slice a subarray from an array.

array iteration


How to test for membership in an array.


How to compute an intersection.





universal predicate

How to test whether a condition holds for all members of an array. Always true for an empty array.

existential predicate

How to test whether an item in an array exists for which a condition holds. Always false for an empty array.



The dict type was introduced in Tcl 8.5.

In earlier versions of Tcl associative arrays were used when a dictionary type was needed, and they remain an alternative in Tcl 8.5. Associative arrays are stored in variables as strings. The array command is used to treat the string as an associative array:

array set d [list "t" 1 "f" 0]
array size d
array set d [list "t" 2]
info exists d(t)
array unset d "t"
foreach {k v} [array get d] {
  puts k
  puts v

dictionary literal

dictionary size

dictionary lookup

dictionary iteration

out of bounds behavior



Tcl variables inside functions have local scope.

function definition

function invocation

missing argument value

Value of an argument variable if a function is invoked with fewer arguments than are declared.

extra arguments

If a function is invoked with more arguments than are declared, how the function can access them.

default argument value

How to declare a default value for an argument.

variable number of arguments

How to write a function which accepts a variable number of argument.

named parameters

How to write a function which uses named parameters.

return value

lambda declaration

How to define a lambda function.

lambda invocation

default scope

Execution Control



Tcl also has a switch:

switch $a 0 { puts "no" } 1 { puts "yes" } 2 { puts "maybe" } default { puts "error" }


The traditional style omits the parens around the conditionals.

|if n = 0
  msgbox % "zero hits"
} _
else if n = 1
  msgbox % "one hit"
  msgbox % n . " hits"



break exits a for or while loop immediately. continue goes to the next iteration of the loop. redo goes back to the beginning of the current iteration.



raise exception

How to raise an exception.

catch exception

How to handle an exception.

uncaught exception behavior

System behavior if an exception goes uncaught. Most interpreters print the exception message to stderr and exit with a nonzero status.


A tcl process can have multiple interpreters and multiple threads. However, each interpreter is limited to a single thread.

wait on thread


print to standard out


To prevent puts from appending a newline to the output, use

puts -nonewline "hello"

standard filehandles

read line

read file

write to file

append to file


File Formats


Processes and Environment

external command


When using tclsh as a shell or repl, external commands that do not have the same name as a built-in or user defined function can be executed directly without using the exec command.


command line args


How to make the computer talk.

environment variable

command path

The directory containing a command. Also indicates if the command is a built-in, alias, or function. Shows the definition of aliases and functions.


set signal handler

Libraries and Namespaces


What a library looks like.

import library

library path

namespace declaration

namespace separator




image and virtual machine | browser, workspace, and transcript | the smalltalk language

image and virtual machine

Executable Smalltalk consists of an image and a virtual machine. A Smalltalk image is equivalent to a program, except that it also contains the state of a Smalltalk process; a Smalltalk process can save itself as an image at any point in its execution. The Smalltalk image is usually portable, whereas the virtual machine is operating system specific.

To create a new Smalltalk executable, one copies an existing image, launches it, adds to or modifies the code while the process is running, and then persists the new code and the process state when the executable is done.

After a fresh installation of Pharo 3.0 on Mac OS X, one has a image named Pharo.image and a virtual machine named Pharo. One can launch the program at the command line by passing the image to the virtual machine as an argument:

$ ls -l Pharo.image                            
-rw-rw-r--  1 hpglot  staff  21802780 Dec 12 06:38 Pharo.image

$ ls -l pharo-vm/
-rwxr-xr-x  1 hpglot  staff  867488 May 15  2014 pharo-vm/

$ ./pharo-vm/ Pharo.image

It is worth noting that even after a fresh installation, the image is already much larger than the virtual machine. The standard library and any ofther classes distributed with the implementation are implemented in Smalltalk; they are in the image, not the virtual matchine.

browser, workspace, and transcript

the smalltalk language

All values which can be stored in variables are objects.

Every expression and statement is implemented as a message which is sent to an object.

Messages are classified as unary, binary, or keyword.

Examples of unary messages:

1 class.
false not.
Date today.

Examples of binary messages:

2 * 7.
true & true.
3 < 10.
'Hello, ', 'World!'.

Examples of keyword messages:

Precedence of messages.

Cascaded messages.

No functions, just methods and blocks.


Tcl Reference Manual
Tcl Standard Library

Tcl has some traits which will be familiar to anyone who has done Unix shell script programming:

(1) variables have a $ prefix except when values are assigned to them, in which case they are used unadorned:

set v 42
puts $v

(2) statements consist of a command and zero or more arguments. Commands which are not built-in functions or user defined functions are resolved by looking for an external command in the search path and running it.

(3) the values are always stored in variables as strings. Commands which expect numeric arguments perform an implicit conversion, so there isn't much practical consequence for the developer.

(4) in the absence of quoting ("", {}, []) the arguments of a command are parsed into words using whitespace; commas are not used to separate arguments.

(5) square brackets [] must be used to execute a function and use its return value as an argument. A combination of square brackets [] and the expr command must be used to evaluate an expression and use its value as an argument:

puts [format "%10s" "lorem"]
puts [expr 1 + 1]

Square brackets can be used to invoke an external command, but the value of the square brackets containing an external command is always the empty string: "".

Unlike shells, *, ?, ~ in variable names are not automatically expanded using the filesystem, but this behavior can be invoked with the glob command.




Mozilla Developer Network: JavaScript
JavaScript for Automation: Release Notes
Mozilla Developer Network: Document
Mozilla Document Network: Window
W3C: Document Object Model (DOM) Level 3 Core Specification
W3C: Document Object Model (DOM) Level 3 Events Specification

Most browsers include a debugger which can be launched with a keystroke:

browser mac windows linux
Chrome ⌥⌘J Cmd+Shift+J Cmd+Shift+J
Firefox ⌥⌘S Cmd+Shift+S Cmd+Shift+S
Safari ⌥⌘C

The debugger has a console pane, which is a JavaScript REPL.

> Math.log(10)

> alert("Hello, World!")

The console provides a global object named document which provides access to the DOM of the current page:

> document.getElementsByTagName("div").length

TODO: more ways to select node elements. Attributes of node elements.

There is also a global object named window which is useful.

JavaScript can be embedded in an HTML document using the <script> tag:

  var sum = 1 + 2;
  alert('the sum is ' + sum);

Alternatively the JavaScript can be in a separate file served by the same server:

<script src="foo.js"></script>

<script> tags can be placed in either the <head> or the <body> of an <html> document. They are executed as they are encountered by the browser. If there is a syntax error, then none of the JavaScript in the <script> tag is executed. If there is an unhandled exception, the browser stops execution of the <script> at that point. Neither syntax errors nor unhandled exceptions prevent the browser from executing JavaScript in subsequent <script> tags.

using JavaScript to modify the DOM

waiting for all JavaScript to load

javascript URL

DOM events

To guard against websites serving malicious JavaScript code, the JavaScript interpreters in browsers do not provide the ability to interact with the local operating system. In particular, client-side JavaScript cannot read or write to files. Client-side JavaScript cannot spawn other processes.

Client-side JavaScript can make HTTP requests. Client-side JavaScript can modify the DOM of an HTML page which was served from the same origin as the JavaScript. To be from the same origin, the URLs must have the same protocol, domain, and port. Client-side JavaScript can also get and set cookies which share the same origin. The origin policy for cookies is slightly relaxed, since the JavaScript can also get and set cookies for a parent domain, excluding public top level domains such as .com, .net, and .org.

issue tracker | content of this page licensed under creative commons attribution-sharealike 3.0