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 | |
interpreter |
$ tclsh foo.tcl | > autohotkey foo.ahk | ||
repl |
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 nestable: function |
|||
are expressions statements |
yes | no | no | |
end-of-line comment |
// comment | no | # comment | ; comment |
multiple line comment | /* line another line */ |
"comment another comment" |
if (0) { commented out can contain {} if balanced } |
/* comment 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 |
none |
swap |
tmp = x; x = y; y = tmp; |
lassign "$x $y" y x | none | |
compound assignment arithmetic, string, bit |
+= -= *= /= none %= += none <<= >>= &= |= ^= |
+= -= *= /= //= .= <<= >>= &= |= ^= |
||
increment and decrement | var x = 1; var y = ++x; var z = --y; |
premodifiers: ++i --i postmodifiers: i++ i-- |
||
variable declaration |
||||
null |
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 synonyms: 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 synonyms: && || ! |
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 Inf. |
evaluates to empty string |
power |
Math.pow(2, 32) | 2 raisedTo 32 | expr 2 ** 32 expr pow(2, 32) |
2 ** 32 |
sqrt |
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 Math.E |
Float pi Float e |
expr 4 * atan(1) expr exp(1) |
|
float truncation round towards zero, round to nearest integer, round down, round up |
none Math.round(3.1) Math.floor(3.1) Math.ceil(3.1) |
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) |
none round(3.14) floor(3.14) ceil(3.14) |
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: 1.#INF00 |
random integer, uniform float | Math.floor(Math.random() * 100) Math.random() |
rnd := Random new. rnd next. (rnd nextInt: 100) - 1. |
expr int(rand() * 100) expr rand() none |
; 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 0x2a |
|||
radix convert integer to and from string with radix |
(42).toString(7) ?? |
|||
strings | ||||
javascript | smalltalk | tcl | autohotkey | |
string type |
String | |||
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. |
yes | |
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"] " " | ||
split |
// [ "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": 12.3456.toFixed(2) |
set fmt "lorem %s %d %.2f" format $fmt "ipsum" 13 3.7 |
||
translate case to upper, to lower |
"lorem".toUpperCase() "LOREM".toLowerCase() |
'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: parseInt("12A") // NaN: parseInt("A") |
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") "foobar".endsWith("bar") |
|||
length |
"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) "A".charCodeAt(0) |
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/)) { alert("party!"); } |
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); | |||
backreference 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 |
Date | |||
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); |
t 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() t.getMinutes() t.getSeconds() |
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); |
none | ||
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? | ||||
microseconds | ||||
sleep |
none | after 500 | ||
timeout | ||||
arrays | ||||
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]; a.push(9); 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]; a.unshift(5); 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) { alert(n); }); |
nums do: [:o| Transcript show: o printString; cr] | foreach i $a { puts $i } | |
reverse | var a = [1, 2, 3]; a.reverse(); |
set a {1 2 3} set a [lreverse $a] |
||
sort | var a = [3, 1, 4, 2]; a.sort(); |
set a {3 1 4 2} set a [lsort $a] |
||
dedupe | lsort -unique {1 2 2 3} | |||
membership |
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} |
|||
map |
// callback gets 3 args: // value, index, array a.map(function(x) { 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 |
|
filter |
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 |
|
reduce |
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 ::tcl::mathop::+ |
|
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; }; a.every(even) a.some(even) |
#(1 2 3 4) anySatisfy: [:o | o even] | ||
dictionaries | ||||
javascript | smalltalk | tcl | autohotkey | |
constructor |
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 | |
lookup |
d.t d["t"] |
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 | ||
iterate |
for (var k in d) { use k or d[k] } |
h keysAndValuesDo: [:k :v| code ] | foreach {k v} $d { code } |
|
keys and values as arrays | h keys h values |
|||
functions | ||||
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; alert(counter()); |
|||
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"); break; case 1: alert("one hit\n"); break; default: 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++) { alert(i); } |
1 to: 100 do: [ :i | msg value: i printString ]. |
for {set i 0} {$i < 10} {incr i} { puts $i } |
|
exceptions | ||||
javascript | smalltalk | tcl | autohotkey | |
base exception | Any value can be thrown. | |||
predefined exceptions | Error EvalError RangeError ReferenceError SyntaxError TypeError URIError |
|||
raise exception | throw new Error("bad arg"); | Exception raiseSignal: 'bam!'. | error "bad arg" | |
catch-all handler |
try { risky(); } catch (e) { alert("risky failed: " + e.message); } |
|||
uncaught exception behavior | stderr and exit | |||
re-raise exception | try { throw new Error("bam!"); } catch (e) { alert("re-raising..."); 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) { alert(e.message); } else { throw e; } } |
[ o risky ] on: Exception do: [ :ex | Transcript show: 'risky failed' ] |
catch risky retval if { retval != 0 } { puts "risky failed" } |
|
finally block |
acquire_resource(); try { risky(); } finally { release_resource(); } |
|||
streams | ||||
javascript | smalltalk | tcl | autohotkey | |
standard file handles | stdin stdout stderr |
|||
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 | ||||
files | ||||
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); |
|||
directories | ||||
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 |
$env(HOME) | |||
get pid, parent pid | ||||
exit |
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 | ||||
objects | ||||
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: this.plus = function(v) { return this.value + v; }; // outside constructor: Int.prototype.plus = function (v) { return this.value + v; } |
|||
invoke method |
i.plus(3); | |||
inheritance and polymorphism | ||||
javascript | smalltalk | tcl | autohotkey | |
subclass |
||||
mixin | ||||
overload operator | ||||
reflection | ||||
javascript | smalltalk | tcl | autohotkey | |
object id |
none | |||
inspect type |
typeof([]) === 'object' | |||
basic types | number string boolean undefined function object # these evaluate as 'object': typeof(null) typeof([]) typeof({}) |
|||
inspect class | // returns prototype object: Object.getPrototypeOf(o) |
'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 |
eval('1 + 1') | |||
list object methods |
1 class selectors. | |||
list object attributes |
||||
list loaded libraries | ||||
list loaded namespaces | ||||
inspect namespace | ||||
pretty-print |
var d = {"lorem": 1, "ipsum": [2, 3]}; console.log(JSON.stringify(d, null, 2)); |
|||
source line number and file name | ||||
command line documentation | ||||
gui | ||||
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" | |
button | ||||
text entry | ||||
frame | ||||
label | ||||
image | ||||
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 | ||||
____________________________________________ | ____________________________________________ | ____________________________________________ | ____________________________________________ |
General
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
interpreter
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.
tcl:
Code fragments such as
1 + 1
or
[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.
tcl:
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.
tcl:
The method described requires that there not be an unmatched right curly bracket in the comment.
Variables and Expressions
are identifiers case sensitive
assignment
How to assign a value to a variable.
parallel assignment
How to assign values to variables in parallel.
swap
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.
null
The null literal.
tcl
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.
tcl:
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.
falsehoods
Values which are false in conditional expressions.
tcl:
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
tcl
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
tcl:
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"}
0
% expr {"0" == "00"}
1
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"}
0
The relational operators can be invoked as commands in the following manner:
% ::tcl::mathop::== 1 1
1
% ::tcl::mathop::!= 1 1
0
% ::tcl::mathop::> 1 1
%::tcl::mathop::< 1 1
0
% ::tcl::mathop::>= 1 1
1
% ::tcl::mathop::<= 1 1
1
% ::tcl::mathop::eq "lorem" "ipsum"
0
%::tcl::mathop::ne "lorem" "ipsum"
1
autohotkey:
<> is a synonym for !=.
convert from string
convert to string
arithmetic expressions
How to evaluate an arithmetic expression.
tcl:
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.
tcl:
Arithmetic operators are normally used as arguments to expr, but commands also exist for each of them:
::tcl::mathop::+
::tcl::mathop::-
::tcl::mathop::*
::tcl::mathop::/
::tcl::mathop::**
::tcl::mathop::%
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
Strings
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.
escapes
Character escape sequences which can be used in string literals.
variable interpolation
How to interpolate variables in a string.
length
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.
split
How to split a string into an array of strings.
tcl:
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.
join
How to concatenate the elements of an array into a string with a separator.
scan
sprintf
How to create a string using a printf style format.
case manipulation
strip
pad on right, pad on left
string to number
tcl:
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.
modifiers
tcl:
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.
tcl:
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.
Arrays
tcl:
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.
tcl:
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 http://www.tcl.tk/man/tcl/tutorial/Tcl15.html.
array slice
How to slice a subarray from an array.
array iteration
membership
How to test for membership in an array.
intersection
How to compute an intersection.
union
map
filter
reduce
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.
Dictionaries
tcl:
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
$d(t)
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
Functions
tcl:
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
if
tcl:
Tcl also has a switch:
switch $a 0 { puts "no" } 1 { puts "yes" } 2 { puts "maybe" } default { puts "error" }
autohotkey:
The traditional style omits the parens around the conditionals.
|if n = 0
{
msgbox % "zero hits"
} _
else if n = 1
{
msgbox % "one hit"
}
else
{
msgbox % n . " hits"
}
while
break/continue/redo
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.
for
Exceptions
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.
tcl:
A tcl process can have multiple interpreters and multiple threads. However, each interpreter is limited to a single thread.
wait on thread
Files
print to standard out
tcl:
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
GUI
File Formats
Directories
Processes and Environment
external command
tcl
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.
backticks
command line args
speech
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.
exit
set signal handler
Libraries and Namespaces
library
What a library looks like.
import library
library path
namespace declaration
namespace separator
Reflection
class
Smalltalk
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/Pharo.app/Contents/MacOS/Pharo
-rwxr-xr-x 1 hpglot staff 867488 May 15 2014 pharo-vm/Pharo.app/Contents/MacOS/Pharo
$ ./pharo-vm/Pharo.app/Contents/MacOS/Pharo 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
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.
AutoHotkey
JavaScript
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)
2.302585092994046
> 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
302
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:
<script>
var sum = 1 + 2;
alert('the sum is ' + sum);
</script>
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.