More Interpreted Languages: Perl, Tcl, Lua, Groovy

a side-by-side reference sheet

grammar and invocation | variables and expressions | arithmetic and logic | strings | regexes | dates and time | arrays | dictionaries | functions | execution control | exceptions | file handles | files | file formats | directories | processes and environment | option parsing | libraries and namespaces | objects | polymorphism | reflection | net and web | unit tests | debugging and profiling | java interop

perl tcl lua groovy
version used
 
5.14; 5.16 8.5 5.1 2.2
show version $ perl --version $ tclsh
% info tclversion
$ lua -v $ groovy -v
implicit prologue
 
use strict;
grammar and invocation
perl tcl lua groovy
interpreter
 
$ perl foo.p $ tclsh foo.tcl $ lua foo.lua $ echo 'println "hi!"' > hi.groovy
$ groovy hi.groovy
repl
 
$ perl -de 0 $ tclsh $ lua $ groovysh
command line program $ perl -e 'print("hi\n")' none $ lua -e 'print("hi world!")' $ groovy -e 'println "hi world!"'
block delimiters
 
{} {} or "" do end {}
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
newline or ;

newline not a separator inside (), [], triple quote literal, or after binary operator or backslash.
are expressions statements no no yes
source code encoding use utf8;
end-of-line comment # comment # comment -- comment // comment
multiple line comment =for
comment line
another line
=cut
if (0) {
  commented out
  can contain {} if balanced
}
--[[
  commented out
  also commented out
]]
/* comment
another comment */
variables and expressions
perl tcl lua groovy
local variable my $v;
my (@a, %d);
my $x = 1;
my ($y, $z) = (2, 3);
# set variable inside procedure
proc foo {args} {
  set x 1
  
}
local x = 1 x = 1
def y = 2
Integer z = 3
regions which define lexical scope top level:
  file

nestable:
  function body
  anonymous function body
  anonymous block
global variable our ($g1, $g2) = (7, 8);

sub swap_globals {
  ($g1, $g2) = ($g2, $g1);
}
# 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
end
constant
 
use constant PI => 3.14;
assignment
 
$v = 1; set x 1 x = 1 x = 1
parallel assignment
 
($x, $y, $z) = (1, 2, 3);

# 3 is discarded:
($x, $y) = (1, 2, 3);

# $z set to undef:
($x, $y, $z) = (1, 2);
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
(x, y, z) = [1, 2, 3]

// 3 is discarded:
(x, y) = [1, 2, 3]

// z is set to null:
(x, y, z) = [1, 2]
swap
 
($x, $y) = ($y, $x); lassign "$x $y" y x x, y = y, x (x, y) = [y, x]
compound assignment
arithmetic, string, logical, bit
+= -= *= none /= %= **=
.= x=
&&=
^=
«= »= &= |= ^=
increment and decrement my $x = 1;
my $y = ++$x;
my $z = —$y;
null
 
undef "" nil null
null test
 
! defined $v v eq "" v == nil v == null
undefined variable access error under use strict; otherwise undef error nil raises groovy.lang.MissingPropertyException
conditional expression $x > 0 ? $x : -$x expr $x > 0 ? $x : -$x none x > 0 ? x : -x
arithmetic and logic
perl tcl lua groovy
true and false
 
1 "" 1 0 true false true false
falsehoods undef 0 0.0 "" "0" () 0 "false" "no"
most strings cause error in boolean context; nonzero numbers are true
false nil false null 0 0.0 "" [] [:]
logical operators
 
&& || !
lower precedence:
and or xor not
&& || ! and or not && || !
relational expressions numbers: == != > < >= <=
strings: eq ne gt lt ge le
if {$x > 3} {}
# outside of conditionals use expr:
expr $x > 3
x > 3 x > 0
relational operators == != > < >= <=

# string comparison:
eq ne
== ~= < > >= <= == != > < >= <=
min and max use List::Util qw(min max);

min(1, 2, 3);
max(1, 2, 3);

@a = (1, 2, 3);
min(@a);
max(@a);
expr min(1, 2, 3)
expr max(1, 2, 3)
math.min(1, 2, 3)
math.max(1, 2, 3)

math.min(unpack({1 ,2 ,3}))
math.max(unpack({1, 2, 3}))
[1, 2, 3].min()
[1, 2, 3].max()

// binary functions:
Math.min(1, 2)
Math.max(1, 2)
three value comparison 0 <=> 1
"do" cmp "re"
arithmetic expression + - * / none % expr 1 + 3
# expr not needed in conditionals:
if {1 + 3} {}
1 + 3 1 + 3
arithmetic operators
addition, subtraction, multiplication, float division, quotient, modulus
+ - * none / % + - * / none % ^ + - * / ?? %
integer division
 
int(13 / 5) expr $x / $y math.floor(x / y) Math.floor(x / y)
integer division by zero
 
error error returns assignable value inf, nan, or -inf depending upon whether dividend is positive, zero, or negative.

There are no literals for any of these values.
raises java.lang.ArithmeticException
float division
 
13 / 5 expr $x * 1.0 / $y x / y x / y
float division by zero
 
error returns assignable value Inf if dividend is positive and -Inf if negative. Raises error if dividend is zero.

There is a literal for
Inf.
same behavior as for integers raises java.lang.ArithmeticException
power 2 ** 32 expr 2 ** 32
expr pow(2, 32)
2 ^ 32
math.pow(2, 32)
2 ** 32
sqrt
 
sqrt(2) expr sqrt(2) math.sqrt(2) Math.sqrt(2)
sqrt -1
 
error unless use Math::Complex in effect error nan Double.NaN
transcendental functions use Math::Trig qw(tan asin acos atan);

exp log sin cos tan asin acos atan atan2
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.exp math.log math.sin math.cos math.tan math.asin math.acos math.atan math.atan2 Math.exp Math.log Math.sin Math.cos Math.tan Math.asin Math.acos Math.atan Math.atan2
transcendental constants
π and e
expr 4 * atan(1)
expr exp(1)
math.pi
math.exp(1)
Math.PI
Math.E
float truncation
round towards zero, round to nearest integer, round down, round up
# cpan -i Number::Format
use Number::Format 'round';
use POSIX qw(ceil floor);

int($x)
round($x, 0)
ceil($x)
floor($x)
expr int(3.1)
expr round(3.1)
expr floor(3.1)
expr ceil(3.1)
none
none
math.floor(3.1)
math.ceil(3.1)
(int)3.1
Math.round(3.1)
(int)Math.floor(3.1)
(int)Math.ceil(3.1)
absolute value
 
abs($x) expr abs(-3) math.abs(-3) Math.abs(-3)
integer overflow
 
converted to float; use Math::BigInt to create arbitrary length integers arbitrary length integers introduced in 8.5 all numbers are floats becomes type java.math.BigInteger
float overflow
 
inf error inf Double.POSITIVE_INFINITY
rational construction use Math::BigRat;

my $x = Math::BigRat->new("22/7");
rational decomposition $x->numerator();
$x->denominator();
complex construction use Math::Complex;

my $z = 1 + 1.414 * i;
complex decomposition
real and imaginary component, argument, absolute value, conjugate
Re($z);
Im($z);
arg($z);
abs($z);
~$z;
random number
uniform integer, uniform float, normal float
int(rand() * 100)
rand()
none
expr int(rand() * 100)
expr rand()
none
math.random(100) - 1
math.random()
none
rnd = new Random()
rnd.nextInt(100)
rnd.nextDouble()
random seed
how to set
srand 17;

my $seed = srand;
srand($seed);
expr srand(17) math.randomseed(17) rnd = new Random()
rnd.setSeed(17)
bit operators
left shift, right shift, and, inclusive or, exclusive or, complement
<< >> & | ^ ~ << >> & | ^ ~ none << >> & | ^ ~
binary, octal, and hex literals 0b101010
052
0x2a
radix # cpan -i Math::BaseCalc
use Math::BaseCalc;

$c = new Math::BaseCalc(
  digits => [0..6]);
$c->to_base(42);
$c->from_base("60");
strings
perl tcl lua groovy
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\""
'don\'t say "no"'
"""don't say "no\""""
'''don't say "no"'''
/don't say "no"/
newline in literal
 
'first line
second line'

"first line
second line"
yes yes, if preceded by backslash // triple quote literals only:
"""foo
bar"""

'''foo
bar'''
literal escapes double quoted:
\a \b \cx \e \f \n \r \t \xhh \x{hhhh} \ooo \o{ooo}

single quoted:
\' \\
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
// including triple quotes:

\b \f \n \r \t
\\ \" \'
\uhhhh \o \oo \ooo

// slash quotes:
\/
here document $word = "amet";

$s = «EOF;
lorem ipsum
dolor sit $word
EOF
none none none
variable interpolation my $count = 3;
my $item = "ball";
print "$count ${item}s\n";
set count 3
set item "ball"
"$count ${item}s"
none count = 3
item = "ball"

"$count ${item}s"
"""$count ${item}s"""
expression interpolation none none none "1 + 1 = ${1 + 1}"
"""1 + 1 = ${1 + 1}"""
concatenate my $s = "Hello, ";
my $s2 = $s . "World!";
set s1 "Hello, "
set s2 "World!"
set s $s1$s2
s = "Hello, " .. "World!" s = "Hello, " + "World!"
replicate
 
my $hbar = "-" x 80; set hbar [string repeat "-" 80] string.rep("-", 80) hbar = "-" * 80
sprintf my $fmt = "lorem %s %d %f";
sprintf($fmt, "ipsum", 13, 3.7)
set fmt "lorem %s %d %.2f"
format $fmt "ipsum" 13 3.7
string.format("lorem %s %d %.2f",
  "ipsum", 13, 3.7)
fmt = "lorem %s %d %.2f"
String.format(fmt, "ipsum", 13, 3.7)
case manipulation uc("lorem")
lc("LOREM")
string toupper "lorem"
string tolower "LOREM"
string.upper("lorem")
string.lower("LOREM")
"lorem".toUpperCase()
"LOREM".toLowerCase()
capitalize
string, words
# cpan -i Text::Autoformat
use Text::Autoformat;

ucfirst("lorem")
autoformat("lorem ipsum",
  {case => 'title'})
none
none
none
none
"lorem".capitalize()
none
trim # cpan -i Text::Trim
use Text::Trim;

trim " lorem "
ltrim " lorem"
rtrim "lorem "
string trim " lorem "
string trimleft " lorem"
string trimright "lorem "
none " lorem ".trim()
pad
on right, on left, centered
# cpan -i Text::Format
use Text::Format;

sprintf("%-10s", "lorem")
sprintf("%10s", "lorem")

$text = Text::Format->new(columns => 10);
$text->center("lorem");
format "%10s" "lorem"
format "%-10s" "lorem"
none "lorem".padRight(10)
"lorem".padLeft(10)
"lorem.center(10)
string to number 7 + "12"
73.9 + ".037"
use expr to interpret as numbers:
set x "12"
expr 7 + $x
set y ".037"
expr 73.9 + $y
7 + tonumber("12")
73.9 + tonumber(".037")
arithmetic operators attempt numeric conversion of string operands
7 + Integer.parseInt("12")
73.9 + Double.parseDouble(".037")
number to string
 
"value: " . 8 all values are strings "value: " .. 8 "value: " + 8

// explicit conversion:
8.toString()
join
 
join(" ", qw(do re mi fa)) join [list "do" "re" "mi"] " " table.concat({"do","re","mi"}, " ") ["do", "re", "mi"].join(" ")
split
 
split(/\s+/, "do re mi fa") split "do re mi" none "do re mi".split()
split in two split(/\s+/, "do re mi fa", 2)
split and keep delimiters split(/(\s+)/, "do re mi fa")
length
 
length("lorem") string length "lorem" string.len("lorem") "lorem".size()
"lorem".length()
index of substring
 
# returns -1 if not found:
index("lorem ipsum", "ipsum")
rindex("do re re", "re")
string first "ipsum" "lorem ipsum" string.find("lorem ipsum", "ipsum") "lorem ipsum".indexOf("ipsum")
extract substring
 
substr("lorem ipsum", 6, 5) string range "lorem ipsum" 6 10 string.sub("lorem ipsum", 7, 11) "lorem ipsum".substring(6, 11)
extract character # can't use index notation with
# strings:

substr("lorem ipsum", 6, 1)
chr and ord chr(65)
ord("A")
format %c 65
scan A %c ascii_value
string.char(65)
string.byte("A")
(Character)65
(Integer)'A'
to array of characters split(//, "abcd") split "abcd" ""
translate characters $s = "hello";
$s =~ tr/a-z/n-za-m/;
delete characters $s = "disemvowel me";
$s =~ tr/aeiou//d;
squeeze characters $s = "too much space";
$s =~ tr/ //s;
regular expressions
perl tcl lua groovy
literal, custom delimited literal /lorem|ipsum/
qr(/etc/hosts)
character class abbreviations and anchors . \d \D \h \H \s \S \v \V \w \W 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
anchors ^ $ \A \b \B \z \Z
match test
 
if ($s =~ /1999/) {
  print "party!\n";
}
if [regexp -- {1999} $s] {
  puts "party!"
}
if string.match(s, "1999") then
  print("party!")
end
s = "it is 1999"

if (s =~ /1999/) {
  println("party!")
}
case insensitive match test "Lorem" =~ /lorem/i regexp -nocase -- {lorem} "Lorem" none "Lorem" =~ /(?i)lorem/
modifiers i m s p x -all -expanded -indices -inline
-line -lineanchor -linestop -nocase
none i s
substitution my $s = "do re mi mi mi";
$s =~ s/mi/ma/g;
set s "do re mi mi mi"
regsub -all -- "mi" $s "ma"
s = "do re mi mi mi"
s = string.gsub(s, "mi", "ma")
"do re mi mi mi".replaceAll(/mi/, "ma")
match, prematch, postmatch f ($s =~ /\d{4}/p) {
  $match = ${^MATCH};
  $prematch = ${^PREMATCH};
  $postmatch = ${^POSTMATCH};
}
group capture $rx = qr/(\d{4})-(\d{2})-(\d{2})/;
"2010-06-03" =~ $rx;
($yr, $mo, $dy) = ($1, $2, $3);
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)
s = "2010-06-03"
m = s =~ /(\d{4})-(\d{2})-(\d{2})/
yr = m.group(1)
mo = m.group(2)
dy = m.group(3)
named group capture $s = "foo.txt";
$s =~ /^(?<file>.+)\.(?<suffix>.+)$/;

$+{"file"}
$+{"suffix"}
scan my $s = "dolor sit amet";
@a = $s =~ m/\w+/g;
backreference
in regex, in substitution string
"do do" =~ /(\w+) \1/

my $s = "do re";
$s =~ s/(\w+) (\w+)/$2 $1/;
regexp -- {(\w+) \1} "do do"

set rx {(\w+) (\w+)}
regsub -all -- $rx "do re" {\2 \1}
string.match("do do", "(%w+) %1")

rx = "(%w+) (%w+)"
string.gsub("do re", rx, "%2 %1")
"do do" =~ /(\w+) \1/

rx = /(\w+) (\w+)/
"do re".replaceAll(rx, '$2 $1')
recursive regex /\(([^()]*|(?R))\)/
dates and time
perl tcl lua groovy
date/time type Time::Piece if use Time::Piece in effect, otherwise tm array
current date/time use Time::Piece;

my $t = localtime(time);
my $utc = gmtime(time);
set t [clock seconds] t = os.time() t = new Date()
to unix epoch, from unix epoch use Time::Local;
use Time::Piece;

my $epoch = timelocal($t);
my $t2 = localtime(1304442000);
t
set t2 1315716177
t
t2 = 1315716177
Math.round(t.getTime() / 1000)
t = new Date(1315716177 * 1000)
current unix epoch $epoch = time;
strftime use Time::Piece;

$t = localtime(time);
$fmt = "%Y-%m-%d %H:%M:%S";
print $t->strftime($fmt);
set fmt "%Y-%m-%d %H:%M:%S"
clock format $t -format $fmt
os.date("%Y-%m-%d %H:%M:%S", t)
strptime use Time::Local;
use Time::Piece;

$s = "2011-05-03 10:00:00";
$fmt = "%Y-%m-%d %H:%M:%S";
$t = Time::Piece->strptime($s,$fmt);
none none
parse date w/o format # cpan -i Date::Parse
use Date::Parse;

$epoch = str2time("July 7, 1999");
set t [clock scan "July 7, 1999"] none
get date parts $t->year
$t->mon
$t->mday
clock format $t -format "%Y"
clock format $t -format "%m"
clock format $t -format "%d"
none
get time parts $t->hour
$t->min
$t->sec
clock format $t -format "%H"
clock format $t -format "%M"
clock format $t -format "%S"
none
build date/time from parts $dt = DateTime->new(
  year=>2014,
  month=>4,
  day=>1,
  hour=>10,
  minute=>3,
  second=>56);
none none
result of date subtraction Time::Seconds object if use Time::Piece in effect; not meaningful to subtract tm arrays
add time duration use Time::Seconds;

$now = localtime(time);
$now += 10 * ONE_MINUTE() + 3;
local timezone Time::Piece has local timezone if created with localtime and UTC timezone if created with gmtime; tm arrays have no timezone or offset info
timezone name; offset from UTC; is daylight savings? # cpan -i DateTime
use DateTime;
use DateTime::TimeZone;

$dt = DateTime->now();
$tz = DateTime::TimeZone->new(
  name=>"local");

$tz->name;
$tz->offset_for_datetime($dt) /
  3600;
$tz->is_dst_for_datetime($dt);
microseconds use Time::HiRes qw(gettimeofday);

($sec, $usec) = gettimeofday;
sleep
 
# a float argument will be truncated
# to an integer:

sleep 1;
after 500 none
timeout eval {
  $SIG{ALRM}= sub {die "timeout!";};
  alarm 5;
  sleep 10;
};
alarm 0;
arrays
perl tcl lua groovy
literal
 
@a = (1, 2, 3, 4); set a [list 1 2 3 4]
set a {1 2 3 4}
a = { 1, 2, 3, 4 } a = [1, 2, 3, 4]
quote words @a = qw(do re mi);
size
 
$#a + 1
scalar(@a)
llength $a -- not well-defined if array
-- contains nil values:

# a
a.size
lookup
 
$a[0]

# returns last element:
$a[-1]
lindex $a 0 a[1] a[0]
update $a[0] = "lorem"; # provide start and end index
# of elements to replace:

set a [lreplace $a 1 1 "lorem"]
a[1] = "lorem" a[0] = 'lorem'
out-of-bounds behavior @a = ();
# evaluates as undef:
$a[10];
# increases array size to 11:
$a[10] = "lorem";
returns "" returns nil returns null
index of element
first and last occurrence
use List::Util 'first';

@a = qw(x y z w);
$i = first {$a[$_] eq "y"} (0..$#a);
lsearch {6 7 7 8} 7
lindex [lsearch -all {6 7 7 8} 7] end
# returns -1 if not found
none; use for and ipairs [6, 7, 7, 8].indexOf(7)
[6, 7, 7, 8].lastIndexOf(7)
// returns -1 if not found
slice
 
# select 3rd and 4th elements:
@a[2..3]
splice(@a, 2, 2)
lrange $a 1 2 none // ['b', 'c']:
['a', 'b', 'c', 'd'][1..2]
slice to end @a[1..$#a] lrange {"a" "b" "c" "d"} 1 end none // ['b', 'c', 'd']:
['a', 'b', 'c', 'd'][1..-1]
manipulate back @a = (6, 7, 8);
push @a, 9;
pop @a;
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]
a.push(9)
// also:
a << 9
i = a.pop()
manipulate front @a = (6, 7, 8);
unshift @a, 5;
shift @a;
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]
a.add(0, 5)
i = a.remove(0)
concatenate
 
@a = (1, 2, 3);
@a2 = (@a, (4, 5, 6));
push @a, (4,5,6);
set a [concat {1 2 3} {4 5 6}] none [1, 2, 3] + [4, 5, 6]
replicate
 
@a = (undef) x 10; lrepeat 10 "" none a = [null] * 10
copy
address copy, shallow copy, deep copy
use Storable 'dclone'

my @a = (1,2,[3,4]);
my $a2 = \@a;
my @a3 = @a;
my @a4 = @{dclone(\@a)};
arrays as function arguments each element passed as separate argument; use reference to pass array as single argument
iterate over elements for $i (1, 2, 3) { print "$i\n" } foreach i $a { puts $i } for k,v in ipairs(a) do
  print(v)
end
for (i in [1, 2, 3, 4]) {
  println i
}
iterate over range for $i (1..1_000_000) {
  code
}
instantiate range as array @a = 1..10;
reverse
 
@a = (1, 2, 3);

reverse @a;
@a = reverse @a;
set a {1 2 3}
set a [lreverse $a]
none a = [1, 2, 3]
a.reverse()
sort
 
@a = qw(b A a B);

sort @a;
@a = sort @a;
sort { lc($a) cmp lc($b) } @a;
set a {3 1 4 2}
set a [lsort $a]
a = {3, 1, 4, 2}
table.sort(a)
a = [3, 1, 4, 2]
a.sort()
dedupe use List::MoreUtils 'uniq';

my @a = (1, 2, 2, 3);

my @a2 = uniq @a;
@a = uniq @a;
lsort -unique {1 2 2 3} none a = [1, 2, 2, 3]

// modifies array in place:
a.unique()
membership 7 ~~ @a expr {7 in $a}
expr {7 ni $a}
none [1, 2, 3].contains(7)
![1, 2, 3].contains(7)
intersection
 
package require struct::set

::struct::set intersect {1 2} {2 3}
none [1, 2].intersect([2, 3])
union
 
package require struct::set

::struct::set union {1 2} {2 3 4}
none ([1, 2] + [2, 3, 4]).unique()
relative complement
 
package require struct::set

::struct::set difference {1 2 3} {2}
none [1 2 3] - [2]
map
 
map { $_ * $_ } (1,2,3) package require struct::list

proc sqr {x} {return [expr $x * $x]}
::struct::list map {1 2 3} sqr
none [1, 2, 3].collect() { n -> n * n }
filter
 
grep { $_ > 1 } (1,2,3) package require struct::list

proc gt1 {x} {return [expr $x > 1]}
::struct::list filter {1 2 3} gt1
none [1, 2, 3].findAll() { x -> x > 2 }
reduce
 
use List::Util 'reduce';

reduce { $x + $y } 0, (1,2,3)
package require struct::list

::struct::list fold {1 2 3} 0
  ::tcl::mathop::+
none [1, 2, 3].inject(0) { x, y -> x + y }
universal and existential tests # cpan -i List::MoreUtils
use List::MoreUtils qw(all any);

all { $_ % 2 == 0 } (1, 2, 3, 4)
any { $_ % 2 == 0 } (1, 2, 3, 4)
none none none
shuffle use List::Util 'shuffle';

@a = (1, 2, 3, 4);
shuffle(@a);
none none a = [1, 2, 3, 4]
// no return value:
Collections.shuffle(a)
zip
 
# cpan -i List::MoreUtils
use List::MoreUtils 'zip';

@nums = (1, 2, 3);
@lets = qw(a b c);
# flat array of 6 elements:
@a = zip @nums, @lets;
none none [[1,2,3], ['a', 'b', 'c']].transpose()
dictionaries
perl tcl lua groovy
literal %d = ( "t" => 1, "f" => 0 );

# barewords permitted in front of =>
# under 'use strict'
set d [dict create t 1 f 0] d = { t=1, f=0 } d = ["t": 1, "f": 0]
size
 
scalar(keys %d) dict size $d size = 0
for k, v in pairs(d) do
  size = size + 1
end
d.size()
lookup $d{"t"}

# barewords permitted inside { }
# under 'use strict'
dict get $d t d.t
d["t"]
d["t"]
update dict set d t 2 d["t"] = 2
d.t = 2
d["t"] = 2
out of bounds behavior %d = ();
# evaluates as undef:
$d{"lorem"};
# adds key/value pair:
$d{"lorem"} = "ipsum";
error returns nil returns null
is key present
 
exists $d{"y"} dict exists $d t d["t"] ~= nil d.containsKey("t")
delete %d = ( 1 => "t", 0 => "f" );
delete $d{1};
dict unset d t d.t = nil
d["t"] = nil
from array of pairs, from even length array @a = (1,"a",2,"b",3,"c");
%d = @a;
merge %d1 = (a => 1, b => 2);
%d2 = (b => 3, c => 4);
%d1 = (%d1, %d2);
invert %to_num = (t=>1, f=>0);
%to_let = reverse %to_num;
iteration while (($k, $v) = each %d) {
  code
}
foreach {k v} $d {
  code
}
for k,v in pairs(d) do
  use k or v
end
keys and values as arrays keys %d
values %d
sort by values foreach $k (sort
  { $d{$a} <=> $d{$b} } keys %d) {
  print "$k: $d{$k}\n";
}
default value, computed value my %counts;
$counts{'foo'} += 1

define a tied hash for computed values and defaults other than zero or empty string
functions
perl tcl lua groovy
define function sub add3 { $_[0] + $_[1] + $_[2] }

sub add3 {
  my ($x1, $x2, $x3) = @_;
  $x1 + $x2 + $x3;
}
proc add { x y } {
  expr $x + $y
}
function add(x, y)
  return x + y
end
def (x, y) {
  x + y
}
invoke function
 
add3(1, 2, 3);

# parens are optional:
add3 1, 2, 3;
# statement position:
add 1 2

# argument position:
set a [ add 1 2 ]
add(1, 2) add(1, 2)

// parens are optional:
add 1, 2
nested function defined when containing function is defined; visible outside containing function defined when containing function executes; visible outside containing function visible outside containing function
missing argument behavior set to undef error nil raises groovy.lang.MissingMethodException
extra argument behavior
 
error ignored raises groovy.lang.MissingMethodException
default argument
 
sub my_log {
  my $x = shift;
  my $base = shift // 10;

  log($x) / log($base);
}

my_log(42);
my_log(42, exp(1));
proc log {x {base 10 }} { body } none
collect arguments in array sub first_and_last {

  if ( @_ >= 1 ) {
    print "first: $_[0]\n";
  }

  if ( @_ >= 2 ) {
    print "last: $_[-1]\n";
  }
}
last arg contains list of remaining values declare function with ellipsis:
function foo(...)
  local arg = {...}
pass array elements as separate arguments @a = (2, 3);

add3(1, @a);

# arrays are always expanded when used
# as arguments
return value return arg or last expression evaluated return arg or empty string return arg or nil return arg or last expression evaluated
multiple return values sub first_and_second {
  return ($_[0], $_[1]);
}

@a = (1,2,3);
($x, $y) = first_and_second(@a);
none function roots(x)
  r = math.sqrt(x)
  return r, -r
end
r1,r2 = roots(4)
none
anonymous function literal $sqr = sub { $_[0] * $_[0] } set sqr {{x} {return [expr $x*$x]}} sqr = function(x) return x*x end sqr = { x -> Math.sqrt x }
invoke anonymous function
 
$sqr->(2) apply $sqr 2 sqr(2) sqr(2)
function as value my $func = \&add;
function with private state use feature state;

sub counter {
  state $i = 0;
  ++$i;
}

print counter() . "\n";
closure sub make_counter {
  my $i = 0;
  return sub { ++$i };
}

my $nays = make_counter;
print $nays->() . "\n";
generator to be added to Tcl 8.6 crt = coroutine.create(
  function (n)
    while (true) do
      coroutine.yield(n % 2)
      n = n + 1
    end
  end
)

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

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

_, retval = coroutine.resume(crt)
print("parity: " .. retval)
execution control
perl tcl lua groovy
if if ( 0 == $n ) {
  print "no hits\n"
} elsif ( 1 == $n ) {
  print "one hit\n"
} else {
  print "$n hits\n"
}
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")
else
  print(n .. " hits")
end
if (n == 0) {
  println("no hits")
}
else if (n == 1) {
  println("one hit")
}
else {
  println(n + " hits")
}
while while ( $i < 100 ) { $i++ } while { $i < 100 } {
  incr i
}
while i < 100 do
  i = i + 1
end
while (i < 100) {
  i += 1
}
break and continue last next break continue break none break continue
for for ( $i=0; $i <= 10; $i++ ) {
  print "$i\n";
}
for {set i 0} {$i < 10} {incr i} {
  puts $i
}
for i = 0, 9 do
  print(i)
end
for (i = 0; i < 10; i++) {
  println i
}
statement modifiers print "positive\n" if $i > 0;
print "nonzero\n" unless $i == 0;
exceptions
perl tcl lua groovy
raise exception die "bad arg"; error "bad arg" error "bad arg" throw new Exception("bad arg")
catch exception eval { risky };
if ($@) {
  print "risky failed: $@\n";
}
catch risky retval
if { retval != 0 } {
    puts "risky failed"
}
if not pcall(risky) then
  print "risky failed"
end
global variable for last exception $EVAL_ERROR: $@
$OS_ERROR: $!
$CHILD_ERROR: $?
finally/ensure none none
uncaught exception behavior stderr and exit stderr and exit
file handles
perl tcl lua groovy
standard file handles STDIN STDOUT STDERR stdin
stdout
stderr
io.stdin
io.stdout
io.stderr
System.in
System.out
System.err
read line from stdin $line = <STDIN>; gets stdin line line = io.stdin:read()
end-of-file behavior returns string without newline or undef
chomp chomp $line; string trimright $line "\r\n" none, read() and lines() remove trailing newlines
write line to stdout print "Hello, World!\n"; puts "Hello, World!" print "Hello, World!" print("Hello, World!\n")
println("Hello, World!")
System.out.print("Hello, World!\n")
System.out.println("Hello, World!")
write formatted string to stdout use Math::Trig 'pi';

printf("%.2f\n", pi);
open file for reading open my $f, "/etc/hosts" or die; set f [open "/tmp/foo"] f = io.open("/tmp/foo")
open file for writing open my $f, ">/tmp/test" or die; set f [open "/tmp/foo" "w"] f = io.open("/tmp/foo", "w")
set file handle encoding open my $fin, "<:encoding(UTF-8)", "/tmp/foo"
  or die;

open my $fout, ">:encoding(UTF-8)", "/tmp/bar"
  or die;
open file for appending open my $f, "»/tmp/err.log" or die;
close file
 
close $f or die; close $f f:close()
close file implicitly {
  open(my $f, ">/tmp/test") or die;
  print $f "lorem ipsum\n";
}
i/o error return false value
encoding error emit warning and replace bad byte with 4 character \xHH sequence
read line
 
$line = <$f>; gets $f f:read()
iterate over file by line while ($line = <$f>) {
  print $line;
}
while { [gets $f s] >= 0 } {
  use s
}
for s in f:lines() do
  use s
end
read file into array of strings @a = <$f>;
read file into string $s = do { local $/; <$f> }; set s [ read $f] s = f:read("*a")
write string
 
print $f "lorem ipsum"; puts -nonewline $f "lorem ipsum" f:write("lorem ipsum")
write line print $f "lorem ipsum\n";
flush file handle use IO::Handle;

$f->flush();
flush $f f:flush()
end-of-file test eof($f)
get and set file handle position tell($f)
seek($f, 0, SEEK_SET);
open temporary file use File::Temp;

$f = File::Temp->new();

print $f "lorem ipsum\n";

print "tmp file: ";
print $f->filename . "\n";

close $f or die;

# file is removed when file handle goes
# out of scope
in memory file my ($f, $s);
open($f, ">", \$s);
print $f "lorem ipsum\n";
$s;
files
perl tcl lua groovy
file exists test, file regular test -e "/etc/hosts"
-f "/etc/hosts"
file exists "/etc/hosts"
file isfile "/etc/hosts"
none f = new File('/etc/hosts')

f.exists()
f.isFile()
file size -s "/etc/hosts" f = new File('/etc/hosts')

f.length()
is file readable, writable, executable -r "/etc/hosts"
-w "/etc/hosts"
-x "/etc/hosts"
f = new File('etc/hosts')

f.canRead()
f.canWrite()
f.canExecute()
set file permissions chmod 0755, "/tmp/foo"; set s "/tmp/foo"
file attributes $s -permissions 0755
none
last modification time my @data = stat('/etc/passwd');

# unix epoch:
my $t = $data['mtime'];
copy file, remove file, rename file use File::Copy;

copy("/tmp/foo", "/tmp/bar");
unlink "/tmp/foo";
move("/tmp/bar", "/tmp/foo");
file copy "/tmp/foo" "/tmp/bar"
file delete "/tmp/foo"
file rename "/tmp/bar" "/tmp/foo"
none
create symlink, symlink test, readlink symlink "/etc/hosts", "/tmp/hosts";
-l "/etc/hosts"
readlink "/tmp/hosts"
generate unused file name use File::Temp;

$f = File::Temp->new(DIR=>"/tmp",
  TEMPLATE=>"fooXXXXX",
  CLEANUP=>0);
$path = $f->filename;
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")
f:close()
??
file formats
perl tcl lua groovy
parse csv # cpan -i Text::CSV
use Text::CSV;

my $csv = Text::CSV->new or die;
open my $f, $ARGV[0] or die;
while (my $row = $csv->getline($f)) {
  print join("\t", @$row) . "\n";
}
generate csv # cpan -i Text::CSV
use Text::CSV;

my $csv = Text::CSV->new or die;
$csv->eol ("\r\n");
open my $f, ">foo.csv" or die;
$csv->print($f, ["one", "une", "uno"]);
$csv->print($f,
  ["two", "deux", "dos"]);
$f->close or die;
json generate/parse # cpan -i JSON
use JSON;

$raw = {t => 1, f => 0};
$json = JSON->new->allow_nonref;
$s = $json->encode($raw);
$d = $json->decode($s);
generate xml # cpan -i XML::Writer
use XML::Writer;

my $writer = XML::Writer->new(
OUTPUT => STDOUT);
$writer->startTag("a");
$writer->startTag("b", id => "123");
$writer->characters("foo");
$writer->endTag("b");
$writer->endTag("a");

# <a><b id="123">foo</b></a>:
$writer->end;
parse xml # cpan -i XML::XPath
use XML::XPath;

my $xml = "<a><b><c>foo</c></b></a>";

# fatal error if XML not well-formed
my $doc = XML::XPath->new(xml => $xml);

my $nodes = $doc->find("/a/b/c");
print $nodes->size . "\n";

$node = $nodes->get_node(0);
print $node->string_value . "\n";
print $node->getAttribute("ref") . "\n";
parse html
directories
perl tcl lua groovy
working directory
get and set
use Cwd;

my $old_dir = cwd();

chdir("/tmp");
build pathname use File::Spec;

File::Spec->catfile("/etc", "hosts")
file join "/etc" "hosts"
dirname and basename use File::Basename;

print dirname("/etc/hosts");
print basename("/etc/hosts");
file dirname "/etc/hosts"
file tail "/etc/hosts"
absolute pathname use Cwd;

# symbolic links are resolved:
Cwd::abs_path("foo")
Cwd::abs_path("/foo")
Cwd::abs_path("../foo")
Cwd::abs_path(".")
iterate over directory by file opendir(my $dh, $ARGV[0]);

while (my $file = readdir($dh)) {
  print $file . "\n";
}

closedir($dh);
glob paths while ( </etc/*> ) {
  print $_ . "\n";
}
make directory use File::Path 'make_path';

make_path "/tmp/foo/bar";
file mkdir "/tmp/foo/bar"
recursive copy # cpan -i File::Copy::Recursive
use File::Copy::Recursive 'dircopy';

dircopy "/tmp/foodir",
  "/tmp/bardir";
remove empty directory rmdir "/tmp/foodir"; file delete "/tmp/foodir"
remove directory and contents use File::Path 'remove_tree';

remove_tree "/tmp/foodir";
file delete -force "/tmp/foodir"
directory test
 
-d "/tmp" file isdirectory "/tmp"
generate unused directory use File::Temp qw(tempdir);

$path = tempdir(DIR=>"/tmp",
  CLEANUP=>0);
system temporary file directory use File::Spec;

File::Spec->tmpdir
processes and environment
perl tcl lua groovy
command line arguments @ARGV [lindex $argv 0]
[lindex $argv 1]
# arg
arg[0]
arg[1]
args.size()
args[0]
args[1]
program name $0
environment variable
get, set
$ENV{"HOME"}

$ENV{"PATH") = "/bin";
$env(HOME) os.getenv("HOME") System.getenv("HOME")
get pid, parent pid $$
getppid
get user id and name $<
getpwuid($<)
exit
 
exit 0; exit 0 os.exit(0) System.exit(0)
set signal handler $SIG{INT} = sub {
  die "exiting…\n";
};
executable test -x "/bin/ls"
external command system("ls -l /tmp") == 0 or
  die "ls failed";
exec ls os.execute("ls")
escaped external command $path = <>;
chomp($path);
system("ls", "-l", $path) == 0 or
  die "ls failed";
command substitution my $files = ‘ls -l /tmp`;
# or
my $files = qx(ls);
set f [ open |ls ]
read f
f = io.popen("ls")
s = f:read("*a")
option parsing
perl tcl lua groovy
command line options use Getopt::Long;

my ($file, $help, $verbose);

my $usage =
  "usage: $0 [-f FILE] [-v] [ARG …]\n";

if (!GetOptions("file=s" => \$file,
                "help" => \$help,
                "verbose" => \$verbose)) {
  print $usage;
  exit 1;
}

if ($help) {
  print $usage;
  exit 0;
}

# After call to GetOptions() only
# positional arguments are in @ARGV.
#
# Options can follow positional arguments.
#
# Long options can be preceded by one or two
# hyphens. Single letters can be used if
# only one long option begins with that
# letter.
#
# Single letter options cannot be bundled
# after a single hyphen.
#
# Single letter options must be separated
# from an argument by a space or =.
libraries and namespaces
perl tcl lua groovy
load library require ’Foo.pm';

# searches @INC for Foo.pm:
require Foo;
source foo.tcl
add 3 7
require 'foo'
add(3,7)
load library in subdirectory require 'Foo/Bar.pm';

require Foo::Bar;
hot patch do 'Foo.pm';
load error fatal error if library not found or if last expression in library does not evaluate as true; fatal error parsing library propagates to client
main routine in library unless (caller) {
  code
}
library path @INC

push @INC, "/some/path";
none package.path
library path environment variable $ PERL5LIB=~/lib perl foo.pl TCLLIBPATH LUA_PATH
library path command line option $ perl -I ~/lib foo.pl
simple global identifiers none
multiple label identifiers all identifiers not declared with my
label separator Foo::Bar::baz(); :: .
namespace declaration package Foo;
require Exporter;
our @ISA = ("Exporter");
our @EXPORT_OK = qw(bar baz);
namespace module
child namespace declaration package Foo::Bar;
unqualified import of namespace # imports symbols in @EXPORT:
use Foo;
unqualified import of definitions # bar and baz must be in
# @EXPORT or @EXPORT_OK:

use Foo qw(bar baz);
list installed packaged, install a package $ perldoc perllocal
$ cpan -i Moose
objects
perl tcl lua groovy
define class package Int;

sub new {
  my $class = shift;
  my $v = $_[0] || 0;
  my $self = {value => $v};
  bless $self, $class;
  $self;
}

sub value {
  my $self = shift;
  if ( @_ > 0 ) {
    $self->{'value'} = shift;
  }
  $self->{'value'};
}
class Int {
  public int value
  Int (int n) {
    value = n
  }
}
create object my $i = new Int(); # or
my $i = Int->new();
o = new Int(3)
create blank object o = {}
instance variable visibility private; getters and setters must be explicitly defined
object literal o = {
  score=21,
  doubleScore=function(self)
    return 2*self.score
  end
}
set attribute
 
$i->value($v + 1); o.score = 21 o.value = 4
get attribute my $v = $i->value; if o.score == 21 then
  print("Blackjack!")
end
o.value
define method sub plus {
  my $self = shift;
  $self->value + $_[0];
}
function o.doubleScore(self)
  return 2 * self.score
end
invoke method $i->plus(7) print("Answer: " .. o:doubleScore())
handle undefined method invocation our $AUTOLOAD;

sub AUTOLOAD {
  my $self = shift;
  my $argc = scalar(@_);
  print "no def: $AUTOLOAD"
    . " arity: $argc\n";
}
define class method
invoke class method Counter->instances();
define class variable
get and set class variable
polymorphism
perl tcl lua groovy
subclass package Counter;

our @ISA = "Int";

my $instances = 0;

sub new {
  my $class = shift;
  my $self = Int->new(@_);
  $instances += 1;
  bless $self, $class;
  $self;
}

sub incr {
  my $self = shift;
  $self->value($self->value + 1);
}

sub instances {
  $instances;
}
reflection
perl tcl lua groovy
inspect type
 
ref([]) eq "ARRAY"

returns empty string if argument not a reference; returns package name for objects
type(o) o.class
o.getClass()
basic types SCALAR
ARRAY
HASH
CODE
REF
GLOB
LVALUE
FORMAT
IO
VSTRING
Regexp
inspect class ref($o) eq "Foo"
has method?
 
$o->can("reverse")
message passing for $i (0..10) {
  $meth = "phone$i";
  $o->$meth(undef);
}
eval
 
while(<>) {
  print ((eval), "\n");
}
assert(loadstring("x = 1+1"))()
list object methods "lorem".metaClass.methods
list object attributes keys %$o;
list loaded libraries # relative to directory in lib path:
keys %INC

# absolute path:
values %INC
list loaded namespaces grep { $_ =~ /::/ } keys %::
inspect namespace keys %URI::
pretty print use Data::Dumper;

%d = (lorem=>1, ipsum=>[2, 3]);

print Dumper(\%d);
source line number and file name __LINE__
__FILE__
command line documentation $ perldoc Math::Trig
net and web
perl tcl lua groovy
get local hostname, dns lookup, reverse dns lookup use Sys::Hostname;
use IO::Socket;

$host = hostname;
$ip = inet_ntoa(
  (gethostbyname(hostname))[4]);
$host2 = (gethostbyaddr(
    inet_aton("10.45.234.23"),
    AF_INET))[0];
http get use LWP::UserAgent;

$url = "http://www.google.com";
$r = HTTP::Request->new(GET=>$url);
$ua = LWP::UserAgent->new;
$resp = $ua->request($r);
my $s = $resp->content();
http post
absolute url
from base and relative url
use URI;

URI->new_abs("analytics",
  "http://google.com");
parse url use URI;

$url = "http://foo.com:80/baz?q=3#baz";
$up = URI->new($url);

$protocol = $up->scheme;
$hostname = $up->host;
$port = $up->port;
$path = $up->path;
$query_str = $up->query;
$fragment = $up->fragment;

# flat list of alternating keys and
# values:

@params = $up->query_form();
url encode/decode use CGI;

CGI::escape("lorem ipsum?")
CGI::unescape("lorem%20ipsum%3F")
base64 encode/decode use MIME::Base64;

open my $f, "<", "foo.png";
my $s = do { local $/; <$f> };
my $b64 = encode_base64($s);
my $s2 = decode_base64($b64);
unit tests
perl tcl lua groovy
test class # cpan -i Test::Class Test::More
package TestFoo;
use Test::Class;
use Test::More;
use base qw(Test::Class);

sub test_01 : Test {
  ok(1, "not true!");
}

1;
run tests, run test method $ cat TestFoo.t
use TestFoo;
Test::Class->runtests;

$ perl ./TestFoo.t
equality assertion my $s = "do re me";
is($s, "do re me");
approximate assertion
regex assertion my $s = "lorem ipsum";
like($s, qr/lorem/);
exception assertion use Test::Fatal;

ok(exception { 1 / 0 });
setup # in class TestFoo:
sub make_fixture : Test(setup) {
  print "setting up";
};
teardown # in class TestFoo:
sub teardown : Test(teardown) {
  print "tearing down";
};
debugging and profiling
perl tcl lua groovy
check syntax $ perl -c foo.pl
flags for stronger and strongest warnings $ perl -w foo.pl
$ perl -W foo.pl
lint $ perl MO=Lint foo.pl
debugger $ perl -d foo.pl
debugger commands h l n s b c T ?? ?? p q
benchmark code use Benchmark qw(:all);

$t = timeit(1_000_000, '$i += 1;');
print timestr($t);
profile code $ perl -d:DProf foo.pl
$ dprofpp
java interoperation
perl tcl lua groovy
______________________________________________ _____________________________________________ ______________________________________________ ______________________________________________

General

version used

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

show version

How to get the version.

perl:

Also available in the predefined variable $], or in a different format in $^V and $PERL_VERSION.

implicit prologue

Code which examples in the sheet assume to have already been executed.

perl:

We adopt the convention that if an example uses a variable without declaring it, it should be taken to have been previously declared with my.

Grammar and Invocation

interpreter

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

unix:

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

bash ~/configure.sh

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

~/configure.sh

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

groovy:

Groovy does not in general have # style comments, but one can be used on the first line to create a shebang script:

#!/usr/bin/env groovy

println "hello world!"

repl

The customary name of the repl.

perl:

The Perl REPL perl -de 0 does not save or display the result of an expression. perl -d is the Perl debugger and perl -e runs code provided on the command line.

perl -de 0 does not by default have readline, but it can be added:

$ cpan -i Term::ReadLine::Perl

  <cpan output omitted>

$ perl -de 0

  DB<1> use Term::ReadLine::Perl;

  DB<2> print 1 + 1;
2

command line program

How to pass in a program to the interpreter on the command line.

block delimiters

How blocks are delimited.

perl:

Curly brackets {} delimit blocks. They are also used for:

  • hash literal syntax which returns a reference to the hash: $rh = { 'true' => 1, 'false' => 0 }
  • hash value lookup: $h{'true'}, $rh->{'true'}
  • variable name delimiter: $s = "hello"; print "${s}goodbye";

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

lua:

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

statement separator

How the parser determines the end of a statement.

perl:

In a script statements are separated by semicolons and never by newlines. However, when using perl -de 0 a newline terminates the statement.

are expressions statements

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

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.

source code encoding

How to identify the character encoding for a source code file.

Setting the source code encoding makes it possible to safely use non-ASCII characters in string literals and regular expression literals.

end-of-line comment

How to make the remainder of the line a comment.

multiple line comment

How to comment out multiple lines.

tcl:

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

lua:

The double bracket notation [[ ]] is the syntax for a multiline string literal.

Variables and Expressions

local variable

How to declare a local variable.

perl:

Variables don't need to be declared unless use strict is in effect.

If not initialized, scalars are set to undef, arrays are set to an empty array, and hashes are set to an empty hash.

Perl can also declare variables with local. These replace the value of a global variable with the same name, if any, for the duration of the enclosing scope, after which the old value is restored.

regions which define local scope

A list of regions which define a lexical scope for the local variables they contain.

perl:

A local variable can be defined outside of any function definition or anonymous block, in which case the scope of the variable is the file containing the source code.

When a region which defines a scope is nested inside another, then the inner region has read and write access to local variables defined in the outer region.

Note that the blocks associated with the keywords if, unless, while, until, for, and foreach are anonymous blocks, and thus any my declarations in them create variables local to the block.

global variable

How to declare and access a global variable.

perl:

Undeclared variables, which are permitted unless use strict is in effect, are global. If use strict is in effect, a global can be declared at the top level of a package (i.e. outside any blocks or functions) with the our keyword. A variable declared with my inside a function will hide a global with the same name, if there is one.

constant

How to declare a constant.

assignment

How to assign a value to a variable.

perl:

Assignment operators have right precedence and evaluate to the right argument, so assignments can be chained:

$a = $b = 3;

parallel assignment

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

swap

How to swap the values in two variables.

compound assignment

Compound assignment operators mutate a variable, setting it to the value of an operation which takes the previous value of the variable as an argument.

increment and decrement

The C-style increment and decrement operators can be used to increment or decrement values. They return values and thus can be used in expressions. The prefix versions return the value in the variable after mutation, and the postfix version return the value before mutation.

perl:

The increment and decrement operators also work on strings. There are postfix versions of these operators which evaluate to the value before mutation:

$x = 1;
$x++;
$x--;

null

The null literal.

null test

How to test if a value is null.

perl:

$v == undef does not imply that $v is undef. Any comparison between undef and a falsehood will return true. The following comparisons are true:

$v = undef;
if ($v == undef) { print "true"; }

$v = 0;
if ($v == undef) { print "sadly true"; }

$v = '';
if ($v == undef) { print "sadly true"; }

tcl

Tcl has has no null value.

undefined variable access

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

perl:

Perl does not distinguish between unset variables and variables that have been set to undef. In Perl, calling defined($a) does not result in a error if $a is undefined, even with the strict pragma.

tcl:

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

expr ![info exists v]

lua:

There is no distinction between a variable being defined and a variable having a nil value. Assigning nil to a variable frees it.

conditional expression

How to write a conditional expression.

lua:

notes on Lua and the ternary operator

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.

perl:

&& and || have higher precedence than assignment, compound assignment, and the ternary operator (?:), which have higher precedence than and and or.

relational expressions

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

The available relational operators.

perl:

The operators: == != > < >= <= convert strings to numbers before performing a comparison. Many string evaluate as zero in a numeric context and are equal according to the == operator. To perform a lexicographic string comparison, use: eq, ne, gt, lt, ge, le.

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

min and max

How to find the min and max value in mix of values or variables.

three value comparison

Binary comparison operators which return -1, 0, or 1 depending upon whether the left argument is less than, equal to, or greater than the right argument.

The <=> symbol is called the spaceship operator.

arithmetic expression

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

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.

perl:

The integer pragma makes all arithmetic operations integer operations. Floating point numbers are truncated before they are used. Hence integer division could be performed with:

use integer;
my $a = 7 / 3;
no integer;

lua:

All Lua numbers are floating point.

integer division by zero

What happens when a float is divided by zero.

lua

As already noted there are no literals for inf and nan. Once could assign the correct values
to variables with the following code

inf = 1 / 0
nan = 0 / 0

inf can be compared to itself, but nan cannot. In other words:

# this prints 'true'
=(1 / 0) == (1 / 0)
# this prints 'false'
=(0 / 0) == (0 / 0)

float division

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

float division by zero

The result of dividing a float by zero.

power

How to compute exponentiation.

The examples calculate 2 to the 32 which is the number of distinct values that can be stored in 32 bits.

sqrt

How to get the square root of a number.

sqrt -1

The result of taking the square root of -1.

transcendental functions

Functions for computing the 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.

transcendental constants

Approximate values for π and e.

float truncation

Ways to convert a float to a nearby integer: towards zero; to the nearest integer; towards positive infinity; towards negative infinity.

perl:

The CPAN module Number::Format provides a round function. The 2nd argument specifies the number of digits to keep to the right of the radix. The default is 2.

use Number::Format 'round';

round(3.14, 0);

absolute value

How to get the absolute value of a 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.

rational construction

How to construct a rational number.

rational decomposition

How to decompose a rational number into a numerator and a denominator.

complex construction

How to construct a complex number.

complex decomposition

How to decompose a complex number into its real and imaginary part; how to get the polar decomposition of a complex number; how to get the complex conjugate.

random number

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

random seed

How to set the seed for the random number generator.

Setting the seed to a fixed number can be used for repeatable results.

bit operators

The available bit operators.

binary, octal, and hex literals

Binary, octal, and hex integer literals

radix

How to convert integers to strings of digits of a given base. How to convert such strings into integers.

perl:

Perl has the functions oct and hex which convert strings encoded in octal and hex and return the corresponding integer. The oct function will handle binary or hex encoded strings if they have "0b" or "0x" prefixes.

oct("60")
oct("060")
oct("0b101010")
oct("0x2a")

hex("2a")
hex("0x2a")

Strings

string literal

The syntax for a string literal.

perl:

When use strict is not in effect bareword strings are permitted.

Barewords are strings without quote delimiters. They are a feature of shells. Barewords cannot contain whitespace or any other character used by the tokenizer to distinguish words.

Before Perl 5 subroutines were invoked with an ampersand prefix & or the older do keyword. With Perl 5 neither is required, but this made it impossible to distinguish a bareword string from a subroutine without knowing all the subroutines which are in scope.

The following code illustrates the bareword ambiguity:

no strict;

print rich . "\n";  # prints "rich"; rich is a bareword string

sub rich { return "poor" }

print rich . "\n";  # prints "poor"; rich is now a subroutine

Perl allows custom delimiters to be used for single and double quoted strings. These can be used to avoid backslash escaping. If the left delimiter is (, [, or { the right delimiter must be ), ], or }, respectively.

my $s1 = q(lorem ipsum);
my $s2 = qq($s1 dolor sit amet);

newline in literal

Are newlines permitted in a string literal?

lua:

One can avoid backslashes by using the double bracket string notation. The following are equivalent:

s = "one\
two\
three"

s = [[one
two
three]]

literal escapes

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

perl:

In addition to the character escapes, Perl has the following translation escapes:

\u make next character uppercase
\l make next character lowercase
\U make following characters uppercase
\L make following characters lowercase
\Q backslash escape following nonalphanumeric characters
\E end \U, \L, or \Q section

When use charnames is in effect the \N escape sequence is available:

binmode(STDOUT, ':utf8');

use charnames ':full';

print "lambda: \N{GREEK SMALL LETTER LAMDA}\n";

use charnames ':short';

print "lambda: \N{greek:lamda}\n";

use charnames qw(greek);

print "lambda: \N{lamda}\n";

here document

Here documents are strings terminated by a custom identifier. They perform variable substitution and honor the same backslash escapes as double quoted strings.

perl:

Put the custom identifier in single quotes to prevent variable interpolation and backslash escape interpretation:

s = <<'EOF';
Perl code uses variables with dollar
signs, e.g. $var
EOF

variable interpolation

The syntax for interpolating variables into a string literal.

expression interpolation

Interpolating the result of evaluating an expression in a string literal.

concatenate

The string concatenation operator.

replicate

The string replication operator.

split

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.

lua:

how to split a string in Lua

join

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

sprintf

How to create a string using a printf style format.

case manipulation

trim

How to remove whitespace from the ends of a string.

perl:

An example of how to trim a string without installing a library:

$s = " lorem ";
$s =~ s/^\s*(.*)\s*$/\1/;

The return value of the =~ operator is boolean, indicating whether a match occurred. Also the left hand side of the =~ operator must be a scalar variable that can be modified. Using the =~ operator is necessarily imperative, unlike the Text::Trim functions which can be used in expressions.

pad

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.

groovy

Provide a second argument to set the pad character:

"lorem".padRight(10, '_')
"lorem".padLeft(10, '_')
"lorem.center(10, '_')

string to number

How to convert a string to a number.

perl:

Perl converts a scalar to the desired type automatically and does not raise an error if the string contains non-numeric data. If the start of the string is not numeric, the string evaluates to zero in a numeric context.

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]

lua:

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'

number to string

How to convert a number to a string.

lua:

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

(8).toString()
x = 7
x.toString()

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 Expressions

literal, custom delimited literal

The literal for a regular expression; the literal for a regular expression with a custom delimiter.

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]
\h horizontal whitespace character [ \t]
\H not a horizontal whitespace character [^ \t]
%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
\v vertical whitespace character [\r\n\f]
\V not a vertical whitespace character [^\r\n\f]
\w, %w alphanumeric character. \w also matches underscore
\W not a word character
\Z end of string
%z the null character (ASCII zero)

anchors

The supported anchors.

match test

How to test whether a regular expression matches a string.

groovy

The =~ operator succeeds if the regex matches part of the string. The ==~ succeeds only if the regular expression matches the entire string:

s = "it's 1999"

// true:
s =~ /1999/

// false:
s ==~ /1999/

case insensitive match test

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

modifiers

Available flags for modifying regular expression behavior.

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

substitution

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

perl:

The =~ operator performs the substitution in place on the string and returns the number of substitutions performed.

The g modifiers specifies that all occurrences should be replaced. If omitted, only the first occurrence is replaced.

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"

lua:

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)

match, prematch, postmatch

How to get the substring that matched the regular expression, as well as the part of the string before and after the matching substring.

perl:

The special variables $&, $`, and $' also contain the match, prematch, and postmatch.

group capture

How to get the substrings which matched a parenthesized portion of a regular expression.

named group capture

How to get the substrings which matched the parenthesized parts of a regular expression and put them into a dictionary.

For reference, we call the (?P<foo>...) notation Python-style and the (?<foo>...) notation Perl-style.

perl:

Perl 5.10 added support for both Python-style and Perl-style named groups.

backreference

How to use backreferences in a regex; how to use backreferences in the replacement string of substitution.

Perl uses and exposes the tm struct of the standard library. The first nine values of the struct (up to the member tm_isdst) are put into an array.

Date and Time

date/time type

The data type used to hold a combined date and time.

perl

Built in Perl functions work with either (1) scalars containing the Unix epoch as an integer or (2) arrays containing the first nine values of the standard C library tm struct. When use Time::Piece is in effect functions which work with tm arrays are replaced with variant that work with the Time::Piece wrapper.

The modules Time::Local and Date::Parse can create scalars containing the Unix epoch.

CPAN provides the DateTime module which provides objects with functionality comparable to the DateTime objects of PHP and Python.

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.

current unix epoch

strftime

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.

strptime

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

result of date subtraction

add time duration

local timezone

timezone name, offset from UTC, is daylight savings?

How to get time zone information: the name of the timezone, the offset in hours from UTC, and whether the timezone is currently in daylight savings.

Timezones are often identified by three or four letter abbreviations. As can be seen from the list, many of the abbreviations do not uniquely identify a timezone. Furthermore many of the timezones have been altered in the past. The Olson database (aka Tz database) decomposes the world into zones in which the local clocks have all been set to the same time since 1970 and it gives these zones unique names.

perl:

It is not necessary to create a DateTime object to get the local timezone offset:

use Time::Piece;

$t = localtime(time);
$offset_hrs = $t->tzoffset / 3600;

microseconds

sleep

How to sleep for half a second.

perl:

The Perl standard library includes a version of sleep which supports fractional seconds:

use Time::HiRes qw(sleep);

sleep 0.5;

timeout

Arrays

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

perl tcl lua groovy
array array, list list table java.util.ArrayList
dictionary hash array, dict table java.util.LinkedHashMap

perl:

Arrays are a data type. Lists are a context.

tcl:

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

lua:

Note that Lua uses the same data structure for arrays and dictionaries.

literal

Array literal syntax.

perl:

Square brackets create an array and return a reference to it:

$a = [1,2,3]

quote words

The quote words operator, which is a literal for arrays of strings where each string contains a single word.

size

How to get the number of elements in an array.

lua:

The # operator returns the index of a non-nil value in the array that is followed by a nil value. Unfortunately different Lua implementations behave differently when there are multiple such indices. In particular there is no guarantee that the index will be the index of the last non-nil value in the array.

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

lookup

How to access a value in an array by index.

perl:

A negative index refers to the length - index element.

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.

lua:

Lua arrays are indexed from one.

update

How to change the value stored in an array at given index.

out-of-bounds behavior

What happens when a lookup is performed on an out-of-bounds index.

index of element

How to get the first or last index containing a value.

perl:

Some techniques for getting the index of an array element.

slice

How to slice a subarray from an array.

perl:

Perl arrays can take an array of indices as the index value. The range of values selected can be discontinuous and the order of the values can be manipulated:

@nums = (1,2,3,4,5,6);                                                                                                                                                  
@nums[(1,3,2,4)];

slice to end

How to slice an array to the end

manipulate back

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

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.

concatenate

How to concatenate two arrays.

replicate

How to create an array consisting of n copies of a value.

copy

How to make an address copy, a shallow copy, and a deep copy of an array.

After an address copy is made, modifications to the copy also modify the original array.

After a shallow copy is made, the addition, removal, or replacement of elements in the copy does not modify of the original array. However, if elements in the copy are modified, those elements are also modified in the original array.

A deep copy is a recursive copy. The original array is copied and a deep copy is performed on all elements of the array. No change to the contents of the copy will modify the contents of the original array.

perl:

Taking a reference is customary way to make an address copy in Perl, but the Perl example is not equivalent to the other languages in that different syntax has to be used to access the original array and the address copy: @a and @$a1. To make @a1 and @a refer to the same array, use typeglobs:

*a1 = *a;

arrays as function arguments

How arrays are passed as arguments.

iterate over elements

How to iterate through the elements of an array.

perl:

for and foreach are synonyms. Some use for exclusively for C-style for loops and foreach for array iteration.

iterate over range

Iterate over a range without instantiating it as a list.

perl:

With Perl 5.005 the for and foreach operators were optimized to not instantiate a range argument as a list.

instantiate range as array

How to convert a range to an array.

reverse

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

sort

How to sort an array.

dedupe

How to remove extra occurrences of elements from an array.

membership

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.

intersection

How to compute an intersection.

union

How to compute the union of two arrays.

relative complement

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

map

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

None of the examples modify the source array.

lua:

map implementation

filter

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

None of the examples modify the source array.

lua:

filter implementation

reduce

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

None of the examples modify the source array.

lua:

reduce implementation

universal and existential tests

How to test whether all elements in an array satisfy a predicate; how to test whether at least one element in an array satisfies a predicate.

shuffle

How to shuffle an array.

zip

How to interleave arrays. In the case of two arrays the result is an array of pairs or an associative list.

perl:

zip expects arrays as arguments, which makes it difficult to define the arrays to be zipped on the same line as the invocation. It can be done like this:

@a = zip @{[1,2,3]}, @{['a','b','c']};

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
}

literal

The syntax for a dictionary literal.

perl:

Curly brackets create a hash and return a reference to it:

$h = { 'hello' => 5, 'goodbye' => 7 }

size

How to get the number of entries in a dictionary.

lookup

How to look up the value associated with a key.

perl:

Use the ampersand prefix @ to slice a Perl hash. The index is a list of keys.

%nums = ('b'=>1, 't'=>2, 'a'=>3);
@nums{('b','t')}

update

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.

delete

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

from array of pairs, from even length array

How to create a dictionary from an array of pairs; how to create a dictionary from an even length array.

merge

How to merge the values of two dictionaries.

In the examples, if the dictionaries d1 and {d2}} share keys then the values from d2 will be used in the merged dictionary.

invert

How to turn a dictionary into its inverse. If a key 'foo' is mapped to value 'bar' by a dictionary, then its inverse will map the key 'bar' to the value 'foo'. However, if multiple keys are mapped to the same value in the original dictionary, then some of the keys will be discarded in the inverse.

iteration

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

keys and values as arrays

How to convert the keys of a dictionary to an array; how to convert the values of a dictionary to an array.

sort by values

How to sort the data in a dictionary by its values.

default value, computed value

How to create a dictionary with a default value for missing keys; how to compute and store the value on lookup.

perl:

How to use a tied hash. If the CPAN module Tie::ExtraHash is installed there is a shorter way.

Functions

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.

define function

How to define a function.

perl:

One can also use shift to put the arguments into local variables:

sub add {
  my $a = shift;
  my $b = shift;

  $a + $b;
}

invoke function

How to invoke a function.

nested function

Can function definitions be nested; are nested functions visible outside of the function in which they are defined.

missing argument behavior

How incorrect number of arguments upon invocation are handled.

perl:

Perl collects all arguments into the @_ array, and subroutines normally don't declare the number of arguments they expect. However, this can be done with prototypes. Prototypes also provide a method for taking an array from the caller and giving a reference to the array to the callee.

extra argument behavior

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

default argument

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.

lua:

In version 5.1 and earlier the global variable arg was set automatically. In version 5.2 one must explicitly assign to a local array.

It is possible to get the number of arguments that were provided without assigning to a local array:

function foo(...)
  print('passed ' .. select('#', ...) .. ' arguments')
end

return value

How the return value of a function is determined.

multiple return values

lua:

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)
end
(roots(4))

anonymous function literal

How to define a lambda function.

invoke anonymous function

How to invoke a lambda function.

function as value

How to store a function in a variable and pass it as an argument.

function with private state

How to create a function with private state which persists between function invocations.

default scope

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

tcl:

Tcl variables inside functions have local scope.

Execution Control

if

The if statement.

perl:

When an if block is the last statement executed in a subroutine, the return value is the value of the branch that executed.

tcl:

Tcl also has a switch:

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

while

How to create a while loop.

perl:

Perl provides until, do-while, and do-until loops.

An until or a do-until loop can be replaced by a while or a do-while loop by negating the condition.

break and continue

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

for

How to create a C-style for loop.

lua:

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

for i = 0, 90, 10 do
  print(i)
end

raise exception

How to raise an exception.

catch exception

How to handle an exception.

finally/ensure

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.

tcl:

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

closure

How to create a first class function with access to the local variables of the local scope in which it was created.

generator

How to create and use a generator.

File Handles

print to standard output

tcl:

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.

close file

How to close a file handle.

read line

iterate over a file by line

chomp

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

Files

file exists test, file regular test

copy file, remove file, rename file

set file permissions

temporary file

Directories

Processes and Environment

command line arguments

How to access the command line arguments.

environment variable

How to access an environment variable.

exit

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.

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

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

Libraries and Namespaces

library

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.

namespace declaration

How to declare a namespace.

namespace separator

The separator used in namespace names.

list installed packages, install a package

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

Objects

define class

How to define a class.

create object

How to instantiate a class.

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.

instance variable visibility

object literal

The syntax for an object literal.

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.

handle undefined method invocation

define class method

invoke class method

define class variable

get and set class variable

Polymorphism

subclass

Reflection

inspect type

basic types

inspect class

has method?

message passing

eval

list object methods

list object attributes

list loaded libraries

list loaded namespaces

inspect namespace

pretty print

source line number and file name

command line documentation

Net and Web

get local hostname, dns lookup, reverse dns lookup

How to get the hostname and the ip address of the local machine without connecting to a socket.

The operating system should provide a method for determining the hostname. Linux provides the uname system call.

A DNS lookup can be performed to determine the IP address for the local machine. This may fail if the DNS server is unaware of the local machine or if the DNS server has incorrect information about the local host.

A reverse DNS lookup can be performed to find the hostname associated with an IP address. This may fail for the same reasons a forward DNS lookup might fail.

http get

How to make an HTTP GET request and read the response into a string.

http post

absolute url

How to construct an absolute URL from a base URL and a relative URL as documented in RFC 1808.

When constructing the absolute URL, the rightmost path component of the base URL is removed unless it ends with a slash /. The query string and fragment of the base URL are always removed.

If the relative URL starts with a slash / then the entire path of the base URL is removed.

If the relative URL starts with one or more occurrences of ../ then one or more path components are removed from the base URL.

The base URL and the relative URL will be joined by a single slash / in the absolute URL.

parse url

How to extract the protocol, host, port, path, query string, and fragment from a URL. How to extract the parameters from the query string.

url encode/decode

How to URL encode and URL unencode a string.

URL encoding, also called percent encoding, is described in RFC 3986. It replaces all characters except for the letters, digits, and a few punctuation marks with a percent sign followed by their two digit hex encoding. The characters which are not escaped are:

A-Z a-z 0-9 - _ . ~

URL encoding can be used to encode UTF-8, in which case each byte of a UTF-8 character is encoded separately.

When form data is sent from a browser to a server via an HTTP GET or an HTTP POST, the data is percent encoded but spaces are replaced by plus signs + instead of %20. The MIME type for form data is application/x-www-form-urlencoded.

base64 encode/decode

How to encode binary data in ASCII using the Base64 encoding scheme.

A popular Base64 encoding is the one defined by RFC 2045 for MIME. Every 3 bytes of input is mapped to 4 of these characters: [A-Za-z0-9/+].
If the input does not consist of a multiple of three characters, then the output is padded with one or two hyphens: =.

Whitespace can inserted freely into Base64 output; this is necessary to support transmission by email. When converting Base64 back to binary whitespace is ignored.

Unit Tests

test class

run tests, run test method

equality assertion

approximate assertion

regex assertion

exception assertion

setup

teardown

Debugging and Profiling

check syntax

flags for stronger and strongest warnings

lint

debugger

debugger commands

benchmark code

profile code

Java Interoperation

Perl

perldoc
core modules

The first character of a Perl variable $ @ % determines the type of value that can be stored in the variable: scalar, array, hash. Using an array variable @foo in a scalar context yields the size of the array, and assigning a scalar to an array will modify the array to contain a single element. $foo[0] accesses the first element of the array @foo, and $bar{'hello'} accesses the value stored under 'hello' in the hash %bar. $#foo is the index of the last element in the array @foo.

Scalars can store a string, integer, or float. If an operator is invoked on a scalar which contains an incorrect data type, perl will perform an implicit conversion to the correct data type: non-numeric strings evaluate to zero.

Scalars can also contain a reference to a variable, which can be created with a backslash: $baz = \@foo; The original value can be dereferenced with the correct prefix: @$baz. References are how perl creates complex data structures, such as arrays of hashes and arrays of arrays. If $baz contains a reference to an array, then $baz->[0] is the first element of the array. if $baz contains a reference to a hash, $baz->{'hello'} is the value indexed by 'hello'.

The literals for arrays and hashes are parens with comma separated elements. Hash literals must contain an even number of elements, and the => operator can be used in placed of a comma between a key and its value. Square brackets, e.g. [1, 2, 3], create an array and return a reference to it, and curly brackets, e.g. {'hello' => 5, 'bye' => 3} , create a hash and return a reference to it.

By default Perl variables are global. They can be made local to the containing block with the my keyword or the local keyword. my gives lexical scope, and local gives dynamic scope. Also by default, the perl interpreter creates a variable whenever it encounters a new variable name in the code. The use strict; pragma requires that all variables be declared with my, local, or our. The last is used to declare global variables.

Perl functions do not declare their arguments. Any arguments passed to the function are available in the @_ array, and the shift command will operate on this array if no argument is specified. An array passed as an argument is expanded: if the array contains 10 elements, the callee will have 10 arguments in its @_ array. A reference (passing \@foo instead of @foo) can be used to prevent this.

Some of Perl’s special variables:

  • $$: pid of the perl process
  • $0: name of the file containing the perl script (may be a full pathname)
  • $@: error message from last eval or require command
  • $& $` $’: what last regex matched, part of the string before and after the match
  • $1$9: what subpatterns in last regex matched

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.

Lua

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 cannot in general be used in the position of a statement. An expression can be converted to a statement and printed by preceding it with an equals sign:

> =1 + 1
2
> ="lorem ipsum"
lorem ipsum

There is no built-in pretty printer for tables. All numbers are stored as double precision floats. The table type can be used as both an array and a dictionary.

Groovy

User Guide

An interpreted Groovy script can be nothing more than a few top level statements which are executed in order. The Groovy interpreter handles providing an entry point class and main method, compiling the source to Java byte code, and launching the JVM.

$ cat > hello.groovy
s = "Hello, World!"
println(s)

$ groovy hello.groovy
Hello, World!

Groovy classes can be placed in their own files and compiled to Java byte code explicitly. The resulting .class files depend on the groovy.jar and the asm.jar but otherwise can be used like .class files compiled from Java source files.

$ cat > Greeting.groovy
class Greeting {
  void say(name) {
    println("Hello, ${name}!")
  }
}

$ cat > UseGreeting.java
public class UseGreeting {
  public static void main(String[] args) {
    Greeting g = new Greeting();
    g.say(args[0]);
  }
}

$ groovyc Greeting.groovy

$ javac UseGreeting.java

$ java -cp.:/PATH/TO/groovy-2.2.1.jar:/PATH/TO/asm-4.1.jar UseGreeting Fred
Hello, Fred!

All Groovy values have a Java type which can be inspected at runtime with the getClass() method.

A Groovy variable can optionally be declared to have a type. This places a constraint on the values which can be stored in the variable which is enforced at run time. The following code generates a org.codehaus.groovy.runtime.typehandling.GroovyCastException:

Integer i = 'foo'

Groovy does not use any of the Java primitive types directly: byte, short, int, long, float, double, boolean, char. Instead it used it uses the wrapper classes: Byte, Short, Integer, Long, Float, Double, Boolean, Char. Nevertheless it is still possible to use the primitive type in a variable declaration.

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