Interpreted Languages: Tcl, Lua, JavaScript, Io

a side-by-side reference sheet

arithmetic and logic | strings | regexes | dates and time | arrays | dictionaries | functions | execution control | files
directories | processes and environment | libraries and modules | objects | reflection | contact

tcl (1988) lua (1993) javascript (1995) io (2002)
version used
8.5 5.1 ECMAScript 5
node.js 0.4
show version $ tclsh
% info tclversion
$ lua -v $ node —version $ io
Io> System version
$ tclsh foo.tcl $ lua foo.lua $ node foo.js $ io
$ tclsh $ lua $ node $ io
statement separator newline or ;

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

newline not separator inside {}, (), or after binary operator.

newline can be put in "" or '' if preceded by backslash
; or newline

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

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

newline not separator inside () or ""
block delimiters
{} or "" do end {} ()
assignment set x 1 x = 1 x = 1; x := 1
# exception if x doesn't exist:
x = 1
parallel assignment
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
x, y, z = 1, 2, 3
-- 3 is discarded:
x, y = 1, 2, 3
-- z is set to nil:
x, y, z = 1, 2
none none
swap lassign "$x $y" y x x, y = y, x tmp = x;
x = y;
y = tmp;
tmp := x
x = y
y = tmp
declare local variable # set variable inside procedure
proc foo {args} {
  set x 1
local x = 1 var x = 1; x := 1
declare and access global variable # set variable outside procedure
set g 1

proc incr_global {} {
  global g
  incr g
-- assign without using local
g = 1

function incr_global()
  g = g + 1
// assign without using var
g = 1;

function incr_global () { g++; }
# no globals, but root object is
# named Lobby

g := 1

incr_global := block(
  Lobby g = Lobby g + 1
to-end-of-line comment # comment -- comment // comment // comment
# comment
comment out multiple lines if (0) {
  commented out
  can contain {} if balanced
  commented out
  also commented out
/* comment
another comment */
/* comment
another comment */
"" nil null nil
null test
v eq "" v == nil v === null v == nil
undefined variable access error nil undefined raises exception
undefined test expr ![info exists v] v == nil v === undefined not_defined := false
e := try(v)
e catch(Exception,
  not_defined = true
arithmetic and logic
tcl lua javascript io
true and false
1 0 true false true false true false
falsehoods 0 "false" "no" most strings cause error in boolean context; nonzero numbers are true false nil false null undefined "" 0 NaN false nil
logical operators && || ! and or not && || ! not is postfix:
and or not
conditional expression expr $x > 0 ? $x : -$x none x > 0 ? x : -x if(x > 0, x, -x)
are expressions statements no no yes yes
relational expression if {$x > 3} {}
# outside of conditionals use expr:
expr $x > 3
x > 3 x > 3 x > 3
comparison operators == != > < >= <=
# string comparison:
eq ne
== ~= < > >= <= === !== < > >= <=
perform type coercion:
== !=
== != < > >= <=
convert from string use expr to interpret as numbers:
set x "12"
expr 7 + $x
set y ".037"
expr 73.9 + $y
7 + "12"
73.9 + ".037"
7 + parseInt("12", 10)
73.9 + parseFloat(".037")
7 + ( "12" asNumber )
73.9 + ( ".037" asNumber )
convert to string
all values are strings "value: " .. 8 "value: " + 8 "value: " .. (8 asString)
arithmetic expression expr 1 + 3
# expr not needed in conditionals:
if {1 + 3} {}
1 + 3 1 + 3 1 + 3
arithmetic operators + - * none / % **
also: pow(base, exp)
+ - * / none % ^
also has math.pow
+ - * / none % Math.pow(base, exp) + - * / none % **
integer division
$x / $y math.floor(x / y) Math.floor(x / y) (x / y) floor
float division
$x * 1.0 / $y x / y x / y x / y
arithmetic functions sqrt 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
math.sqrt math.exp math.log math.sin math.cos math.tan math.asin math.acos math.atan math.atan2 Math.sqrt Math.exp Math.log Math.sin Math.cos Math.tan Math.asin Math.acos Math.atan Math.atan2 sqrt exp log sin cos tan asin acos atan atan2
arithmetic truncation expr int(3.1)
expr round(3.1)
expr ceil(3.1)
expr floor(3.1)
expr abs(-3)
3.1 round
3.1 ceil
3.1 floor
(-3) abs
min and max expr min(1,2,3)
expr max(1,2,3)
Math.min.apply(Math, [1,2,3])
Math.max.apply(Math, [1,2,3])
list(1,2,3) min
list(1,2,3) max
division by zero
error inf Infinity inf
integer overflow
arbitrary length integers introduced in 8.5 all numbers are floats all numbers are floats conversion to float
float overflow
error inf Infinity inf
sqrt -2
error nan NaN nan
random integer, uniform float, normal float int(rand() * 100)
math.random(100) - 1
Math.floor(Math.random() * 100)
Random value(100) floor
Random value
Random gaussian
bit operators
<< >> & | ^ ~ none << >> & | ^ ~ << >> & | ^ bitwiseComplement
tcl lua javascript io
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"'
"don't say \"no\""
newline in literal
yes yes, if preceded by backslash yes no
escapes in double quotes:
\a \b \f \n \r \t \v \\ \" \oooo \uhhhh \xhh
single and double quotes:
\a \b \f \n \r \t \v \" \' \\ \ddd
single and double quotes:
\b \f \n \r \t \v \uhhhh \xhh \" \' \\
\a \b \f \n \r \t \v \" \\
variable interpolation set count 3
set item "ball"
"$count ${item}s"
none none count := 3
item := "ball"
"#{count} #{item}s" interpolate
string concatenation set s1 "Hello, "
set s2 "World!"
set s $s1$s2
s = "Hello, " .. "World!" s = "Hello, " + "World!"; s := "Hello, " .. "World!"
split "do re mi" none "do re mi".split(" ") "do re mi" split(" ")
join [list "do" "re" "mi"] " " table.concat({"do","re","mi"}, " ") ["do", "re", "mi"].join(" ") list("do", "re", "mi") join(" ")
sprintf set fmt "lorem %s %d %f"
format $fmt "ipsum" 13 3.7
string.format("lorem %s %d %f",
  "ipsum", 13, 3.7)
none none
case manipulation string toupper "lorem"
string tolower "LOREM"
"lorem" asUppercase
"LOREM" asLowercase
"lorem" asCapitalized
strip string trim " lorem "
string trimleft " lorem"
string trimright "lorem "
none " lorem ".trim()
# some browsers:
" lorem".trimLeft()
"lorem ".trimRight()
" lorem " asMutable strip
" lorem" asMutable lstrip
"lorem " asMutable rstrip
pad on right, pad on left, center format "%10s" "lorem"
format "%-10s" "lorem"
none none "foo" alignRight(10, " ")
"lorem" alignLeft(10, " ")
"lorem" alignCenter(10, " ")
string length "lorem" string.len("lorem") "lorem".length "lorem" size
index of substring
string first "ipsum" "lorem ipsum" string.find("lorem ipsum", "ipsum") "lorem ipsum".indexOf("ipsum") "lorem ipsum" findSeq("ipsum")
extract substring
string range "lorem ipsum" 6 10 string.sub("lorem ipsum", 7, 11) "lorem ipsum".substr(6, 5)
"lorem ipsum".substring(6, 11)
"foo bar" exSlice(4,7)
chr and ord format %c 65
scan A %c ascii_value
65 asCharacter
"A" at(0)
tcl lua javascript io
character class abbreviations and anchors char class abbrevs:
. \d \D \s \S \w \W

anchors: ^ $ \A \m \M \y \Y \Z
char class abbrevs:
. %a %c %d %l %p %s %u %w %x %z

anchors: ^ $
char class abbrevs:
. \d \D \s \S \w \W

anchors: ^ $ \b \B
match test
if [regexp -- {1999} $s] {
  puts "party!"
if string.match(s, "1999") then
if (s.match(/1999/)) {
case insensitive match test regexp -nocase -- {lorem} "Lorem" none "Lorem".match(/lorem/i)
modifiers -all -expanded -indices -inline
-line -lineanchor -linestop -nocase
none g i m
substitution set s "do re mi mi mi"
regsub -all -- "mi" $s "ma"
s = "do re mi mi mi"
s = string.gsub(s, "mi", "ma")
s = "do re mi mi mi";
s.replace(/mi/g, "ma");
group capture set s "2009-06-03"
set rx {^(\d{4})-(\d{2})-(\d{2})$}
regexp -- $rx $s - yr mo dy
s = "2010-06-03"
rx = "(%d+)-(%d+)-(%d+)"
yr, mo, dy = string.match(s, rx)
rx = /^(\d{4})-(\d{2})-(\d{2})$/;
m = rx.exec('2009-06-03');
yr = m[1];
mo = m[2];
dy = m[3];
dates and time
tcl lua javascript io
current date/time set t [clock seconds] t = os.time() var t = new Date(); t := Date now
to unix epoch, from unix epoch t
set t2 1315716177
t2 = 1315716177
Math.round(t.getTime() / 1000)
var epoch = 1315716177;
var t2 = new Date(epoch * 1000);
t asNumber
epoch := 1315716177
t2 := Date clone fromNumber(epoch)
strftime set fmt "%Y-%m-%d %H:%M:%S"
clock format $t -format $fmt"%Y-%m-%d %H:%M:%S", t) none t asString("%Y-%m-%d %H:%M:%S")
strptime none none none s := "2011-05-03 10:00:00"
fmt := "%Y-%m-%d %H:%M:%S"
t := Date fromString(s, fmt)
parse date w/o format set t [clock scan "July 7, 1999"] none var t = new Date("July 7, 1999"); none
get date parts clock format $t -format "%Y"
clock format $t -format "%m"
clock format $t -format "%d"
none t.getFullYear()
t.getMonth() + 1
t.getDate() # getDay() is day of week
t year
t month
t day
get time parts clock format $t -format "%H"
clock format $t -format "%M"
clock format $t -format "%S"
none t.getHours()
t hour
t minute
t second floor
build date/time from parts none none 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);
t := Date now
t setYear(1999)
t setMonth(9)
t setDay(10)
t setHour(23)
t setMinute(30)
t setSecond(0)
after 500 none none System sleep(0.5)
tcl lua javascript io
set nums [list 1 2 3 4]
set nums {1 2 3 4}
nums = { 1, 2, 3, 4 } nums = [1,2,3,4] nums := list(1,2,3,4)
llength $nums # nums nums.length nums size
lindex $nums 0 nums[1] nums[0] nums at(0)
lrange $nums 1 2 none nums.slice(1,3) nums slice(1,3)
set a [concat {1 2 3} {4 5 6}] none a = [1,2,3].concat([4,5,6]); list(1,2,3) appendSeq(list(4,5,6))
manipulate back of array set a {6 7 8}
lappend a 9
set i [lindex $a end]
set a [lreplace $a end end]
a = {6,7,8}
table.insert(a, 9)
i = table.remove(a)
a = [6,7,8];
i = a.pop();
a := list(6,7,8)
a push(9)
i := a pop
manipulate front of array set a {6 7 8}
set a [concat {5} $a]
set a [lassign $a i]
a = {6,7,8}
table.insert(a, 1, 5)
i = table.remove(a, 1)
a = [6,7,8];
i = a.shift();
a := list(6,7,8)
a prepend(5)
i := a removeFirst
iteration foreach i $nums { puts $i } for k,v in ipairs(nums) do
var len = nums.length;
for (var i=0; i<len; i++ ) {
nums foreach(v, v println)
set a {3 1 4 2}
set a [lsort $a]
a = {3,1,4,2}
var a = [3,1,4,2];
a := list(3,1,4,2)
a := a sort
set a {1 2 3}
set a [lreverse $a]
none var a = [1,2,3];
a := list(1, 2, 3)
a := a reverse
member, not a member expr {7 in $nums}
expr {7 ni $nums}
none none nums contains(7)
nums contains(7) not
package require struct::set

::struct::set intersect {1 2} {2 3}
none none list(1,2) intersect(list(2,3))
package require struct::set

::struct::set union {1 2} {2 3 4}
none none list(1,2) union(list(2,3,4))
set difference
package require struct::set

::struct::set difference {1 2 3} {2}
none none list(1,2,3) difference(list(2))
package require struct::list

proc sqr {x} {return [expr $x*$x]}
::struct::list map {1 2 3} sqr
none {return x*x}) nums map(x, x*x)
package require struct::list

proc gt1 {x} {return [expr $x>1]}
::struct::list filter {1 2 3} gt1
none nums.filter(function(x) {return x>1}) nums select(x, x>1)
package require struct::list

::struct::list fold {1 2 3} 0
none nums.reduce(function(m,o) {
  return m+o;
}, 0)
nums reduce(m, o, m+o, 0)
tcl lua javascript io
literal set d [dict create t 1 f 0] d = { t=1, f=0 } 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
d := Map with("t", 1, "f", 0)
dict size $d size = 0
for k, v in pairs(d) do
  size = size + 1
var size = 0;
for (var k in d) {
  if (d.hasOwnProperty(k)) size++;
d size
lookup dict get $d t d.t
d at("t")
update dict set d t 2 d["t"] = 2
d.t = 2
d["t"] = 2;
d.t = 2;
d.atPut("t", 2)
out of bounds behavior error returns nil returns undefined returns nil
is key present
dict exists $d t d["t"] ~= nil d.hasOwnProperty("t"); d hasKey("t")
delete dict unset d t d.t = nil
d["t"] = nil
delete d["t"];
delete d.t;
d removeAt("t")
iteration foreach {k v} $d {
for k,v in pairs(d) do
  use k or v
for (var k in d) {
  use k or d[k]
d foreach(k, v,
  k println
  v println
tcl lua javascript io
function declaration proc add { x y } {
  expr $x + $y
function add(x, y)
  return x + y
function add(x, y) {
  return x+y;
add := block(x, y,
function invocation
add 1 2 add(1, 2) add(1, 2) add call(1, 2)
missing argument value error nil undefined nil
extra arguments
error ignored available in arguments ignored
default value
proc log {x {base 10 }} { body } none none none
variable number of arguments last arg contains list of remaining values declare function with ellipsis:
function foo(…)
and arguments will be in array arg
args in arguments[0], arguments[1], … with number of args in arguments.length arguments in
call message arguments
return value return arg or empty string return arg or nil return arg or undefined. If invoked with new and return value not an object, returns this return arg or last expression evaluated
multiple return values none function roots(x)
  r = math.sqrt(x)
  return r, -r
r1,r2 = roots(4)
none none
lambda declaration set sqr {{x} {return [expr $x*$x]}} sqr = function(x) return x*x end sqr = function(x) { return x*x; } all functions are lambdas:
sqr := block(x, x*x)
lambda invocation
apply $sqr 2 sqr(2) sqr(2) sqr call(2)
default scope
local global unless declared with local global unless declared with var local
nested function visibility not visible outside containing function visible outside containing function not visible outside containing function visible if stored in visible variable
execution control
tcl lua javascript io
if if { 0 == $n } {
  puts "no hits"
} elseif { 1 == $n } {
  puts "1 hit"
} else {
  puts "$n hits"
if n == 0 then
  print("no hits")
elseif n == 1 then
  print("one hit")
  print(n .. " hits")
if (0 == n) {
  alert("no hits");
} else if (1 == n) {
  alert("1 hit");
} else {
  alert(n + " hits");
if (n == 0,
  "no hits",
  if (n == 1,
    "1 hit",
    "#{n} hits" interpolate
while while { $i < 100 } {
  incr i
while i < 100 do
  i = i + 1
while ( i < 100 ) {
  i += 1;
while (i < 100,
  i = i + 1
break and continue break continue break none break continue break continue
for for {set i 0} {$i < 10} {incr i} {
  puts $i
for i = 0, 9 do
for (var i=0; i<10; i++) {
for (i, 0, 9,
  i println
raise exception error "bad arg" error "bad arg" throw "bad arg"; Exception raise("bad arg")
catch exception catch risky retval
if { retval != 0 } {
    puts "risky failed"
if not pcall(risky) then
  print "risky failed"
try {
} catch (e) {
  alert("risky failed");
msg := "risky failed\n"
e := try(risky call)
e catch(Exception, write(msg))
finally/ensure none none acquire_resource();
try {
} finally {
uncaught exception behavior stderr and exit stderr and exit error to console; script terminates. Other scripts in page will execute stderr and exit
generator to be added to Tcl 8.6 crt = coroutine.create(
  function (n)
    while (true) do
      coroutine.yield(n % 2)
      n = n + 1

status, retval =
  coroutine.resume(crt, 1)

if status then
  print("parity: " .. retval)
  print("couldn't resume crt")

_, retval = coroutine.resume(crt)
print("parity: " .. retval)
none none; although Io has coroutines, yield and resume do not pass values. Also, yield returns control to a scheduler, not the caller.
tcl lua node.js io
print to standard output puts "Hello, World!" print "Hello, World!" var sys = require('sys');

sys.puts("Hello, World!");
"Hello, World!" println
read from standard input gets stdin line line = io.stdin:read() line := File standardInput readLine
standard file handles stdin
File standardInput
File standardOutput
File standardError
open file set f [open "/tmp/foo"] f ="/tmp/foo") var fs = require('fs');

f = fs.openSync("/tmp/foo", "r");
f := File with("/tmp/foo")
f openForReading
open file for writing set f [open "/tmp/foo" "w"] f ="/tmp/foo", "w") var fs = require('fs');

f = fs.openSync("/tmp/foo", "w");
f := File with("/tmp/foo")
f remove
f openForUpdating
close file
close $f f:close() fs.closeSync(f); f close
read line
gets $f f:read() f readLine
iterate over a file by line while { [gets $f s] >= 0 } {
  use s
for s in f:lines() do
  use s
var fs = require('fs');

var file = fs.readFileSync("/etc/hosts").toString();
file.split("\n").forEach(function (s) {
  use s
f foreachLine(s,
  use s
chomp string trimright $line "\r\n" none, read() and lines() remove trailing newlines none, readLine and readLines remove trailing newlines
read file
read $f f:read("*a") var fs = require('fs');

fs.readFileSync("/tmp/foo", "utf8");
f contents
write to file
puts -nonewline $f "lorem ipsum" f:write("lorem ipsum") fs.writeSync(f, "lorem ipsum"); f write("lorem ipsum")
flush file handle flush $f f:flush() none f flush
file test, regular file test file exists "/etc/hosts"
file isfile "/etc/hosts"
none var path = require('path');

file := "/etc/hosts"
File exists(file)
File with(file) isRegularFile
copy file, remove file, rename file file copy "/tmp/foo" "/tmp/bar"
file delete "/tmp/foo"
file rename "/tmp/bar" "/tmp/foo"
none var fs = require('fs');

fs.rename("/tmp/bar", "/tmp/foo");
foo := "/tmp/foo"
bar := "/tmp/bar"
File with(foo) copyToPath(bar)
File with(foo) remove
File with(bar) moveTo(foo)
set file permissions set s "/tmp/foo"
file attributes $s -permissions 0755
none var fs = require('fs');

fs.chmod("/tmp/foo", 0755);
temporary file set tmp [::fileutil::tempfile foo]
set f [open $tmp "w"]
puts $f "lorem ipsum"
close $f
puts "tmp file: $tmp"
f = io.tmpfile()
f:write("lorem ipsum\n")
tcl lua node.js io
build pathname file join "/etc" "hosts" var path = require('path');

path.join("/etc", "hosts");
dirname and basename file dirname "/etc/hosts"
file tail "/etc/hosts"
var path = require('path');

iterate over directory by file var fs = require('fs');
var sys = require('sys');

var a = fs.readdirSync("/etc");
for (var i=0; i<a.length; i++) {
dir := Directory with("/etc")
dir items foreach(file,
  file name println
make directory file mkdir "/tmp/foo/bar" var fs = require('fs');

fs.mkdirSync("/tmp/foo", 0755);
fs.mkdirSync("/tmp/foo/bar", 0755);
path := "/tmp/foo/bar"
Directory with(path) createIfAbsent
remove empty directory file delete "/tmp/foodir" var fs = require('fs');

Directory with("/tmp/foodir") remove
remove directory and contents file delete -force "/tmp/foodir"
directory test
file isdirectory "/tmp" Directory with("/tmp") exists
processes and environment
tcl lua node.js io
command line args [lindex $argv 0]
[lindex $argv 1]
# arg
System args size
System args at(0)
System args at(1)
environment variable $env(HOME) os.getenv("HOME") System getEnvironmentVariable("HOME")
exit 0 os.exit(0) process.exit(0) System exit(0)
set signal handller
none none none
external command exec ls os.execute("ls") var exec =
var child = exec('ls');
System runCommand("ls")
backticks set f [ open |ls ]
read f
f = io.popen("ls")
s = f:read("*a")
var exec =
var f = function(err, fout, ferr) {
  output in fout
var child = exec('ls', f);
(System runCommand("ls")) stdout
libraries and modules
tcl lua javascript io
library $ cat foo.tcl
proc add {x y} {expr $x + $y}
$ cat foo.lua
function add(x, y) return x+y end
$ cat foo.js
function add(x,y) {
  return x+y;
$ cat
Foo := Object clone
Foo add := method(x, y, x + y)
import library source foo.tcl
add 3 7
require 'foo'
<script src="foo.js"/>

imported when first referenced:
Foo add(3,7)
library path none package.path node.js, not available in repl:
Importer FileImporter directories
library path environment variable TCLLIBPATH LUA_PATH none none
module declaration namespace module use an Object:
foo := Object clone
module separator :: . .
list installed packaged, install a package $ npm ls
$ npm install tmp
tcl lua javascript io
create blank object o = {} var o = new Object(); or
var o = {};
o := Object clone
set attribute
o.score = 21 o.score = 21; o score := 21
get attribute if o.score == 21 then
if (o.score == 21) {
if (o score == 21,
  "Blackjack!" println
define method function o.doubleScore(self)
  return 2 * self.score
o.doubleScore = function() {
  return this.score * 2;
o doubleScore := method(2 * score)
invoke method print("Answer: " .. o:doubleScore()) alert("Answer: " + o.doubleScore()); ans := o doubleScore asString
"Answer: " .. ans println
clone object
var o2 = Object.create(o); o2 := o clone
object literal o = {
    return 2*self.score
var o = {
  score: 21,
  doubleScore: function() {
    return this.score * 2;
tcl lua javascript io
inspect type
type(o) typeof o
has method?
typeof( == 'function' o getSlot("foo") isActivatable
message passing o["foo"](1,1) o getSlot("foo")(1+1)
assert(loadstring("x = 1+1"))() x = eval("1 + 1"); x := doString("1+1")
inspect methods o slotNames select(v,
  o getSlot(v) isActivatable)
inspect attributes o slotNames select(v,
  o getSlot(v) isActivatable not)
__________________________________________ __________________________________________ __________________________________________ __________________________________________

General Footnotes

version used

The version used for verifying the examples in this cheat sheet.


In the JavaScript standard the language is called ECMAScript. Four versions of the standard have been adopted:

ecmacript version date
1 June 1997
2 June 1998
3 December 1999
5 December 2009

Here is a summary of ECMAScript 5 compliance for recent browsers:

browser compliance
Chrome 7-12 all but "use strict"
Chrome 13+ all
Firefox 4+ all
IE 9-10 all but "use strict"
Safari 5.1 all but Function.prototype.bind

show version

How to get the version.


This html will show the JavaScript version of the browser that renders it:

<script type="text/javascript">var javascript_version = 1.0;</script>
<script language="Javascript1.1">var javascript_version = 1.1;</script>
<script language="Javascript1.2">var javascript_version = 1.2;</script>
<script language="Javascript1.3">var javascript_version = 1.3;</script>
<script language="Javascript1.4">var javascript_version = 1.4;</script>
<script language="Javascript1.5">var javascript_version = 1.5;</script>
<script language="Javascript1.6">var javascript_version = 1.6;</script>
<script language="Javascript1.7">var javascript_version = 1.7;</script>
<script language="Javascript1.8">var javascript_version = 1.8;</script>
<script type="text/javascript1.9">var javascript_version = 1.9;</script>
<script type="text/javascript">
document.write('<p>Javascript version: ' + javascript_version + '<\/p>');


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


On Unix, scripts are executing by passing the file containing the script to the interpreter as an argument:

bash ~/

If the executable bit is set, the file can be run directly:


To determine the name of the interpreter that will process the script, Unix will look for the presence of a shebang (#!) at the start of the file. If the pathname to a command follows the shebang, it will be used to interpret the script. If no shebang is present, the script will be interpreted with sh, which is bash on modern Unix systems.

Arguments that follow the command will be passed to interpreter as command line arguments.

If it is undesirable to specify the pathname of the interpreter, the env command can be used to search the PATH directories:

#!/usr/bin/env lua


To use a browser to execute JavaScript code, put the code inside a <script> tag in an HTML page and open the page with the browser.


The customary name of the repl.


You can use the JavaScript console as a repl. Here are the keystrokes to launch the console:

chrome firefox safari
mac win mac win mac
⌥⌘J Ctrl+Shift+J Fn F12 Ctrl+Shift+K ⌥⌘C

statement separator

How the parser determines the end of a statement.

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}"


The function and if keywords open blocks which are terminated by end keywords. The repeat keyword opens a block which is terminated by until.


How to assign a value to a variable.

parallel assignment

Whether parallel assignment is supported, and if so how to do it.


How to swap the values in two variables.

declare local variable

How to declare a local variable.

declare and access global variable

How to declare and access a global variable.

to-end-of-line comment

How to make the remainder of the line a comment.

comment out multiple lines

How to comment out multiple lines.


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


The method described is the syntax for a multiline string literal.


The null literal.

null test

How to test if a value is null.


Tcl has has no null value.


null == undefined is true. The triple equality operator === is thus necessary to test if a variable is null.

undefined variable access

What happens when the value in an undefined variable is accessed.

undefined test

How to determine if a variable is undefined.


undefined == null is true. The triple equality operator === is necessary to test if a variable is undefined.


To determine if a variable is undefined, compare it with nil. Assigning nil to a variable releases the variable.

Arithmetic and Logic Footnotes

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

How to write a conditional expression.


notes on Lua and the ternary operator

are expressions statements

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


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.

relational expressions

How to write a 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]

comparison operators

The available comparison 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 comparison 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"

convert from string

How to convert a string to a 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]


Arithmetic operators will attempt to convert strings to numbers; if the string contains non-numeric data an error results. Note that relational operators do not perform conversion. Thus the following expression is false:

 0 == '0'


Numbers can be explicitly converted to strings with toString(). Numeric literals must be put inside parens to invoke the toString() method.

x = 7

convert to string

How to convert a number to a string.


print and the .. operator will convert all types to strings.


The plus operator + performs concatenation on strings. If either operand is a string, then the other operand will be converted to a string.

100 == "100"

Numbers can be explicitly converted to strings with toString(). Numeric literals must be put inside parens to invoke the toString() method.

x = 7

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 binary 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.


All Lua numbers are floating point.

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

How to truncate a float towards zero; how to round to the nearest integer; how truncate towards positive infinity; how to truncate towards negative infinity; how to take the absolute value.

min and max

How to find the min and max value in disparate variables or an array of values.

division by zero

The result of division by zero.


There is no constant for inf, so if the parser encounters it it is treated as a variable with a value of nil unless a value has been assigned to it.

To assign inf to a value, use the expression 1 / 0. inf has type number.

integer overflow

What happens when an operation yields an integer larger than the largest representable value.

float overflow

What happens when an operation yields a float larger than the largest representable value.

sqrt -2

The result of taking the square root of -2.


There is no constant for nan; if the parser encounters it it is treated as a variable with a value of nil unless a value has been assigned to it.

To assign nan to a value, use the expression math.sqrt(-1)}. {{nan has type number.

random integer, uniform float, normal 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

bit operators

The available bit operators.

String Footnotes

string literal

The syntax for a string literal.

newline in literal

Are newlines permitted in a string literal?


Backslash escape sequences that can be used in a string literal.

variable interpolation

The syntax for interpolating variables into a string literal.

string concatenation

The string concatenation operator.



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 split a string in Lua


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, center

How to pad a string to a given length on the right; how to pad on the left; how to center a string inside a larger string of a given length.


How to get the number of characters in a string.

index substring

How to get the index of the leftmost occurrence of a substring.

extract substring

How to extract a substring.

chr and ord

converting characters to ASCII codes and back

Regular Expression Footnotes

character class abbreviations and anchors

The supported character class abbreviations and anchors

abbrev description
. any character; doesn't match newline when -linestop in effect
^ beginning of string; beginning of line when -lineanchor in effect
$ end of string; end of line when -lineanchor in effect
\A beginning of string
%a letter
\b, \y word boundary
\B, \Y not a word boundary
%c control character
\d, %d digit [0-9]
\D not a digit [^0-9]
%l lowercase letter
\m beginning of a word
\M end of a word
%p punctuation character
\s white space
\S not white space
%u uppercase letter
\w, %w alphanumeric character. \w also matches underscore
\W not a word character
\Z end of string
%z the null character (ASCII zero)

match test

How to test whether a regular expression matches a string.

case insensitive match test

How to test whether a regular expression matches a string, ignoring case.


Available flags for modifying regular expression behavior.


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


modifier description
g when used with match, causes all occurrences of pattern in string to be return in an array; when used with replace causes all occurrences to be replaced
i makes matching case insensitive
m causes ^ and $ to match beginning and ending of lines instead of the whole string


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


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

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


To specify the maximum number of pattern occurrences to be replaced, provide a fourth argument:

s = "do re mi mi mi"
s = string.gsub(s, "mi", "ma", 1)


If the g modifier is not used, only the first occurrence of the pattern will be replaced.

s = "do re mi mi mi";
s.replace(/mi/, "ma");

group capture

Date and Time Footnotes

current date/time

How to get the current time.

to unix epoch, from unix epoch

How to convert a date/time object to the Unix epoch; how to convert a date/time object from the Unix epoch.

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


How to use a strftime style format string to convert a date/time object to a string representation.

strftime is from the C standard library. The Unix date command uses the same style of format.


How to parse a string into a date/time object using a strftime style format string. strptime is from the C standard library.

parse date w/o format

How to parse a string into a date/time object without using a format string.

get date parts

How to get the year as a four digit integer; how to get the month as an integer from 1 to 12; how to get the day of the month as an integer from 1 to 31.

get time parts

How to get the hour as an integer from 0 to 23; how to get the minute as an integer from 0 to 59; how to get the second as an integer from 0 to 59.

build date/time from parts

How to assemble a date/time object from the 4 digit year, month (1-12), day (1-31), hour (0-23), minute (0-59), and second (0-59).


How to sleep for half a second.

Container Footnotes

The names given by the languages for their basic container types:

tcl lua javascript io
array list table Array List
dictionary array, dict table Object Map


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

Array Footnotes


Array literal syntax.


How to get the number of elements in an array.


# d is not necessarily the number of values stored in a table. If # d is n, then the values stored at 1 through n are not nil and the value of n+1 is nil. There may be non-nil values at higher indices, however. Furthermore, since tables can act as both arrays and dictionaries, there may be values stored at non-integer or non-numeric indices.

# d returns the number of times that a for loop used with ipairs will execute.


How to access a value in an array by index.


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

lset nums 1 8

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


Lua arrays are indexed from one.


How to slice a subarray from an array.


How to concatenate two arrays.

manipulate back of array

How to push or pop elements from the back an array. The return value of the pop command is the value of the item which is removed.

With these commands an array can be used as a stack.

manipulate front of array

How to shift or unshift elements to the front of an array. The return value of the shift command is the value of the item which is removed.

With these commands an array can be used as a stack. When combined with the commands from the previous section the array can be used as a queue.


How to iterate through the elements of an array.


How to sort an array.


sort does not modify the receiver. sortInPlace modifies the receiver:

a := list(3,1,4,2)
a sortInPlace


How to reverse the order of the elements in an array.


reverse does not modify the receiver. reverseInPlace modifies the receiver:

a := list(1,2,3)
a reverseInPlace

member, non a member

How to test whether a value is an element of an array; how to test whether a value is not an element of an array.


How to compute an intersection.


How to compute the union of two arrays.

set difference

How to find the elements of an array that are not in another array.


How to apply a function to the elements of an array.

None of the examples modify the source array.


map implementation


How to select the elements of an array for which a predicate is true.

None of the examples modify the source array.


filter implementation


How to reduce an array using a binary operation and an initial value.

None of the examples modify the source array.


reduce implementation

Dictionary Footnotes


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


The syntax for a dictionary literal.


How to get the number of entries in a dictionary.


How to look up the value associated with a key.


JavaScript objects support both o.k and o['k'] style attribute access, but in the former case k must be a valid JavaScript identifier.


How to set or update the value associated with a key.

out of bounds behavior

What happens when a lookup is performed for a key the dictionary does not have.

is key present

How to find out whether a value is associated with a key.


How to remove a key/value pair from a dictionary.


How to iterate through all the key/value pairs of a dictionary.

Function Footnotes

Python has both functions and methods. Ruby only has methods: functions defined at the top level are in fact methods on a special main object. Perl subroutines can be invoked with a function syntax or a method syntax.

function declaration

How to declare a function.

function invocation

How to invoke a function.

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 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.

return value

How the return value of a function is determined.

multiple return values


If a function returns multiple values, the first value can be selected by placing the invocation inside parens:

function roots(x)
  return math.sqrt(x), -math.sqrt(x)

lambda declaration

How to define a lambda function.

lambda invocation

How to invoke a lambda function.

default scope

What scope do variables declared inside a function have by default.


Tcl variables inside functions have local scope.

nested function visibility

Whether nested functions are visible outside of the function in which they are defined.

Execution Control Footnotes


The if statement.


Tcl also has a switch:

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


How to create a while loop.

break and continue

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


How to create a C-style for loop.


Provide a third argument to set the step size to something other than the default of one:

for i = 0, 90, 10 do

raise exception

How to raise an exception.

catch exception

How to handle an exception.


Clauses that are guaranteed to be executed even if an exception is thrown or caught.

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.


How to create and use a generator.

File Footnotes

print to standard output


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

puts -nonewline "hello"

read from standard input

How to read a line from standard input.

standard file handles

Constands for the standard file handles.

open file

How to create a file handle for reading.

open file for writing

How to create a file handle for writing.


If remove is not invoked, the file will not be truncated before writing. Part of the old contents will still be visible if they exceed the length of the new contents.

close file

How to close a file handle.

read line

iterate over a file by line


Remove a newline, carriage return, or carriage return newline pair from the end of a line if there is one.

read file

write to file

flush file handle

file test, regular file test

copy file, remove file, rename file

set file permissions

temporary file

Directory Footnotes

Processes and Environment Footnotes


Browser-embedded JavaScript cannot interact with the browser's operating system. All examples in this section assume the JavaScript code is being executed by node.js.

command line arguments

How to access the command line arguments.

environment variable

How to access an environment variable.


How to terminate the process and set the status code.

set signal handler

How to register a signal handler.

external command

How to execute an 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.


How to execute an external command and read the standard output into a variable.

Library and Module Footnotes


What a library looks like.

import library

How to import a library.

library path

How to access the library path.

library path environment variable

The environment variable which governs the library path.

module declaration

How to declare a module.

module separator

The separator used in module names.

list installed packages, install a package

How to list the installed 3rd party packages; how to install a 3rd party package.

Object Footnotes

create blank object

How to create a blank object without any attributes or methods, or at least without any but the default attributes and methods.

set attribute

How to set an object attribute.

get attribute

How to get an object attribute.

define method

How to define a method for an object.

invoke method

How to invoke an object method.


How to make a copy of an object. Changes to the copy will not affect the original.

object literal

The syntax for an object literal.

Reflection Footnotes


has method?

message passing





Tcl Tutorial
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 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.


Lua 5.1 Reference Manual
Lua Tutorial Directory

The Lua REPL is actually a REL; that is, it doesn't print the value of statement. Furthermore, expressions are not in general statements. print() can be used to display numbers and strings. There is no built in pretty printer for tables.

In Lua all numbers are stored as double precision floats. The table type can be used as both an array and a dictionary.


JavaScript Guide
Core Global Objects
Eloquent JavaScript
ECMA 262 5th Edition (pdf) 2009
DOM 3 Core
DOM 3 Events


Io Programming Guide
Io Reference


Tcl History

Tcl Chronology:

6.0 (1991)

7.0 (1993)

Tcl and the Tk Toolkit (1994)

Tk 4.0 (1995)

8.0 (1997)

  • bytecode compiler (previously strings)
  • namespaces

8.1 (1999)

  • threads (at most one tcl interpreter per thread, but multiple interpreters per process)
  • unicode

8.2 (1999)

8.3 (2000)

8.4 (2002)

8.5 (Dec 23, 2007)

  • bignum
  • dict
  • anonymous procedures

JavaScript History

JavaScript was released as part of Netscape Navigator 2.0 in 1995. Internet Explorer 3.0 added a mostly compatible language called JScript in 1996. ECMA published an open standard for JavaScript in 1997; the official name for the language described in the standard is ECMAScript. Macromedia added scripting to Flash 4 (1999). Flash 5 (2000) used a revised scripting language called ActionScript which was based on ECMAScript.

JavaScript and Java

Navigator 2.0 could also run Java applets by means of its plug-in architecture and the HTML tag embed. The embed tag was deprecated by the W3C because the attributes are plug-in specific. Java applets can also be run via the HTML tag applet, but this tag is deprecated because it is Java specific. The object tag is the recommended way to run Java in the browser.

JavaScript was called Mocha when the language was under development. According to Brendan Eich, it was an explicit design goal for the language to have a Java-like syntax.


DOM 2 Core

JavaScript was initially used for form validation and image rollovers. The JavaScript code was launched by registering it using HTML tag attributes such as onSubmit and onMouseOver. Early versions of JavaScript did not have much ability to change the HTML document being rendered by the browser. The W3C devised a standard for an object-oriented library by which JavaScript could inspect and manipulate any part of the document. The standard was released in 1998 as the Document Object Model (DOM) 1. What ability the browsers had to interact with the document before the standard was retroactively called DOM 0 or Legacy DOM.

DOM 2 (2000) added the document.getElementById method, which the frameworks would abbreviate with $, as well as events and CSS support. DOM 3 (2004) added keyboard events and XPath support.

Ajax and JSON

RFC 4627: The application/json Media Type for JavaScript Object Notation 2006

The iframe tag, which Internet Explorer added as a possible child tag of a frame in 1996, gave JavaScript the ability to replace a portion of the HTML document with body of an HTTP request. Internet Explorer 5 (1999) added the XMLHTTP Active X control for fetching data via HTTP. The other browsers added an object called XMLHttpRequest, starting with Mozilla in 2002, with the same functionality. The technique of loading data in an HTTP request separate from the HTTP request initially used to load the document was christened Asynchronous JavaScript and XML, or Ajax, in 2005. Ajax improves the performance of JavaScript applications, making them competitive in many cases with desktop apps.

The payload of an Ajax request does not have to be XML. JSON, which is a subset of JavaScript containing the array literal and object literal notation, is a convenient alternative data format.


Comparison of JavaScript Frameworks

JavaScript frameworks such as prototype.js (2005) and jquery.js (2006) become available. These libraries add features, hide incompatibilities in browser behavior, and augment the DOM with convenience methods.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License