You are on page 1of 2

S p ng Language Node PHP Py hon Ruby Shee One Hype po yg o 07 05 2017

Hype po yg o
Scripting Languages I: Node.js, PHP, Python, Ruby (Sheet One)
a side-by-side reference sheet
sheet one: version | grammar and execution | variables and expressions | arithmetic and logic | strings | regexes | dates
and time | arrays | dictionaries | functions | execution control | exceptions | threads
sheet two: streams | asynchronous events | files | file formats | directories | processes and environment | option parsing |
libraries and namespaces | objects | inheritance and polymorphism | reflection | net and web | gui | databases | unit tests |
logging | debugging

version
node.js php python ruby
version used 6.3 7.0 3.5 2.3

show version $ node --version $ php --version $ python -V $ ruby --version


$ python --version
implicit
// npm install lodash # sudo apt install php-mbstring import os, re, sys none
prologue const _ = require('lodash');

grammar and execution


node.js php python ruby
interpreter $ node foo.js $ php -f foo.php $ python foo.py $ ruby foo.rb

repl $ node $ php -a $ python $ irb

command line $ node -e "console.log('hi!');" $ php -r 'echo "hi!\n";' $ python -c 'print("hi!")' $ ruby -e 'puts "hi!"'
program
block
{} {} : and offside rule {}
delimiters do end

; or newline
statement newline or ; newline or ;
newline not separator inside (), [], {}, "", '', or ;
separator after binary operator newlines not separators inside (), [], {}, triple newlines not separators inside (), [], {}, ``, '',
statements must be semicolon terminated inside {} quote literals, or after backslash: \ "", or after binary operator or backslash: \
newline sometimes not separator when following line
would not parse as a valid statement
Python 3 source is UTF-8 by default; Python 2 source Ruby 2.0 source is UTF-8 by default
source code source is always UTF-8 none is US-ASCII
encoding # -*- coding: utf-8 -*-
# -*- coding: us-ascii -*-
end-of-line
// comment // comment # comment # comment
comment # comment

multiple line use triple quote string literal: =begin


/* line /* comment line comment line
comment another line */ another line */ '''comment line another line
another line''' =end
variables and expressions
node.js php python ruby
// new in ES6:
let x = 1;
let y = 2, z = 3;
// older alternative to let:
var x = 1; # in function body: # in function body:
local variable $x = 1; x = 1 x = 1
// let local scope is nearest list($y, $z) = [2, 3]; y, z = 2, 3 y, z = 2, 3
// enclosing block; var local scope
// is nearest function body.
// var variables are visible to all code
// in the function body; even code
// preceding the var statement.
// outside any function body:
file scope let n = 1; none none none
variable
incrFileVar () { n++; }
$g = 1; g = 1 $g = 1
global.g = 1;
function incr_global() { def incr_global(): def incr_global
global variable global $g;
incrGlobal () { global.g++; } global g $g += 1
++$g; g += 1 end
}
constant // new in ES6 define("PI", 3.14); # uppercase identifiers # warning if capitalized
const PI = 3.14; # constant by convention # identifier is reassigned
const PI = 3.14; PI = 3.14 PI = 3.14
assignment # assignments can be chained
v = 1; $v = 1; # but otherwise don't return values: v = 1
v = 1
list($x, $y, $z) = [1 ,2, 3]; x, y, z = 1, 2, 3 x, y, z = 1, 2, 3
parallel # 3 is discarded: # raises ValueError: # 3 is discarded:
// new in ES6:
assignment let [x, y, z] = [1, 2, 3]; list($x, $y) = [1, 2, 3]; x, y = 1, 2, 3 x, y = 1, 2, 3
# $z set to NULL: # raises ValueError: # z set to nil:
list($x, $y, $z) = [1, 2]; x, y, z = 1, 2 x, y, z = 1, 2
swap // new in ES6: list($x, $y) = [$y, $x]; x, y = y, x x, y = y, x
[x, y] = [y, x];
compound # do not return values:
assignment += -= *= /= none %= += -= *= none /= %= **= += -= *= /= //= %= **= += -= *= /= none %= **=
+= .= none += *= += *=
arithmetic, none &= |= none &&= ||= ^=
string, logical, &= |= ^=
<<= >>= &= |= ^= <<= >>= &= |= ^= <<= >>= &= |= ^= <<= >>= &= |= ^=
bit
increment and let x = 1; $x = 1; x = 1
let y = ++x; $y = ++$x; none # x and y not mutated:
decrement y = x.succ
let z = --y; $z = --$y;
z = y.pred
null null NULL # case insensitive None nil

null test v === null is_null($v) v is None v == nil


! isset($v) v.nil?
undefined Evaluates as undefined
variable Evaluates as NULL raises NameError raises NameError
Use the triple equality === operator to test for
this value.
conditional
expression x > 0 ? x : -x $x > 0 ? $x : -$x x if x > 0 else -x x > 0 ? x : -x

arithmetic and logic


node.js php python ruby
true and false true false TRUE FALSE # case insensitive True False true false

falsehoods false null undefined '' 0 NaN FALSE NULL 0 0.0 "" "0" [] False None 0 0.0 '' [] {} false nil

logical && || ! && || !


operators && || ! lower precedence: and or not lower precedence:
and or xor and or not

relational === !== < > >= <=


== != or <> > < >= <= relational operators are chainable: == != > < >= <=
operators perform type coercion: no conversion: === !== == != > < >= <=
== !=
Math.min(1, 2, 3) min(1, 2, 3) min(1, 2, 3)
min and max Math.max(1, 2, 3) max(1, 2, 3) max(1, 2, 3) [1, 2, 3].min
$a = [1, 2, 3] [1, 2, 3].max
Math.min.apply(Math, [1, 2, 3]) min($a) min([1, 2, 3])
Math.max.apply(Math, [1, 2, 3]) max($a) max([1, 2, 3])
arithmetic
operators
addition,
+ - * / // %
subtraction, + - * / none % + - * / none % + - * x.fdiv(y) / %
multiplication, In Python 2, / performs integer division.
float division,
quotient,
remainder
integer division Math.floor(22 / 7) (int)(22 / 7) 22 // 7 22 / 7

divmod none none q, r = divmod(22, 7) q, r = 22.divmod(7)

integer division Returns Infinity, NaN, or -Infinity depending upon


sign of dividend. returns FALSE with warning raises ZeroDivisionError raises ZeroDivisionError
by zero
There are literals for Infinity and NaN.
22 / 7 22.to_f / 7
float division 22 / 7 22 / 7
# Python 2: 22.fdiv(7)
float(22) / 7
float division
by zero same behavior as for integers returns FALSE with warning raises ZeroDivisionError returns -Infinity, NaN, or Infinity

power Math.pow(2, 32) pow(2, 32) 2 ** 32 2 ** 32

import math include Math


sqrt Math.sqrt(2) sqrt(2)
math.sqrt(2) sqrt(2)
# raises ValueError:
import math Math.sqrt(-1) raises Math::DomainError unless
sqrt -1 math.sqrt(-1) require 'complex' is in effect.
NaN NaN
# returns complex float: (-1) ** 0.5 is (0+1.0i)
import cmath
cmath.sqrt(-1)
transcendental include Math
Math.exp Math.log Math.sin Math.cos Math.tan exp log sin cos tan asin acos atan atan2 from math import exp, log, \
functions Math.asin Math.acos Math.atan Math.atan2 sin, cos, tan, asin, acos, atan, atan2 exp log sin cos tan asin acos atan atan2
transcendental import math include Math
Math.PI M_PI M_E
constants Math.E
and e math.pi math.e PI E
import math
none (int)$x x.to_i
float truncation Math.round(3.1) round($x) int(x) x.round
Math.floor(3.1) ceil($x) int(round(x)) x.ceil
Math.ceil(3.1) floor($x) math.ceil(x) x.floor
math.floor(x)
absolute value Math.abs(-3) abs($x) abs(x) x.abs

integer
overflow all numbers are floats converted to float becomes arbitrary length integer of type long becomes arbitrary length integer of type Bignum

float overflow Infinity INF raises OverflowError Infinity

rational from fractions import Fraction


none none 22 / 7r
construction 22r / 7
x = Fraction(22, 7)
rational x.numerator (22 / 7r).numerator
decomposition none none
x.denominator (22 / 7r).denominator

complex
construction none none z = 1 + 1.414j z = 1 + 1.414i

complex
decomposition import cmath
real and (1 + 3i).real
imaginary z.real (1 + 3i).imag
component, none none z.imag (1 + 3i).arg
argument, cmath.phase(z) (1 + 3i).abs
absolute abs(z) (1 + 3i).conj
value, z.conjugate()
conjugate
random
number import random
Math.floor(Math.random() * 100) rand(0,99) rand(100)
uniform Math.random() lcg_value() random.randint(0, 99) rand
integer, none none random.random() none
uniform float, random.gauss(0, 1)
normal float
import random srand(17)
random seed srand(17);
set, get, none random.seed(17) seed = srand
restore none seed = random.getstate() srand(seed)
random.setstate(seed)
bit operators << >> & | ^ ~ << >> & | ^ ~ << >> & | ^ ~ << >> & | ^ ~

binary, octal, none 0b101010 0b101010 0b101010


and hex 052 // deprecated 052 0o52 # also 052 in Python 2 052
literals 0x2a 0x2a 0x2a 0x2a
radix
convert integer
(42).toString(7) base_convert("42", 10, 7); none 42.to_s(7)
to and from parseInt('60', 7) base_convert("60", 7, 10); int('60', 7) "60".to_i(7)
string with
radix
strings
node.js php python ruby
str
string type String # array of bytes: String
string # Python 2:
unicode
'don\'t say "no"'
"don't say \"no\""
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"'
# Python 2 (and Python 3): "don't " 'say "no"'
u'lorem'
u"ipsum"
// backquote literals only: 'first line # triple quote literals only: 'first line
newline in `first line second line' '''first line second line'
second line` second line'''
literal
"first line "first line
// Backslashes can be used to break second line" """first line second line"
// long strings. second line"""
double quoted: \newline \\ \' \" \a \b \f \n \r \t \v \ooo \xhh double quoted:
single and double quotes: \f \n \r \t \v \xhh \$ \" \\ \ooo \uhhhh \Uhhhhhhhh \a \b \cx \e \f \n \r \s \t \v \xhh \ooo \uhhhh
literal escapes \b \f \n \r \t \v \xhh \" \' \\ \u{hhhhh}
\uhhhh \u{hhhhh} single quoted: In Python 2, \u and \U only available in string
\' \\ literals with u prefix single quoted:
\' \\
$word = "amet"; word = "amet"
here $s = <<<EOF s = <<EOF
document none none
lorem ipsum lorem ipsum
dolor sit $word dolor sit #{word}
EOF; EOF
variable let count = 3; $count = 3; count = 3 count = 3
let item = 'ball'; $item = "ball"; item = 'ball' item = "ball"
interpolation print('{count} {item}s'.format(
let s = `${count} ${item}s`; echo "$count ${item}s\n"; puts "#{count} #{item}s"
**locals()))
expression `1 + 1 = ${1 + 1}` none '1 + 1 = {}'.format(1 + 1) "1 + 1 = #{1 + 1}"
interpolation
// None; use string concatenation. 'lorem %s %d %f' % ('ipsum', 13, 3.7)
format string // Evaluates to "12.35": $fmt = "lorem %s %d %f"; "lorem %s %d %f" % ["ipsum", 13, 3.7]
12.3456.toFixed(2) sprintf($fmt, "ipsum", 13, 3.7); fmt = 'lorem {0} {1} {2}'
fmt.format('ipsum', 13, 3.7)
$s = "bar"; s = "bar"
are strings no $s2 = $s; no s2 = s
mutable? # sets s to "baz"; s2 is unchanged: # sets s and s2 to "baz":
$s[2] = "z"; s[2] = "z"
s = "bar"
none $s2 = $s; none s2 = s.clone
copy string # s2 is not altered:
s[2] = "z"
s = 'Hello, ' s = "Hello, "
s2 = s + 'World!' s2 = s + "World!"
concatenate s = 'Hello, ' + 'World!'; $s = "Hello, ";
$s2 = $s . "World!"; # juxtaposition can be used to # juxtaposition can be used to
# concatenate literals: # concatenate literals:
s2 = 'Hello, ' "World!" s2 = "Hello, " 'World!'
replicate let hbar = _.repeat('-', 80); $hbar = str_repeat("-", 80); hbar = '-' * 80 hbar = "-" * 80

translate case 'lorem'.toUpperCase()


mb_strtoupper("lorem")
'lorem'.upper() "lorem".upcase
to upper, to mb_strtolower("LOREM")
'LOREM'.toLowerCase() # strtoupper/strtolower are ASCII only 'LOREM'.lower() "LOREM".downcase
lower
# ASCII only: import string
capitalize _.capitalize('lorem'); ucfirst(strtolower("lorem")) "lorem".capitalize
none ucwords(strtolower("lorem ipsum")) 'lorem'.capitalize() none
string, words # Unicode title case: string.capwords('lorem ipsum')
mb_convert_case("lorem ipsum", MB_CASE_TITLE)
trim ' lorem '.trim() trim(" lorem ") ' lorem '.strip() " lorem ".strip
both sides, ' lorem'.trimLeft() ltrim(" lorem") ' lorem'.lstrip() " lorem".lstrip
left, right 'lorem '.trimRight() rtrim("lorem ") 'lorem '.rstrip() "lorem ".rstrip
$s = "lorem";
pad _.padStart('lorem', 10) $delta = strlen($s) - mb_strlen($s); 'lorem'.ljust(10) "lorem".ljust(10)
on right, on _.padEnd('lorem', 10) str_pad($s, 10 + $delta) 'lorem'.rjust(10) "lorem".rjust(10)
left, centered _.pad('lorem', 10) str_pad("$s, 10 + $delta, " ", STR_PAD_LEFT) 'lorem'.center(10) "lorem".center(10)
str_pad($s, 10 + $delta, " ", STR_PAD_BOTH)
number to
string 'value: ' + 8 "value: " . 8 'value: ' + str(8) "value: " + 8.to_s

7 + parseInt('12;, 10) 7 + "12" 7 + int('12') 7 + "12".to_i


73.9 + parseFloat('.037') 73.9 + ".037" 73.9 + float('.037') 73.9 + ".037".to_f
string to
number // 12: # 12: # raises ValueError: # 12:
parseInt('12A') 0 + "12A" int('12A') "12A".to_i
// NaN: # 0: # raises ValueError: # 0:
parseInt('A') 0 + "A" int('A') "A".to_i
' '.join(['do', 're', 'mi', 'fa']) %w(do re mi fa).join(' ')
string join ['do', 're', 'mi'].join(' ') $a = ["do", "re", "mi", "fa"];
implode(" ", $a) # raises TypeError: # implicitly converted to strings:
' '.join([1, 2, 3]) [1, 2, 3].join(' ')
// [ 'do', 're', '', 'mi', '' ]: # [ "do", "re", "", "mi", "" ]: # ['do', 're', '', 'mi', '']: # ["do", "re", "", "mi"]:
split 'do re mi '.split(' ') explode(" ", "do re mi ") 'do re mi '.split(' ') "do re mi ".split(/ /)

// [ 'do', 're', 'mi', '' ]: # [ "do", "re", "mi", "" ]: # ['do', 're', 'mi']: # ["do", "re", "mi"]:
'do re mi '.split(/\s+/) preg_split('/\s+/', "do re mi ") 'do re mi '.split() "do re mi ".split
split in two 'do re mi fa'.split(/\s+/, 2) preg_split('/\s+/', "do re mi fa", 2) 'do re mi fa'.split(None, 1) "do re mi fa".split(/\s+/, 2)

split and keep none preg_split('/(\s+)/', "do re mi fa", re.split('(\s+)', 'do re mi fa') "do re mi fa".split(/(\s+)/)
delimiters NULL, PREG_SPLIT_DELIM_CAPTURE)
prefix and 'foobar'.startsWith('foo') 'foobar'.startswith('foo') 'foobar'.start_with?('foo')
suffix test 'foobar'.endsWith('bar') 'foobar'.endswith('bar') 'foobar'.end_with?('bar')
length 'lorem'.length mb_strlen("lorem") len('lorem') "lorem".length
# strlen() counts bytes "lorem".size
# raises ValueError if not found:
'do re re'.index('re')
index of # returns FALSE if not found: 'do re re'.rindex('re') # returns nil if not found:
// returns -1 if not found:
substring 'lorem ipsum'.indexOf('ipsum') mb_strpos("do re re", "re") "do re re".index("re")
first, last mb_strrpos("do re re", "re") # returns -1 if not found: "do re re".rindex("re")
'do re re'.find('re')
'do re re'.rfind('re')
extract
substring
by start and 'lorem ipsum'.substr(6, 5)
mb_substr("lorem ipsum", 6, 5) none "lorem ipsum"[6, 5]
length, by none none "lorem ipsum"[6..10]
'lorem ipsum'.substring(6, 11) none 'lorem ipsum'[6:11] "lorem ipsum"[6...11]
start and end,
by successive
starts
byte array bytes
Buffer string Array of Fixnum
type # In Python 2, str also byte array type
byte array to let a = Buffer.from([0xce, 0xbb]); strings are byte arrays s = b'\xce\xbb'.decode('utf-8') a = "\u03bb".bytes
string let s = a.toString('utf-8'); s = a.pack("C*").force_encoding('utf-8')
a = '\u03bb'.encode('utf-8')
string to byte a = Buffer.from('\u03bb') strings are byte arrays a = "\u03bb".bytes
array # Python 2:
a = u'\u03bb'.encode('utf-8')
character mb_substr("lorem ipsum", 6, 1)
'lorem ipsum'[6] # byte lookup: 'lorem ipsum'[6] "lorem ipsum"[6]
lookup "lorem ipsum"[6]
chr and ord String.fromCharCode(65) # ASCII only: chr(65) 65.chr('UTF-8')
'A'.charCodeAt(0) chr(65) ord('A') "A".ord
ord("A")
to array of
characters 'abcd'.split('') str_split("abcd") list('abcd') "abcd".split("")

from string import ascii_lowercase


translate $ins = implode(range("a", "z"));
none $outs = substr($ins, 13, 13) . ins = ascii_lowercase "hello".tr("a-z", "n-za-m")
characters substr($ins, 0, 13); outs = ins[13:] + ins[:13]
strtr("hello", $ins, $outs) table = str.maketrans(ins, outs)
'hello'.translate(table)
delete $vowels = str_split("aeiou"); table = {ord(ch): None for ch in "aeiou"}
none $s = "disemvowel me"; "disemvowel me".translate(table) "disemvowel me".delete("aeiou")
characters $s = str_replace($vowels, "", $s);
squeeze none $s = "too much space"; re.sub('(\s)+', r'\1', "too much space".squeeze(" ")
characters $s = = preg_replace('/(\s)+/', '\1', $s); 'too much space')
regular expressions
node.js php python ruby
literal, custom /lorem|ipsum/
/lorem|ipsum/ '/lorem|ipsum/' re.compile(r'lorem|ipsum') %r(/etc/hosts)
delimited '(/etc/hosts)' none # double quoted string escapes
literal # and #{} substitution can be used
. [^\n] . [^\n] with re.S modifier matches all chars . [^\n] with m modifier matches all chars
. [^\n] \d [0-9] \d [0-9] \d [0-9]
\d [0-9] \D [^0-9] \D [^0-9] \D [^0-9]
ascii character \D [^0-9] \h [ \t] \s [ \t\r\n\f] \h [0-9a-fA-F]
\s [ \t\r\n\f] \H [^ \t] \S [^ \t\r\n\f] \H [^0-9a-fA-F]
class \w [A-Za-z0-9_]
abbreviations \S [^ \t\r\n\f] \s [ \t\r\n\f] \s [ \t\r\n\f]
\w [A-Za-z0-9_] \S [^ \t\r\n\f] \W [^A-Za-z0-9_] \S [^ \t\r\n\f]
\W [^A-Za-z0-9_] \w [A-Za-z0-9_] \w [A-Za-z0-9_]
\W [^A-Za-z0-9_] In Python 3, the above definitions are used when \W [^A-Za-z0-9_]
re.A is in effect.
. [^\n] with re.S modifier matches all chars .
\d [Nd] Nd: Number, decimal digit \p{Digit}
\D [^Nd] \p{^Digit}
unicode POSIX character classes such as [[:alpha:]] are \s [Z\t\n\r\f\v\x1c\x1d\x1e\x1f\x85] \p{Space}
character available, but they match sets of ASCII characters. \S [^Z\t\n\r\f\v\x1c\x1d\x1e\x1f\x85] \p{^Space}
none General category values (e.g. \p{L}, \p{Lu}) can be \w [LN_] L: Letter; N: Number \p{Word}
class used. Morever, they can be used inside character \p{^Word}
abbreviations \W [^LN_]
classes (.e.g. [\p{L}\p{N}]).
In Python 2, the above definitions are used when POSIX character classes (e.g. [[:alpha:]]), general
re.U is in effect. category values (e.g. \p{L}, \p{Lu}), and script
names (e.g. \p{Greek}) also supported.
^ start of string or line with m modifier ^ start of string or line with re.M ^ start of line
^ start of string or line with m modifier $ end of string or line with m modifier $ end of string or line with re.M $ end of line
anchors $ end of string or line with m modifier \A start of string \A start of string \A start of string
\b word boundary: \w\W or \W\w \b word boundary: \w\W or \W\w \b word boundary: \w\W or \W\w \b unicode-aware word boundary
\B non word boundary \B non word boundary \B non word boundary \B unicode-aware non word boundary
\z end of string \Z end of string \z end of string
\Z end of string, excluding final newline \Z end of string, excluding final newline
match test if (s.match(/1999/)) { if (preg_match('/1999/', $s)) { if re.search('1999', s): if /1999/.match(s)
console.log('party!'); echo "party!\n"; print('party!') puts "party!"
} } end
case
insensitive 'Lorem'.match(/lorem/i) preg_match('/lorem/i', "Lorem") re.search('lorem', 'Lorem', re.I) /lorem/i.match("Lorem")
match test

g used for global substitution and scanning i make case insensitive re.A change meaning of \b \B \d \D \s \S \w \W i make case insensitive
modifiers i make case insensitive m change meaning of ^ and $ re.I make case insensitive o interpolate #{} in literal once
m change meaning of ^ and $ s change meaning of . re.M change meaning of ^ and $ m change meaning of .
u \u{} syntax and astral character support x ignore whitespace outside char class re.S change meaning of . x ignore whitespace outside char class
y used to scan in loop re.X ignore whitespace outside char class
substitution s = 'do re mi mi mi'; $s = "do re mi mi mi"; s = 'do re mi mi mi' s = "do re mi mi mi"
s.replace(/mi/g, 'ma'); $s = preg_replace('/mi/', "ma", $s); s = re.compile('mi').sub('ma', s) s.gsub!(/mi/, "ma")

m = /\d{4}/.exec(s); m = re.search('\d{4}', s) m = /\d{4}/.match(s)


match, if (m) { if m: if m
prematch, match = m[0]; none match = m.group() match = m[0]
postmatch // no prematch or postmatch prematch = s[0:m.start(0)] prematch = m.pre_match
} postmatch = s[m.end(0):len(s)] postmatch = m.post_match
end
rx = /^(\d{4})-(\d{2})-(\d{2})$/; $s = "2010-06-03";
group capture m = rx.exec('2009-06-03'); $rx = '/(\d{4})-(\d{2})-(\d{2})/'; rx = '(\d{4})-(\d{2})-(\d{2})' rx = /(\d{4})-(\d{2})-(\d{2})/
yr = m[1]; preg_match($rx, $s, $m); m = re.search(rx, '2010-06-03') m = rx.match("2010-06-03")
mo = m[2]; list($_, $yr, $mo, $dy) = $m; yr, mo, dy = m.groups() yr, mo, dy = m[1..3]
dy = m[3];
$s = "foo.txt"; rx = '^(?P<file>.+)\.(?P<suffix>.+)$' rx = /^(?<file>.+)\.(?<suffix>.+)$/
$rx = '/^(?P<file>.+)\.(?P<suffix>.+)$/'; m = re.search(rx, 'foo.txt') m = rx.match('foo.txt')
named group none preg_match($rx, $s, $m);
capture m.groupdict()['file'] m["file"]
$m["file"] m.groupdict()['suffix'] m["suffix"]
$m["suffix"]
scan $s = "dolor sit amet"; s = 'dolor sit amet'
let a = 'dolor sit amet'.match(/\w+/g); preg_match_all('/\w+/', $s, $m); a = re.findall('\w+', s) a = "dolor sit amet".scan(/\w+/)
$a = $m[0];
preg_match('/(\w+) \1/', "do do") none
backreference /(\w+) \1/.exec('do do') /(\w+) \1/.match("do do")
in match and $s = "do re"; rx = re.compile('(\w+) (\w+)')
substitution 'do re'.replace(/(\w+) (\w+)/, '$2 $1') $rx = '/(\w+) (\w+)/'; rx.sub(r'\2 \1', 'do re') "do re".sub(/(\w+) (\w+)/, '\2 \1')
$s = preg_replace($rx, '\2 \1', $s);
recursive
regex none '/\(([^()]*|($R))\)/' none /(?<foo>\(([^()]*|\g<foo>)*\))/

dates and time


node.js php python ruby
broken-down
datetime type Date DateTime datetime.datetime Time

$t = new DateTime("now"); import datetime


current let t = new Date(); $utc_tmz = new DateTimeZone("UTC"); t = Time.now
datetime $utc = new DateTime("now", $utc_tmz); t = datetime.datetime.now() utc = Time.now.utc
utc = datetime.datetime.utcnow()
import datetime
current unix (new Date()).getTime() / 1000 $epoch = time(); epoch = Time.now.to_i
epoch t = datetime.datetime.now()
epoch = int(t.strftime("%s"))
broken-down from datetime import datetime as dt
datetime to Math.round(t.getTime() / 1000) $epoch = $t->getTimestamp(); epoch = t.to_i
unix epoch epoch = int(t.strftime("%s"))
unix epoch to let epoch = 1315716177; $t2 = new DateTime();
broken-down t = dt.fromtimestamp(1304442000) t = Time.at(1304442000)
let t2 = new Date(epoch * 1000); $t2->setTimestamp(1304442000);
datetime
// npm install moment
let moment = require('moment'); strftime("%Y-%m-%d %H:%M:%S", $epoch);
format date("Y-m-d H:i:s", $epoch); t.strftime('%Y-%m-%d %H:%M:%S') t.strftime("%Y-%m-%d %H:%M:%S")
datetime let t = moment(new Date()); $t->format("Y-m-d H:i:s");
let fmt = 'YYYY-MM-DD HH:mm:ss';
console.log(t.format(fmt));
// npm install moment from datetime import datetime require 'date'
let moment = require('moment'); $fmt = "Y-m-d H:i:s";
parse $s = "2011-05-03 10:00:00"; s = '2011-05-03 10:00:00' s = "2011-05-03 10:00:00"
datetime let fmt = 'YYYY-MM-DD HH:mm:ss'; $t = DateTime::createFromFormat($fmt, fmt = '%Y-%m-%d %H:%M:%S' fmt = "%Y-%m-%d %H:%M:%S"
let s = '2011-05-03 10:00:00'; $s); t = datetime.strptime(s, fmt) t = DateTime.strptime(s, fmt).to_time
let t = moment(s, fmt);
# pip install python-dateutil require 'date'
parse import dateutil.parser
datetime w/o let t = new Date('July 7, 1999'); $epoch = strtotime("July 7, 1999"); s = "July 7, 1999"
format s = 'July 7, 1999' t = Date.parse(s).to_time
t = dateutil.parser.parse(s)
t.getFullYear() (int)$t->format("Y") t.year t.year
date parts t.getMonth() + 1 (int)$t->format("m") t.month t.month
t.getDate() // getDay() is day of week (int)$t->format("d") t.day t.day
t.getHours() (int)$t->format("H") t.hour t.hour
time parts t.getMinutes() (int)$t->format("i") t.minute t.min
t.getSeconds() (int)$t->format("s") t.second t.sec
let yr = 1999; import datetime
let mo = 9; yr = 1999
let dy = 10; yr = 1999 mo = 9
build broken- let hr = 23; mo = 9 dy = 10
let mi = 30; dy = 10 hr = 23
down datetime hr = 23 mi = 30
let ss = 0;
let t = new Date(yr, mo - 1, dy, mi = 30 ss = 0
hr, mi, ss); ss = 0 t = Time.new(yr, mo, dy, hr, mi, ss)
t = datetime.datetime(yr, mo, dy, hr, mi, ss)
# DateInterval object if diff method used:
$fmt = "Y-m-d H:i:s"; datetime.timedelta object
datetime number containing time difference in milliseconds $s = "2011-05-03 10:00:00"; Float containing time difference in seconds
subtraction $then = DateTime::createFromFormat($fmt, $s); use total_seconds() method to convert to float
$now = new DateTime("now"); representing difference in seconds
$interval = $now->diff($then);
import datetime require 'date/delta'
let t1 = new Date();
let delta = (10 * 60 + 3) * 1000; $now = new DateTime("now"); delta = datetime.timedelta( s = "10 min, 3 s"
add duration $now->add(new DateInterval("PT10M3S"); minutes=10,
let t2 = new Date(t1.getTime() + delta); delta = Date::Delta.parse(s).in_secs
seconds=3) t = Time.now + delta
t = datetime.datetime.now() + delta
# DateTime objects can be instantiated
local time # without specifying the time zone a datetime object has no time zone information if no time zone is specified the local time zone is
zone TZ environment variable or host time zone # if a default is set: unless a tzinfo object is provided when it is used
determination $s = "America/Los_Angeles"; created
date_default_timezone_set($s);
# pip install pytz
import pytz
import datetime # gem install tzinfo
require 'tzinfo'
nonlocal time tmz = pytz.timezone('Asia/Tokyo')
zone utc = datetime.datetime.utcnow() tmz = TZInfo::Timezone.get("Asia/Tokyo")
utc_dt = datetime.datetime( jp_time = tmz.utc_to_local(Time.now.utc)
*utc.timetuple()[0:5],
tzinfo=pytz.utc)
jp_dt = utc_dt.astimezone(tmz)
import time
time zone info $tmz = date_timezone_get($t);
tm = time.localtime() t.zone
name and timezone_name_get($tmz); t.utc_offset / 3600
UTC offset date_offset_get($t) / 3600; time.tzname[tm.tm_isdst]
(time.timezone / -3600) + tm.tm_isdst
// npm install moment import time
daylight let moment = require('moment');
$t->format("I"); tm = time.localtime() t.dst?
savings test
moment(new Date()).isDST()
tm.tm_isdst
t.getMilliseconds() * 1000
list($frac, $sec) = explode(" ", microtime()); t.microsecond t.usec
microseconds // [sec, nanosec] since system boot: $usec = $frac * 1000 * 1000;
process.hrtime()
arrays
node.js php python ruby
$a = [1, 2, 3, 4]; a = [1, 2, 3, 4]
literal a = [1, 2, 3, 4] a = [1, 2, 3, 4]
# older syntax: # a = ['do', 're', 'mi']
$a = array(1, 2, 3, 4); a = %w(do re mi)
size a.length count($a) len(a) a.size
a.length
empty test // TypeError if a is null or undefined: # NULL tests as empty: # None tests as empty: # NoMethodError if a is nil:
a.length === 0 !$a not a a.empty?
$a[0] a[0] a[0]
lookup
a[0] # PHP uses the same type for arrays and # returns last element: # returns last element:
# dictionaries; indices can be negative a[-1] a[-1]
# integers or strings
update a[0] = 'lorem' $a[0] = "lorem"; a[0] = 'lorem' a[0] = "lorem"

$a = []; a = [] a = []
out-of-bounds # evaluates as NULL: # raises IndexError: # evaluates as nil:
returns undefined $a[10]; a[10] a[10]
behavior # increases array size to one: # raises IndexError: # increases array size to 11:
$a[10] = "lorem"; a[10] = 'lorem' a[10] = "lorem"
element index $a = ["x", "y", "y", "z"]; a = ['x', 'y', 'y', 'z'] a = %w(x y y z)
// return -1 if not found:
[6, 7, 7, 8].indexOf(7) # returns FALSE if not found: # raises ValueError if not found: # return nil if not found:
first and last [6, 7, 7, 8].lastIndexOf(7) $i = array_search("y", $a, TRUE); a.index('y') a.index('y')
occurrence none none a.rindex('y')
slice
// select 3rd and 4th elements: # select 3rd and 4th elements: # select 3rd and 4th elements: # select 3rd and 4th elements:
by endpoints, ['a', 'b', 'c', 'd'].slice(2, 4) none a[2:4] a[2..3]
by length none array_slice($a, 2, 2) a[2:2 + 2] a[2, 2]

slice to end ['a', 'b', 'c', 'd'].slice(1) array_slice($a, 1) a[1:] a[1..-1]

manipulate a = [6, 7, 8]; $a = [6, 7, 8]; a = [6, 7, 8] a = [6, 7, 8]


a.push(9); array_push($a, 9); a.append(9) a.push(9)
back $a[] = 9; # same as array_push a << 9 # same as push
i = a.pop(); a.pop()
array_pop($a); a.pop
manipulate a = [6, 7, 8]; $a = [6, 7, 8]; a = [6, 7, 8] a = [6, 7, 8]
front a.unshift(5); array_unshift($a, 5); a.insert(0, 5) a.unshift(5)
i = a.shift(); array_shift($a); a.pop(0) a.shift
$a = [1, 2, 3]; a = [1, 2, 3] a = [1, 2, 3]
concatenate a = [1, 2, 3].concat([4, 5, 6]); $a2 = array_merge($a, [4, 5, 6]); a2 = a + [4, 5, 6] a2 = a + [4, 5, 6]
$a = array_merge($a, [4, 5, 6]); a.extend([4, 5, 6]) a.concat([4, 5, 6])
Array(10).fill(null) $a = array_fill(0, 10, NULL); a = [None] * 10 a = [nil] * 10
replicate a = [None for i in range(0, 10)] a = Array.new(10, nil)
import copy
copy a = [1, 2, [3, 4]]; $a = [1, 2, [3, 4]]; a = [1,2,[3,4]]
address copy, a2 = a; $a2 =& $a; a = [1,2,[3,4]] a2 = a
shallow copy, a3 = a.slice(0); none a2 = a a3 = a.dup
deep copy a4 = JSON.parse(JSON.stringify(a)); $a4 = $a; a3 = list(a) a4 = Marshal.load(Marshal.dump(a))
a4 = copy.deepcopy(a)
array as
function parameter contains address copy parameter contains deep copy parameter contains address copy parameter contains address copy
argument
[6, 7, 8].forEach((n) => {
console.log(n);
iterate over }); foreach ([1, 2, 3] as $i) {
echo "$i\n"; for i in [1, 2, 3]: [1, 2, 3].each { |i| puts i }
elements // new in ES6: print(i)
}
for (let n of [6, 7, 8]) {
console.log(n);
}
for (let i = 0; i < a.length; ++i) {
console.log(a[i]);
iterate over } $a = ["do", "re", "mi" "fa"]; a = ['do', 're', 'mi', 'fa'] a = %w(do re mi fa)
foreach ($a as $i => $s) { for i, s in enumerate(a): a.each_with_index do |s, i|
indices and // indices not guaranteed to be in order: echo "$s at index $i\n"; puts "#{s} at index #{i}"
elements print('%s at index %d' % (s, i))
for (let i in a) { } end
console.log(a[i]);
}
iterate over # use range() in Python 3: (1..1_000_000).each do |i|
not space efficient; use C-style for loop not space efficient; use C-style for loop for i in xrange(1, 1000001): code
range code end
instantiate a = range(1, 11)
let a = _.range(1, 11); $a = range(1, 10); Python 3: a = (1..10).to_a
range as array a = list(range(1, 11))
reverse let a = [1, 2, 3]; $a = [1, 2, 3]; a = [1, 2, 3] a = [1, 2, 3]
non-
destructive, in- let a2 = a.slice(0).reverse(); array_reverse($a); a[::-1] a.reverse
place a.reverse(); $a = array_reverse($a); a.reverse() a.reverse!
sort a = ['b', 'A', 'a', 'B'] a = %w(b A a B)
non- let a = [3, 1, 4, 2]; $a = ["b", "A", "a", "B"];
destructive, sorted(a) a.sort
let a2 = a.slice(0).sort(); none a.sort() a.sort!
in-place, sort($a); # custom binary comparision a.sort do |x, y|
custom a.sort();
none, but usort sorts in place # removed from Python 3: x.downcase <=> y.downcase
comparision a.sort(key=str.lower) end
dedupe let a = [1, 2, 2, 3]; $a = [1, 2, 2, 3]; a = [1, 2, 2, 3] a = [1, 2, 2, 3]
non-
destructive, in- let a2 = _.uniq(a); $a2 = array_unique($a); a2 = list(set(a)) a2 = a.uniq
place a = _.uniq(a); $a = array_unique($a); a = list(set(a)) a.uniq!
membership a.includes(7) in_array(7, $a) 7 in a a.include?(7)

intersection $a = [1, 2];


_.intersection([1, 2], [2, 3, 4]) $b = [2, 3, 4] {1, 2} & {2, 3, 4} [1, 2] & [2 ,3, 4]
array_intersect($a, $b)
union $a1 = [1, 2];
_.union([1, 2], [2, 3, 4]) $a2 = [2, 3, 4]; {1, 2} | {2, 3, 4} [1, 2] | [2, 3, 4]
array_unique(array_merge($a1, $a2))
relative $a1 = [1, 2, 3]; require 'set'
complement, _.difference([1, 2, 3], [2]) $a2 = [2]; {1, 2, 3} - {2}
symmetric none array_values(array_diff($a1, $a2)) {1, 2} ^ {2, 3, 4} [1, 2, 3] - [2]
difference none Set[1, 2] ^ Set[2 ,3, 4]

map // callback gets 3 args: array_map(function ($x) { map(lambda x: x * x, [1, 2, 3])


// value, index, array return $x * $x; # or use list comprehension: [1, 2, 3].map { |o| o * o }
a.map((x) => x * x) }, [1, 2, 3]) [x * x for x in [1, 2, 3]]
array_filter([1, 2, 3], filter(lambda x: x > 1, [1, 2, 3])
filter a.filter((x) => x > 1) function ($x) { # or use list comprehension: [1, 2, 3].select { |o| o > 1 }
return $x>1; [x for x in [1, 2, 3] if x > 1]
})
array_reduce([1, 2, 3], # import needed in Python 3 only
reduce a.reduce((m, o) => m + o, 0) function($x,$y) { from functools import reduce [1, 2, 3].inject(0) { |m, o| m + o }
return $x + $y;
}, 0) reduce(lambda x, y: x + y, [1, 2, 3], 0)
universal and let a = [1, 2, 3, 4];
existential use array_filter all(i % 2 == 0 for i in [1, 2, 3, 4]) [1, 2, 3, 4].all? {|i| i.even? }
tests a.every((n) => n % 2 === 0) any(i % 2 == 0 for i in [1, 2, 3, 4]) [1, 2, 3, 4].any? {|i| i.even? }
a.some((n) => n % 2 === 0)

let a = [1, 2, 3, 4]; $a = [1, 2, 3, 4]; from random import shuffle, sample
shuffle and a = [1, 2, 3, 4]
[1, 2, 3, 4].shuffle!
sample a = _.shuffle(a); shuffle($a); samp = [1, 2, 3, 4].sample(2)
let samp = _.sampleSize([1, 2, 3, 4], 2); $samp = array_rand(|[1, 2, 3, 4], 2); shuffle(a)
samp = sample([1, 2, 3, 4], 2)
flatten let a = [1, [2, [3, 4]]]; a = [1, [2, [3, 4]]]
one level, none none a2 = a.flatten(1)
let a2 = _.flatten(a); a3 = a.flatten
completely let a3 = _.flattenDeep(a);
let a = _.zip([1, 2, 3], ['a', 'b', 'c']); $a = array_map(NULL, list(zip([1, 2, 3], ['a', 'b', 'c'])) [1, 2, 3].zip(["a", "b", "c"])
zip [1, 2, 3],
// shorter array padded with undefined: ["a", "b", "c"]); # extras in longer array dropped: # shorter array padded with nil:
_.zip([1, 2, 3], ['a', 'b']) list(zip([1, 2, 3], ['a', 'b'])) [1, 2, 3].zip(["a", "b"])
# shorter array padded with NULLs
dictionaries
node.js php python ruby
d = {t: 1, f: 0}; $d = ["t" => 1, "f" => 0]; d = {'t' => 1, 'f' => 0}
literal // keys do not need to be quoted if they d = {'t': 1, 'f': 0}
// are a legal JavaScript variable name # older syntax: # keys are symbols:
// and not a reserved word $d = array("t" => 1, "f" => 0); symbol_to_int = {t: 1, f: 0}
size _.size(d) count($d) len(d) d.size
Object.getOwnPropertyNames(d).length d.length
d.hasOwnProperty("t") ? d["t"] : undefined
lookup d.hasOwnProperty("t") ? d.t : undefined
$d["t"] d['t'] d['t']
// JavaScript dictionaries are objects
// and inherit properties from Object.
d['t'] = 2
d['t'] = 2; $d["t"] = 2; d['t'] = 2
update d.t = 2; # provide default to avoid KeyError:
d.get('t', None)
let d = {}; $d = []; d = {} d = {}
missing key // undefined: # NULL: # raises KeyError: # nil:
behavior d["lorem"]; $d["lorem"]; d['lorem'] d['lorem']
// adds key/value pair: # adds key/value pair: # adds key/value pair: # adds key/value pair:
d["lorem"] = "ipsum"; $d["lorem"] = "ipsum"; d['lorem'] = 'ipsum' d['lorem'] = 'ipsum'
is key present d.hasOwnProperty("t"); array_key_exists("y", $d); 'y' in d d.key?('y')

delete d["t"]; $d = [1 => "t", 0 => "f"]; d = {1: True, 0: False} d = {1 => true, 0 => false}
delete delete d.t; unset($d[1]); del d[1] d.delete(1)
from array of let a = [['a', 1], ['b', 2], ['c', 3]]; a = [['a', 1], ['b', 2], ['c', 3]] a = [['a', 1], ['b', 2], ['c', 3]]
pairs, from let d = _.fromPairs(a); d = dict(a) d = Hash[a]
even length a = ['a', 1, 'b', 2, 'c', 3] a = ['a', 1, 'b', 2, 'c', 3]
array none
d = dict(zip(a[::2], a[1::2])) d = Hash[*a]
let d1 = {a: 1, b: 2}; $d1 = ["a" => 1, "b" => 2]; d1 = {'a': 1, 'b': 2} d1 = {'a' => 1, 'b' => 2}
let d2 = {b: 3, c: 4}; $d2 = ["b" => 3, "c" => 4]; d2 = {'b': 3, 'c': 4} d2 = {'b' => 3, 'c' => 4}
merge // d2 overwrites shared keys in d1: $d1 = array_merge($d1, $d2); d1.update(d2) d1.merge!(d2)
d1 = _.assignIn(d1, d2);
to_num = {'t': 1, 'f': 0}
let let2num = {t: 1, f: 0}; $to_num = ["t" => 1, "f" => 0]; # dict comprehensions added in 2.7: to_num = {'t' => 1, 'f' => 0}
invert let num2let = _.invert(let2num); $to_let = array_flip($to_num); to_let = {v: k for k, v to_let = to_num.invert
in to_num.items()}
for (let k in d) { foreach ($d as $k => $v) { for k, v in d.items(): d.each do |k,v|
iterate console.log(`value at ${k} is ${d[k]}`); echo "value at ${k} is ${v}"; print('value at {} is {}'.format(k, v) puts "value at #{k} is #{v}"
} } end
# Python 2: use iteritems()
list(d.keys())
keys and Object.keys(d) array_keys($d) list(d.values()) d.keys
values as _.values(d) array_values($d) d.values
arrays # keys() and values return iterators
# in Python 3 and lists in Python 2
let cmp = (a, b) => a[1] - b[1]; asort($d); from operator import itemgetter
let d = {t: 1, f: 0}; d.sort_by { |k, v| v }.each do |k, v|
foreach ($d as $k => $v) { pairs = sorted(d.items(), key=itemgetter(1)) puts "#{k}: #{v}"
sort by values for (let p of _.toPairs(d).sort(cmp)) { print "$k: $v\n"; end
console.log(p); } for k, v in pairs:
} print('{}: {}'.format(k, v))
from collections import defaultdict
counts = defaultdict(lambda: 0)
counts['foo'] += 1 counts = Hash.new(0)
$counts = []; counts['foo'] += 1
default value, $counts['foo'] += 1; class Factorial(dict):
computed none def __missing__(self, k): factorial = Hash.new do |h,k|
value # For computed values and defaults other than if k > 1: k > 1 ? k * h[k-1] : 1
# zero or empty string, extend ArrayObject. return k * self[k-1] end
else:
return 1
factorial = Factorial()
functions
node.js php python ruby
def add3(x1, x2, x3)
function add3($x1, $x2, $x3) x1 + x2 + x3
define function add3 (x1, x2, x3) { { def add3(x1, x2, x3): end
return x1 + x2 + x3; return $x1 + $x2 + $x3; return x1 + x2 + x3
} } # parens are optional and customarily
# omitted when defining functions
# with no parameters
add3(1, 2, 3); add3(1, 2, 3)
invoke add3(1, 2, 3) add3(1, 2, 3)
# function names are case insensitive: # parens are optional:
ADD3(1, 2, 3); add3 1, 2, 3
missing
argument set to undefined set to NULL with warning raises TypeError if number of arguments doesn't raises ArgumentError if number of arguments doesn't
behavior match function arity match function arity

extra
argument ignored ignored raises TypeError if number of arguments doesn't raises ArgumentError if number of arguments doesn't
behavior match function arity match function arity

function my_log($x, $base=10) import math def my_log(x, base=10)


// new in ES6: { Math.log(x) / Math.log(base)
default function myLog (x, base = 10) { return log($x) / log($base); def my_log(x, base=10): end
argument return Math.log(x) / Math.log(base); } return math.log(x) / math.log(base)
} my_log(42)
my_log(42); my_log(42) my_log(42, Math::E)
my_log(42, M_E); my_log(42, math.e)
function firstAndLast() {
if (arguments.length >= 1) { function first_and_last()
console.log('first: ' + arguments[0]); {
}
if (arguments.length >= 2) { $arg_cnt = func_num_args(); def first_and_last(*a)
console.log('last: ' + arguments[1]); def first_and_last(*a):
} if ($arg_cnt >= 1) { if a.size >= 1
} $n = func_get_arg(0); if len(a) >= 1: puts "first: #{a[0]}"
variadic echo "first: " . $n . "\n"; print('first: ' + str(a[0])) end
function // ... operator new in ES6: }
function firstAndLast(...a) { if len(a) >= 2: if a.size >= 2
if (a.length >= 1) { if ($arg_cnt >= 2) { print('last: ' + str(a[-1])) puts "last: #{a[-1]}"
console.log('first: ' + a[0]); $a = func_get_args(); end
} $n = $a[$arg_cnt-1]; end
if (a.length >= 2) { echo "last: " . $n . "\n";
console.log('last: ' + a[1]); }
} }
}
a = [2, 3] a = [2, 3]
pass array
elements as let a = [1, 2, 3]; $a = [1, 2, 3]; add3(1, *a) add3(1, *a)
separate let sum = add3(...a); call_user_func_array("add3", $a); # splat operator can only be used once # splat operator can be used multiple
arguments # and must appear after other # times and can appear before regular
# unnamed arguments # arguments
function first_and_second(&$a)
parameter none { none none
alias return [$a[0], $a[1]];
}
def fequal(x, y, eps=0.01): def fequals(x, y, eps: 0.01)
named return abs(x - y) < eps (x - y).abs < eps
none none end
parameters
fequal(1.0, 1.001)
fequal(1.0, 1.001, eps=0.1**10) fequals(1.0, 1.001)
fequals(1.0, 1.001, eps: 0.1**10)
return arg or undefined.
return value return arg or NULL return arg or None return arg or last expression evaluated
If invoked with new and return value not an object,
returns this.
function first_and_second(&$a)
function firstAndSecond(a) { { def first_and_second(a)
multiple return return [a[0], a[1]]; return [$a[0], $a[1]]; def first_and_second(a): return a[0], a[1]
} } return a[0], a[1] end
values
let [x, y] = firstAndSecond([6, 7, 8]); $a = [6, 7, 8]; x, y = first_and_second([6, 7, 8]) x, y = first_and_second([6, 7, 8])
list($x, $y) =
first_and_second($a);
let square = function (x) {
return x * x;
};
anonymous $square = function ($x) { # body must be an expression:
function literal // => new in ES6: return $x * $x; square = lambda x: x * x square = lambda { |x| x * x }
let square = (x) => { return x * x; }; };

// expression body variant:


let square = (x) => x * x;
invoke square(2) square(2) square.call(2)
anonymous $square(2)
((x) => (x * x)(2) (lambda x: x * x)(2) # alternative syntax:
function square[2]
function as
value let func = add3; $func = "add3"; func = add3 func = lambda { |*args| add3(*args) }

function counter() { function counter() # state not private:


counter.i += 1; { def counter():
function with return counter.i; static $i = 0; counter.i += 1
} return ++$i; return counter.i none
private state }
counter.i = 0; counter.i = 0
console.log(counter()); echo counter(); print(counter())
function makeCounter () { function make_counter() def make_counter():
let i = 0; { i = 0
$i = 0; def counter(): def make_counter
return function () { return function () use (&$i) { # new in Python 3: i = 0
i += 1; return ++$i; nonlocal i return lambda { i +=1; i }
closure return i; }; i += 1 end
}; } return i
} return counter nays = make_counter
$nays = make_counter(); puts nays.call
let nays = makeCounter(); echo $nays(); nays = make_counter()
console.log(nays()); print(nays())
# cf. itertools library

function * makeCounter () { # PHP 5.5: def make_counter():


let i = 0; function make_counter() { i = 0 def make_counter
while (true) { $i = 0; while True: return Fiber.new do
yield ++i; while (1) { i += 1 i = 0
} yield ++$i; yield i while true
} } i += 1
} nays = make_counter() Fiber.yield i
generator let nays = makeCounter(); # Python 2: nays.next() end
for (let cnt of nays) { $nays = make_counter(); print(next(nays)) end
console.log(cnt); # does not return a value: end
if (cnt > 100) { $nays->next(); for cnt in nays:
break; # runs generator if generator has not print(cnt) nays = make_counter
} # yet yielded: if cnt > 100: puts nays.resume
} echo $nays->current(); break

# Returning without yielding raises


# StopIteration exception.
def logcall(f):
def wrapper(*a, **opts):
print('calling ' + f.__name__)
f(*a, **opts)
none print('called ' + f.__name__)
decorator return wrapper

@logcall
def square(x):
return x * x
import operator
invoke 3.*(7)
none operator.mul(3, 7)
operator like a = ['foo', 'bar', 'baz']
function a = ['foo', 'bar', 'baz'] a.[](2)
operator.itemgetter(2)(a)
execution control
node.js php python ruby
if (n === 0) { if ( 0 == $n ) { if 0 == n: if n == 0
console.log('no hits'); echo "no hits\n"; print('no hits') puts "no hits"
if } else if (n === 1) { } elseif ( 1 == $n ) { elif 1 == n: elsif 1 == n
console.log('1 hit'); echo "one hit\n"; print('one hit') puts "one hit"
} else { } else { else: else
console.log(n + ' hits'); echo "$n hits\n"; print(str(n) + ' hits') puts "#{n} hits"
} } end
switch (n) { switch ($n) {
case 0: case 0: case n
console.log('no hits\n;); echo "no hits\n"; when 0
break; break; puts "no hits"
case 1: case 1: none when 1
switch console.log('one hit\n'); echo "one hit\n"; puts "one hit"
break; break; else
default: default: puts "#{n} hits"
console.log(n + ' hits\n'); echo "$n hits\n"; end
} }
while while (i < 100) { while i < 100: while i < 100 do
i += 1; while ( $i < 100 ) { $i++; } i += 1 i += 1
} end
for for (let i = 0; i < 10; ++i) { for ($i = 1; $i <= 10; $i++) { for i in range(1, 11):
console.log(i); echo "$i\n"; print(i) none
} }
for (let i = 30; i < 50; ++i) {
if (i % 7 === 0) {
break console.log('first multiple: ' + i); break break break
break;
}
}
for (let i = 30; i < 50; ++i) {
if (i % 7 === 0) {
continue continue; continue continue next
}
console.log('not divisible: ' + i);
}
statement
none none none puts "positive" if i > 0
modifiers puts "nonzero" unless i == 0

exceptions
node.js php python ruby
BaseException Exception
base Any value can be thrown. Exception User-defined exceptions should subclass Exception.
exception User-defined exceptions should subclass
StandardError.
In Python 2 old-style classes can be thrown.
BaseException
Exception
TypeError Exception
ImportError NoMemoryError
AssertionError ScriptError
ArithmeticError LoadError
FloatingPointError NotImplementedError
OverflowError SyntaxError
Exception ZeroDivisionError SignalException
LogicException SyntaxError StandardError
BadFunctionCallException OSError ArgumentError
BadMethodCallException MemoryError IOError
Error DomainException StopIteration EOFError
EvalError InvalidArgumentException Error IndexError
predefined RangeError LengthException SystemError LocalJumpError
ReferenceError OutOfRangeException ValueError NameError
exceptions SyntaxError UnicodeError RangeError
RuntimeException
TypeError OutOfBoundsException UnicodeEncodeError RegexpError
URIError OverflowException UnicodeDecodeError RuntimeError
RangeException UnicodeTranslateError SecurityError
UnderflowException UnsupportedOperation SocketError
UnexpectedValueException NameError SystemCallError
AttributeError Errno::*
RuntimeError SystemStackError
LookupError ThreadError
IndexError TypeError
KeyError ZeroDivisionError
EOFError SystemExit
GeneratorExit fatal
KeyboardInterrupt
SystemExit
raise # raises RuntimeError
exception throw new Error("bad arg"); throw new Exception("bad arg"); raise Exception('bad arg')
raise "bad arg"

try { try { # catches StandardError


risky(); risky(); try: begin
catch-all risky
} catch (e) { } catch (Exception $e) { risky()
handler console.log( echo "risky failed: ", except: rescue
'risky failed: ' + e.message); $e->getMessage(), "\n"; print('risky failed') print "risky failed: "
} } puts $!.message
end
begin
try { raise "bam!"
throw new Error("bam!"); try: rescue
re-raise } catch (e) { raise Exception('bam!') puts "re-raising"
console.log('re-raising...'); except: raise
exception print('re-raising...') end
throw e;
} raise
# if rescue clause raises different exception,
# original exception preserved at e.cause
global variable last exception: $!
for last none none last exception: sys.exc_info()[1] backtrace array of exc.: $@
exception exit status of child: $?
class Bam extends Exception
function Bam(msg) { { class Bam < Exception
define this.message = msg; function __construct() class Bam(Exception): def initialize
} { def __init__(self): super("bam!")
exception parent::__construct("bam!"); super(Bam, self).__init__('bam!') end
Bam.prototype = new Error; } end
}
try {
throw new Bam("bam!");
} catch (e) { try { begin
if (e instanceof Bam) { throw new Bam; try: raise Bam.new
handle console.log(e.message); } catch (Bam $e) { raise Bam() rescue Bam => e
exception } echo $e->getMessage(), "\n"; except Bam as e: puts e.message
else { } print(e) end
throw e;
}
}
PHP 5.5:
acquireResource(); acquire_resource(); acquire_resource() acquire_resource
try { try { try: begin
finally block risky(); risky(); risky() risky
} finally { } finally: ensure
releaseResource(); finally { release_resource() release_resource
} release_resource(); end
}
threads
node.js php python ruby
class sleep10(threading.Thread):
def run(self):
start thread none time.sleep(10) thr = Thread.new { sleep 10 }
thr = sleep10()
thr.start()
wait on thread thr.join() thr.join

# a float argument will be truncated import time


sleep # to an integer: sleep(0.5)
sleep(1); time.sleep(0.5)
import signal, time

class Timeout(Exception): pass


def timeout_handler(signo, fm): require 'timeout'
raise Timeout()
use set_time_limit to limit execution time of the begin
entire script; use stream_set_timeout to limit time signal.signal(signal.SIGALRM, Timeout.timeout(5) do
timeout spent reading from a stream opened with fopen or timeout_handler) might_take_too_long
fsockopen end
try: rescue Timeout::Error
signal.alarm(5) end
might_take_too_long()
except Timeout:
pass
signal.alarm(0)
_____________________________________________________ _____________________________________________________ _____________________________________________________ _____________________________________________________

sheet two: streams | asynchronous events | files | directories | processes and environment | option parsing | libraries and
namespaces | objects | inheritance and polymorphism | reflection | net and web | gui | databases | unit tests | logging |
debugging

Version
version used
The versions used for testing code in the reference sheet.

show version
How to get the version.
php:
The function phpversion() will return the version number as a string.
python:
The following function will return the version number as a string:

import platformplatform.python_version()

ruby:
Also available in the global constant RUBY_VERSION.

implicit prologue
Code which examples in the sheet assume to have already been executed.
javascript:
underscore.js adds some convenience functions as attributes of an object which is normally stored in the
underscore _ variable. E.g.:

_.map([1, 2, 3], function(n){ return n * n; });

cdnjs hosts underscore.js and other JavaScript libraries for situations where it is inconvenient to have the webserver host
the libraries.
When using underscore.js with the Node REPL, there is a conflict, since the Node REPL uses the underscore _
variable to store the result of the last evaluation.

$ npm install underscore$ node> var us = require('underscore'); _> us.keys({"one": 1, "two": 2});[ 'one', 'two' ]

php:
The mbstring package adds UTF-8 aware string functions with mb_ prefixes.
python:
We assume that os, re, and sys are always imported.

Grammar and Execution


interpreter
The customary name of the interpreter and how to invoke it.
php:
php -f will only execute portions of the source file within a <?php php code ?> tag as php code. Portions of the source
file outside of such tags is not treated as executable code and is echoed to standard out.
If short tags are enabled, then php code can also be placed inside <? php code ?> and <?= php code ?> tags.
<?= php code ?> is identical to <?php echo php code ?>.

repl
The customary name of the repl.
php:
The php -a REPL does not save or display the result of an expression.
python:
The python repl saves the result of the last statement in _.
ruby:
irb saves the result of the last statement in _.

command line program


How to pass the code to be executed to the interpreter as a command line argument.

block delimiters
How blocks are delimited.
python:
Python blocks begin with a line that ends in a colon. The block ends with the first line that is not indented further than the
initial line. Python raises an IndentationError if the statements in the block that are not in a nested block are not all
indented the same. Using tabs in Python source code is unrecommended and many editors replace them automatically
with spaces. If the Python interpreter encounters a tab, it is treated as 8 spaces.
The python repl switches from a >>> prompt to a prompt inside a block. A blank line terminates the block.
Colons are also used to separate keys from values in dictionary literals and in sequence slice notation.
ruby:
Curly brackets {} delimit blocks. A matched curly bracket pair can be replaced by the do and end keywords. By
convention curly brackets are used for one line blocks.
The end keyword also terminates blocks started by def, class, or module.
Curly brackets are also used for hash literals, and the #{ } notation is used to interpolate expressions into strings.

statement separator
How the parser determines the end of a statement.
php:
Inside braces statements must be terminated by a semicolon. The following causes a parse error:

<? if (true) { echo "true" } ?>

The last statement inside <?= ?> or <? ?> tags does not need to be semicolon terminated, however. The following
code is legal:

<?= $a = 1 ?><? echo $a ?>

python:
Newline does not terminate a statement when:
inside parens
inside list [] or dictionary {} literals
Python single quote '' and double quote "" strings cannot contain newlines except as the two character escaped form \n.
Putting a newline in these strings results in a syntax error. There is however a multi-line string literal which starts and
ends with three single quotes ''' or three double quotes: """.
A newline that would normally terminate a statement can be escaped with a backslash.
ruby:
Newline does not terminate a statement when:
inside single quotes '', double quotes "", backticks ``, or parens ()
after an operator such as + or , that expects another argument
Ruby permits newlines in array [] or hash literals, but only after a comma , or associator =>. Puttin w
mm
A w w m m m w

sou ce code encod ng


Hw
S m ASC

end o ne commen
Hw mm w

mu p e ne commen
Hw mm m

Va ab es and Exp ess ons


oca va ab e
Hw w w mm m

V w
NU

A m m
m O w

V m m @
w m mm
A w m m
m m m Hw m
m O A m m w
w m m m

e scope va ab e
Hw w

g oba va ab e
Hw w

A w
w A m w

A A
m m w m m m
m m m w w

A w

cons an
Hw

C m m B
m m m m
w C m m m m
M P

ass gnmen
Hw

A m m
m m w w A m
m

A m m

pa a e ass gnmen
Hw

N m
m w

m w

P m m

swap
Hw w w

compound ass gnmen


Cm m m w
m
m m w

m m
w m m m m
S w m m
w m
w m

P m m

nc emen and dec emen


C m m m m
m
m
m w m m m

P m m m
R m m m m m Hw R
w

m m w w
m

w m
S m

nu

nu es
Hw

NU m NU m w NU w
w m

unde ned va ab e
m

B m m m m m
w

PHP mm w m m m w
NU
A w

Hw

Hw

cond ona exp ess on


Hw w A w m S

C m

P m mA

R m

A hme c and Log c


ue and a se

A w m RUE RUE Sm A SE
PHP m m
W RUE A SE
RUE A SE

a sehoods
V w
E m m

W m m m
P P m

og ca ope a o s

&& m m m w

e a ona ope a o s
E

M w m m
m

R w

m n and max
Hw m m

a hme c ope a o s
m m

n ege d v s on
Hw w

d vmod
Hw m w

n ege d v s on by ze o
W w

oa d v s on
Hw m m

oa d v s on by ze o
W w

powe
Hw m w

sq

sq 1

anscenden a unc ons


S m m m m w m
w

P m m

R M M m

anscenden a cons an s
C E

oa unca on
Hw w w w
w w w

abso u e va ue
Hw m

n ege ove ow
W w

oa ove ow
W w

a ona numbe s
Hw m m m

R m w

comp ex numbe s

M m m w w w m m

andom n ege un o m oa no ma oa
Hw m w w m
m w m

se andom seed ge and es o e seed


Hw m w m
A m R MR
m D m A
S m m
w m m m
m m m m

b ope a o s

b na y oc a and hex e a s
B

ad x
Hw Hw

P w

S ngs
s ng ype
U

PHP m

P m A w w
U
P m m
m mm w w

m A

s ng e a

S m

P w
P S P
P w

Hw m m
m m m

new ne n e a
W w m

Nw m A w
w

w m
w

e a escapes
B

S
PHP
P
R

W
m
w
w

P U U

P P P w
m P

he e documen
H m m m m m

P m
w m

P m

va ab e n e po a on
Hw

w m m W w m m mm

P w m

exp ess on n e po a on
Hw

o ma s ng
Hw m

% w m m
w m m m

m m m

a e s ngs mu ab e?
A m

copy s ng
Hw m

conca ena e

ep ca e

ans a e case
Hw w

cap a ze
Hw w
m w

Hw U w w

R m w m w

m
Hw m w m

pad
Hw w

numbe o s ng
Hw m

s ng o numbe
Hw m

PHP m m
m m

w m

s ng o n
Hw m w

sp
Hw
S

m m

sp n wo
Hw w

A m w

w w m

sp and keep de m e s
Hw w m m

p e x and su x es
Hw w w

eng h
Hw

ndex o subs ng
Hw m w m

ex ac subs ng
Hw m

by e a ay ype

by e a ay o s ng
Hw U

s ng o by e a ay
Hw U

cha ac e ookup
Hw

ch and o d
C ASC

o a ay o cha ac e s
Hw

ans a e cha ac e s
Hw m

P w
P m

de e e cha ac e s
Hw m m w m m

squeeze cha ac e s
Hw m w

Regu a Exp ess ons


PHP PCRE R
P
R R
R w
m R
m w U mm POS X
w m P
m w w P
A P
A m w m m

A W m
C w m
w S m
m m W
W
m
m m

w m w
m m PHP m P R
m

V
w
W

A m
P w
w w m E m
m m mw m m A
m m w

A m m
m w m

m
m

W w m m mm m m
m m mm m

m m m w

PHP EREG w
w w w

e a cus om de m ed e a
w m m

PHP m m
m m m
H m PHP m

P
Cm w

asc cha ac e c ass abb ev a ons

N w PHP R Sm
m w PHP R

un code cha ac e c ass abb ev a ons


U
E U m

M
N
P
S

E m m m E m w w
m m Nm m
Dw U D w m m

ancho s

ma ch es
Hw w m

m
m

m m w

W m m

case nsens ve ma ch es
Hw m m

mod e s
M
m R m

m M

S
X

P m m m m mw
m

M
S
X

subs u on
Hw m w

m w m

m m w

w m m
m
m

ma ch p ema ch pos ma ch
Hw m w
m

m m m

g oup cap u e
Hw w m

R m m w

named g oup cap u e


Hw w m m
w P P

PHP P m w w PCRE
P m w PHP

P w m

scan
Hw w m

back e e ence n ma ch and subs u on


Hw w m

ecu s ve egex
A m
m m

Da e and T me
SO m G m m
m m A w m m m SO
m PHP P C m m m
m w m
A SO m m
m m
w m m
C w m U w
UC m w w
U m m w
m m m m m
A m W w m w m
UC w w w N S W w
S m m E m m D m
m m m N m BCE
G GM
A w m m m m m A
m m C w U m

m w m w BSD m
m
G w O G
G W
G w AD CE w
BC BCE w BC BCE SO mm
w w m
A w w SO
mm w m m

Aw w w w
SO w w w mM w A SO
w m G w
m w M m W w
m w W

C mm

w m m
C B
m D m m
w m D m

b oken down da e me ype


m m

P C P m w
w w H w P

cu en da e me
Hw m m mm m UC

cu en un x epoch
Hw m U m m

b oken down da e me o un x epoch


Hw m U w m
UC

P m m m w
m m w m m m

H w w U w

R w w w w

un x epoch o b oken down da e me


Hw U w m

o ma da e me
Hw m m m
m m C U mm

m
m m
m m
m

PHP m w m m m
PHP m m m

pa se da e me
Hw m m m C

pa se da e me w o o ma
Hw w m

da e pa s
Hw m m m m

me pa s
Hw m m m

bu d b oken down da e me
Hw w m m m

da e me sub ac on
w m w m m

add du a on
Hw m
A m w U
SO w m w w m w
m m m A m
m
SO w P
m m O m M w
m m

oca me zone de e m na on
D m m m W m m w m
m
O U m m m m
m mm

O W w m m

H m PHP

non oca me zone


Hw m m m

me zone n o
Hw m m mU C
m M
m m m m O
m w w m m
m

m w m m
w m O m
w UC m m w w

day gh sav ngs es


m m

m c oseconds
Hw m m m m S m
m C H

s eep
Hw m P R
m

PHP w m m

meou
Hw m
S GA RM w U m

A ays
W

PHP m

P m mm B m m m
m m m m m

R A m m
E m m

ea
A

w w m w
w m w w m
m
w

quo e wo ds
w w w w

s ze
Hw m m

emp y es
Hw w m

ookup
Hw

A m

A m

upda e
Hw

ou o bounds behav o
W w

e emen ndex
Hw m

S m m O w
m w m m

s ce
Hw m w m

S w

P m

m m m w

s ce o end
Hw
m m

man pu a e back

h p hype po yg o o g p ng 1 2
Scripting Languages I: Node.js, PHP, Python, Ruby (Sheet One) - Hyperpolyglot 07/05/2017

How to add and remove elements from the back or high index end of an array.
These operations can be used to use the array as a stack.

manipulate front
How to add and remove elements from the front or low index end of an array.
These operations can be used to use the array as a stack. They can be used with the operations that manipulate the
back of the array to use the array as a queue.

concatenate
How to create an array by concatenating two arrays; how to modify an array by concatenating another array to the end of
it.

replicate
How to create an array containing the same value replicated n times.

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.
python:
The slice operator can be used to make a shallow copy:

a2 = a[:]

list(v) always returns a list, but v[:] returns a value of the same as v. The slice operator can be used in this
manner on strings and tuples but there is little incentive to do so since both are immutable.
copy.copy can be used to make a shallow copy on types that don't support the slice operator such as a dictionary.
Like the slice operator copy.copy returns a value with the same type as the argument.

array as function argument


How an array is passed to a function when provided as an argument.

iterate over elements


How to iterate over the elements of an array.

iterate over indices and elements


How to iterate over the element-index pairs.

iterate over range


Iterate over a range without instantiating it as a list.

instantiate range as array


How to convert a range to an array.
Python 3 ranges and Ruby ranges implement some of the functionality of arrays without allocating space to hold all the
elements.
python:
In Python 2 range() returns a list.
In Python 3 range() returns an object which implements the immutable sequence API.
ruby:
The Range class includes the Enumerable module.

reverse
How to create a reversed copy of an array, and how to reverse an array in place.
python:
reversed returns an iterator which can be used in a for/in construct:

print("counting down:")for i in reversed([1, 2, 3]): print(i)

reversed can be used to create a reversed list:

a = list(reversed([1, 2, 3]))

sort
How to create a sorted copy of an array, and how to sort an array in place. Also, how to set the comparison function
when sorting.
php:
usort sorts an array in place and accepts a comparison function as a 2nd argument:

function cmp($x, $y) { $lx = strtolower($x); $ly = strtolower($y); if ( $lx < $ly ) { return -1; } if ( $lx == $ly ) { return 0; } return 1;}$a = ["b", "A", "a", "B"];usort($a, "cmp");

python:
In Python 2 it is possible to specify a binary comparision function when calling sort:

a = [(1, 3), (2, 2), (3, 1)]a.sort(cmp=lambda a, b: -1 if a[1] < b[1] else 1)# a now contains:[(3, 1), (2, 2), (1, 3)]

In Python 3 the cmp parameter was removed. One can achieve the same effect by defining cmp method on the class of
the list element.

dedupe
How to remove extra occurrences of elements from an array.
python:
Python sets support the len, in, and for operators. It may be more efficient to work with the result of the set
constructor directly rather than convert it back to a list.

membership
How to test for membership in an array.

intersection
How to compute an intersection.
python:
Python has literal notation for sets:

{1, 2, 3}

Use set and list to convert lists to sets and vice versa:

a = list({1, 2, 3})ensemble = set([1, 2, 3])

ruby:
The intersect operator & always produces an array with no duplicates.

union
ruby:
The union operator | always produces an array with no duplicates.

relative complement, symmetric difference


How to compute the relative complement of two arrays or sets; how to compute the symmetric difference.
ruby:
If an element is in the right argument, then it will not be in the return value even if it is contained in the left argument
multiple times.

map
Create an array by applying a function to each element of a source array.
ruby:
The map! method applies the function to the elements of the array in place.
collect and collect! are synonyms for map and map!.

filter
Create an array containing the elements of a source array which match a predicate.
ruby:
The in place version is select!.
reject returns the complement of select. reject! is the in place version.
The partition method returns two arrays:

a = [1, 2, 3]lt2, ge2 = a.partition { |n| n < 2 }

reduce
Return the result of applying a binary operator to all the elements of the array.
python:
reduce is not needed to sum a list of numbers:

sum([1, 2, 3])

ruby:
The code for the reduction step can be provided by name. The name can be a symbol or a string:

[1, 2, 3].inject(:+)[1, 2, 3].inject("+")[1, 2, 3].inject(0, :+)[1, 2, 3].inject(0, "+")

universal and existential tests


How to test whether a condition holds for all members of an array; how to test whether a condition holds for at least one
member of any array.
A universal test is always true for an empty array. An existential test is always false for an empty array.
A existential test can readily be implemented with a filter. A universal test can also be implemented with a filter, but it is
more work: one must set the condition of the filter to the negation of the predicate and test whether the result is empty.

shuffle and sample


How to shuffle an array. How to extract a random sample from an array.
php:
The array_rand function returns a random sample of the indices of an array. The result can easily be converted to a
random sample of array values:

$a = [1, 2, 3, 4];$sample = [];foreach (array_rand($a, 2) as $i) { array_push($sample, $a[$i]); }

flatten
How to flatten nested arrays by one level or completely.
When nested arrays are flattened by one level, the depth of each element which is not in the top level array is reduced by
one.
Flattening nested arrays completely leaves no nested arrays. This is equivalent to extracting the leaf nodes of a tree.
php, python:
To flatten by one level use reduce. Remember to handle the case where an element is not array.
To flatten completely write a recursive function.

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

Dictionaries
literal
The syntax for a dictionary literal.

size
How to get the number of dictionary keys in a dictionary.

lookup
How to lookup a dictionary value using a dictionary key.

missing key behavior


What happens when a lookup is performed on a key that is not in a dictionary.
python:
Use dict.get() to avoid handling KeyError exceptions:

d = {}d.get('lorem') # returns Noned.get('lorem', '') # returns ''

is key present
How to check for the presence of a key in a dictionary without raising an exception. Distinguishes from the case where
the key is present but mapped to null or a value which evaluates to false.

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 the key/value pairs in a dictionary.
python:
In Python 2.7 dict.items() returns a list of pairs and dict.iteritems() returns an iterator on the list of pairs.
In Python 3 dict.items() returns an iterator and dict.iteritems() has been removed.

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.
python:
In Python 3 dict.keys() and dict.values() return read-only views into the dict. The following code illustrates the
change in behavior:

d = {}keys = d.keys()d['foo'] = 'bar'if 'foo' in keys: print('running Python 3')else: print('running Python 2')

sort by values
How to iterate through the key-value pairs in the order of the 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.
php:
Extend ArrayObject to compute values on lookup:

class Factorial extends ArrayObject { public function offsetExists($i) { return true; } public function offsetGet($i) { if(!parent::offsetExists($i)) { if ( $i < 2 ) { parent::offsetSet($i, 1); } else { $n = $t

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
How to define a function.

invoke
How to invoke a function.
python:
Parens are mandatory, even for functions which take no arguments. Omitting the parens returns the function or method
as an object. Whitespace can occur between the function name and the following left paren.
In Python 3 print is a function instead of a keyword; parens are mandatory around the argument.
ruby:
Ruby parens are optional. Leaving out the parens results in ambiguity when function invocations are nested. The
interpreter resolves the ambiguity by assigning as many arguments as possible to the innermost function invocation,
regardless of its actual arity. It is mandatory that the left paren not be separated from the method name by whitespace.

apply function to array


How to apply a function to an array.
perl:
Perl passes the elements of arrays as individual arguments. In the following invocation, the function foo() does not
know which arguments came from which array. For that matter it does not know how many arrays were used in the
invocation:

foo(@a, @b);

If the elements must be kept in their respective arrays the arrays must be passed by reference:

sub foo { my @a = @{$_[0]}; my @b = @{$_[1]};}foo(\@a, \@b);

When hashes are used as arguments, each key and value becomes its own argument.

missing argument behavior


What happens when a function is invoked with too few arguments.

extra argument behavior


What happens when a function is invoked with too many arguments.

default argument
How to declare a default value for an argument.

variadic function
How to write a function which accepts a variable number of argument.
python:
This function accepts one or more arguments. Invoking it without any arguments raises a TypeError:

def poker(dealer, *players): ...

ruby:
This function accepts one or more arguments. Invoking it without any arguments raises an ArgumentError:

def poker(dealer, *players) ...end

parameter alias
How to make a parameter an alias of a variable in the caller.

named parameters
How to write a function which uses named parameters and how to invoke it.
python:
The caller can use named parameter syntax at the point of invocation even if the function was defined using positional
parameters.
The splat operator * collects the remaining arguments into a list. In a function invocation, the splat can be used to expand
an array into separate arguments.
The double splat operator ** collects named parameters into a dictionary. In a function invocation, the double splat
expands a dictionary into named parameters.
A double splat operator can be used to force the caller to use named parameter syntax. This method has the
disadvantage that spelling errors in the parameter name are not caught:

def fequal(x, y, **kwargs): eps = opts.get('eps') or 0.01 return abs(x - y) < eps

In Python 3 named parameters can be made mandatory:

def fequal(x, y, *, eps): return abs(x-y) < epsfequal(1.0, 1.001, eps=0.01) # Truefequal(1.0, 1.001) # raises TypeError

ruby:
In Ruby 2.1 named parameters can be made mandatory:

def fequals(x, y, eps:) (x - y).abs < epsend# false:fequals(1.0, 1.001, eps: 0.1**10)# ArgumentError:fequals(1.0, 1.001)

return value
How the return value of a function is determined.

multiple return values


How to return multiple values from a function.

anonymous function literal


The syntax for an anonymous function literal; i.e. a lambda function.
python:
Python lambdas cannot contain newlines or semicolons, and thus are limited to a single statement or expression. Unlike
named functions, the value of the last statement or expression is returned, and a return is not necessary or permitted.
Lambdas are closures and can refer to local variables in scope, even if they are returned from that scope.
If a closure function is needed that contains more than one statement, use a nested function:

def make_nest(x): b = 37 def nest(y): c = x*y c *= b return c return nestn = make_nest(12*2)print(n(23))

Python closures are read only.


A nested function can be returned and hence be invoked outside of its containing function, but it is not visible by its name
outside of its containing function.
ruby:
The following lambda and Proc object behave identically:

sqr = lambda { |x| x * x }sqr = Proc.new {|x| x * x }

With respect to control words, Proc objects behave like blocks and lambdas like functions. In particular, when the body of
a Proc object contains a return or break statement, it acts like a return or break in the code which invoked the
Proc object. A return in a lambda merely causes the lambda to exit, and a break inside a lambda must be inside an
appropriate control structure contained with the lambda body.
Ruby are alternate syntax for defining lambdas and invoking them:

sqr = ->(x) {x*x}sqr.(2)

invoke anonymous function


The syntax for invoking an anonymous function.

function as value
How to store a function in a variable and pass it as an argument.
php:
If a variable containing a string is used like a function then PHP will look for a function with the name in the string and
attempt to invoke it.
python:
Python function are stored in variables by default. As a result a function and a variable with the same name cannot share
the same scope. This is also the reason parens are mandatory when invoking Python functions.

function with private state


How to create a function with private state which persists between function invocations.
python:
Here is a technique for creating private state which exploits the fact that the expression for a default value is evaluated
only once:

def counter(_state=[0]): _state[0] += 1 return _state[0]print(counter())

closure
How to create a first class function with access to the local variables of the local scope in which it was created.
python:
Python 2 has limited closures: access to local variables in the containing scope is read only and the bodies of
anonymous functions must consist of a single expression.
Python 3 permits write access to local variables outside the immediate scope when declared with nonlocal.

generator
How to create a function which can yield a value back to its caller and suspend execution.
python:
A Python generator is a function which returns an iterator.
An iterator is an object with two methods: iter(), which returns the iterator itself, and next(), which returns the next
item or raises a StopIteration exception.
Python sequences, of which lists are an example, define an iter() for returned an iterator which traverses the sequence.
Python iterators can be used in for/in statements and list comprehensions.
In the table below, p and q are variables for iterators.

itertools
generator description
count(start=0, step=1) arithmetic sequence of integers
cyle(p) cycle over p endlessly
repeat(v, [n]) return v n times, or endlessly
chain(p, q) p followed by q
compress(p, q) p if q
groupby(p, func)
ifilter(pred, p) p if pred(p)
ifilterfalse(pred, p) p if not pred(p)
islice(p, [start], stop, [step])
imap
starmap()
tee()
takewhile()
izip()
izip_longest()
product()
permutations()
combinations()
combinations_with_replacement()

ruby:
Ruby generators are called fibers.

decorator
A decorator replaces an invocation of one function with another in a way that that is imperceptible to the client.
Normally a decorator will add a small amount of functionality to the original function which it invokes. A decorator can
modify the arguments before passing them to the original function or modify the return value before returning it to the
client. Or it can leave the arguments and return value unmodified but perform a side effect such as logging the call.

invoke operator like function


How to call an operator using the function invocation syntax.
This is useful when dealing with an API which accepts a function as an argument.
python:
The operator module provides functions which perform the same operations as the various operators. Using these
functions is more efficient than wrapping the operators in lambdas.
ruby:
All operators can be invoked with method invocation syntax. The binary operator invocation syntax can be regarded as
syntactic sugar.

Execution Control
if
The conditional branch statement.
php:
PHP has the following alternate syntax for if statements:

if ($n == 0): echo "no hits\n";elseif ($n == 1): echo "one hit\n";else: echo "$n hits\n";endif;

ruby:
If an if statement is the last statement executed in a function, the return value is the value of the branch that executed.
Ruby if statements are expressions. They can be used on the right hand side of assignments:

m = if n 1else 0end

switch
A statement which branches based on the value of an expression.

while
How to loop over a block while a condition is true.
php:
PHP provides a do-while loop. The body of such a loop is guaranteed to execute at least once.

$i = 0;do { echo $i;} while ($i > 0);

ruby:
Ruby provides a loop with no exit condition:

def yes(expletive="y") loop do puts expletive endend

Ruby also provides the until loop.


Ruby loops can be used in expression contexts but they always evaluate to nil.

for
How to write a C-style for loop.

break
A break statement exits a while or for loop immediately.

continue
A continue statement skips ahead to the next iteration of a while or for loop.
ruby:
There is also a redo statement, which restarts the current iteration of a loop.

statement modifiers
Clauses added to the end of a statement to control execution.
Ruby has conditional statement modifiers. Ruby also has looping statement modifiers.
ruby:
Ruby has the looping statement modifiers while and until:

i = 0i += 1 while i < 10j = 10j -= 1 until j < 0

Exceptions
base exception
The base exception type or class that can be used to catch all exceptions.

predefined exceptions
A list of the more commonly encountered exceptions.
python:
Code for inspecting the descendants of a base class:

def print_class_hierarchy(cls, indent=0): print(' ' * indent, cls.__name__) for subclass in cls.__subclasses__(): print_class_hierarchy(subclass, indent + 2)

The complete Python 3.5 exception hierarchy:

BaseException Exception TypeError ImportError ZipImportError AssertionError error ArithmeticError FloatingPointError OverflowError ZeroDivisionError SyntaxError IndentationError TabError OSError

raise exception
How to raise exceptions.
ruby:
Ruby has a throw keyword in addition to raise. throw can have a symbol as an argument, and will not convert a string to a
RuntimeError exception.

catch-all handler
How to catch exceptions.
php:
PHP code must specify a variable name for the caught exception. Exception is the top of the exception hierarchy and will
catch all exceptions.
Internal PHP functions usually do not throw exceptions. They can be converted to exceptions with this signal handler:

function exception_error_handler($errno, $errstr, $errfile, $errline ) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline);}set_error_handler("exception_error_handler");

ruby:
A rescue Exception clause will catch any exception. A rescue clause with no exception type specified will catch
exceptions that are subclasses of StandardError. Exceptions outside StandardError are usually unrecoverable and hence
not handled in code.
In a rescue clause, the retry keyword will cause the begin clause to be re-executed.
In addition to begin and rescue, ruby has catch:

catch (:done) do loop do retval = work throw :done if retval < 10 endend

re-raise exception
How to re-raise an exception preserving the original stack trace.
python:
If the exception is assigned to a variable in the except clause and the variable is used as the argument to raise, then
a new stack trace is created.
ruby:
If the exception is assigned to a variable in the rescue clause and the variable is used as the argument to raise, then
the original stack trace is preserved.

global variable for last exception


The global variable name for the last exception raised.

define exception
How to define a new variable class.

handle exception
How to catch exceptions of a specific type and assign the exception a name.
php:
PHP exceptions when caught must always be assigned a variable name.

finally block
A block of statements that is guaranteed to be executed even if an exception is thrown or caught.

Threads
start thread
ruby:
Ruby MRI threads are operating system threads, but a global interpreter lock prevents more than one thread from
executing Ruby code at a time.

wait on thread
How to make a thread wait for another thread to finish.

Node
Mozilla Developer Network: JavaScript
Node.js
using node
asynchronous programming

PHP
PHP Manual
The PHP interpreter is packaged in 3 different ways: (1) as a standalone executable which can be executed as a CGI
script, (2) as a dynamically linked library which adheres to the SAPI of a webserver such as Apache or IIS, and (3) as a
standalone executable which can be used to run PHP scripts from the command line. The latter executable is called
PHP CLI.
From the perspective of a PHP programmer, there no important differences between PHP CGI and PHP SAPI. The
programmer should be aware of the following differences between PHP CGI/SAPI and PHP CLI:
PHP CGI/SAPI writes HTTP headers to standard out before any output specified by the program. PHP CLI does not.
PHP CLI sets the constants STDIN, STDOUT, and STDERR. PHP CGI/SAPI do not.
PHP CLI has no timeout. PHP CGI/SAPI will typically timeout a script after 30 seconds.
PHP CGI/SAPI add HTML markup to error messages. PHP CLI does not.
PHP CLI does not buffer output, so calling flush is never necessary. PHP CGI/SAPI buffer output.

Python
2.7: Language, Standard Library
3.2: Language, Standard Library
Python uses leading whitespace to indicate block structure. When tabs and spaces are mixed a tab is equal to 8
spaces. The command line options '-t' and '-tt' will warn and raise an error respectively when tabs are mixed with spaces.
Identifiers in imported modules must be fully qualified unless imported with from/import:

from sys import pathfrom re import *

There are two basic sequence types: the mutable list and the immutable tuple. List literals use square brackets and
commas [1, 2, 3]; tuple literals use parens and commas (1 ,2, 3).
The dictionary literals use curly brackets, colons, and commas { hello: 5, goodbye: 7 }. Python has sets; set literals
use curly brackets and commas: {1, 2, 3}. Dictionaries and sets are implemented using hash tables so dictionary keys
and set elements must be hashable.
All values that can be stored in a variable and passed to functions as arguments are objects in the sense that they have
methods which can be invoked using the method syntax.
Attributes are settable by default. This can be changed by defining a __setattr__ method for the class. The attributes of
an object are stored in the __dict__ attribute. Methods must declare the receiver as the first argument.
Classes, methods, functions, and modules are objects. If the body of a class, method, or function definition starts with is
a string, it is available available at runtime via __doc__. Code examples in the string which are preceded with '>>>' (the
python repl prompt) can be executed by doctest and compared with the output that follows.

Ruby
1.9.3 core, stdlib
Ruby has a type of value called a symbol. The literal syntax for a symbol is :identifier or :"arbitrary string". The methods
to_s and to_sym can be used to convert symbols to strings and strings to symbols. Symbols can be used to pass
functions or methods as arguments by name. They can be used as keys in Hash objects in place of strings, but the
client must remember the type of the keys since :foo != "foo". Also note that converting a Hash object with
symbols as keys to JSON and then back will yield a Hash object with strings as keys.
In Ruby all values that can be stored in a variable and passed to functions as arguments are objects in the sense that
they have methods which can be invoked using the method syntax. Moreover classes are objects. The system provided
classes are open and as a result the user can add methods to classes such as String, Array, or Fixnum. Ruby
only permits single inheritance, but Ruby modules are mix-ins and can be used to add methods to a class via the
include statement.
Ruby methods can be declared private and this is enforced by the interpreter. Object attributes are private by default and
attribute names have an ampersand @ prefix. The methods attr_reader, attr_writer, and attr_accessor can
be used in a class block to define a getter, setter, or both for an attribute.
When invoking a method the parens are optional. If there are two or more arguments they must still be separated by
commas. If one of the arguments is an expression containing a method invocation with arguments, then the Ruby
interpreter will assign as many arguments as possible to the innermost method invocation.
Inside a Ruby method, the self keyword refers to the receiver. It is not declared when defining the method. Ruby
functions are implemented as methods on an object called main which has the special property that any methods defined
on it become instance methods in the Object class which is a base class of most Ruby objects. This makes the
method available everywhere. Methods defined at the top level are also added to the main object and the Object class.
Functions which Ruby provides by default are instance methods defined the Object class or the Kernel module.
Ruby methods are not objects and cannot directly be stored in variables. It is worth emphasizing that the Python
interpreter when encountering a method identifier with no parens returns the method as an object value, but the Ruby
interpreter invokes the method. As mentioned earlier, methods can be passed by name using symbols. If a method
receives a symbol representing a method as an argument, it can invoke the method with the syntax
:symbol.to_proc.call(args). Note that to_proc resolves the symbol to the method that is in scope where it is invoked.
Although passing a method or a function is a bit awkward, Ruby provides a convenient mechanism called blocks for
simultaneously defining an anonymous function at the invocation of a method and providing it to the method as an
argument. The block appears immediately after the closing paren of the method invocation and uses either the { |args|
body } or do |args| body end syntax. The invoked method can in turn invoke the block with the yield keyword.
Ruby blocks are closures like lambda functions and can see local variables in the enclosing scope in which they were
defined. The parameters of the block are local to the block. Semicolon syntax is available so that identifiers listed after
the arguments could be made local to the block even if already defined in the containing scope.
The lambda keyword or the Proc.new constructor can be used to store an anonymous function in a variable. The
function can be invoked with variable.call(). If such a function is passed to a method argument as the last argument and
preceded with an ampersand, the function will be used as the block for the method. Conversely, if the last argument in a
method definition is preceded with an ampersand, any block provided to the function will be bound to the argument name
as an anonymous function.

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

http://hyperpolyglot.org/scripting 2/2