a side-by-side reference sheet
arithmetic and logic | strings | dates and time | arrays | dictionaries | functions | execution control | environment and i/o | libraries and modules | objects | reflection | web | history | thanks | contact | edit
php (1995) | perl (1987) | python (1991) | ruby (1995) | |
---|---|---|---|---|
versions used |
5.3 | 5.10; 5.12; 5.14 | 2.6; 2.7; 3.2 | 1.8; 1.9 |
show version |
$ php --version | $ perl --version | $ python -V | $ ruby --version |
interpreter |
$ php -f foo.php | $ perl foo.pl | $ python foo.py | $ ruby foo.rb |
repl |
$ php -a | $ perl -de 0 | $ python | $ irb |
statement separator |
; | ; | newline or ; newlines not separators inside (), [], {}, triple quote literals, or when preceded by backslash: \ |
newline or ; newlines not separators inside (), [], {}, ``, '', "", or when preceded by a binary operator or backslash: \ |
block delimiters |
{} | {} | offside rule | {} do end |
assignment |
$v = 1; | $v = 1; | # does not return a value: v = 1 |
v = 1 |
parallel assignment |
list($x, $y, $z) = array(1 ,2, 3); # 3 is ignored: list($x, $y) = array(1, 2, 3); # $z set to NULL: list($x, $y, $z) = array(1, 2); |
($x, $y, $z) = (1, 2, 3); # 3 is ignored: ($x, $y) = (1, 2, 3); # $z set to undef: ($x, $y, $z) = (1, 2); |
x, y, z = 1, 2, 3 # raises ValueError: x, y = 1, 2, 3 # raises ValueError: x, y, z = 1, 2 |
x, y, z = 1, 2, 3 # 3 is ignored: x, y = 1, 2, 3 # z set to nil: x, y, z = 1, 2 |
swap |
list($x, $y) = array($y, $x); | ($x, $y) = ($y, $x); | x, y = y, x | x, y = y, x |
compound assignment operators: arithmetic, string, logical, bit | += -= *= none /= %= **= .= none &= |= none <<= >>= &= |= ^= |
+= -= *= none /= %= **= .= x= &&= ||= ^= <<= >>= &= |= ^= |
# do not return values: += -= *= /= //= %= **= += *= &= |= ^= <<= >>= &= |= ^= |
+= -= *= /= none %= **= += *= &&= ||= ^= <<= >>= &= |= ^= |
increment and decrement |
$x = 1; ++$x; --$x; |
$x = 1; ++$x; --$x; |
none | x = 1 # x not mutated: x.succ x.pred |
local variable declarations |
# in function body: $v = NULL; $a = array(); $d = array(); $x = 1; list($y, $z) = array(2, 3); |
my $v; my (@a, %d); my $x = 1; my ($y, $z) = (2, 3); |
# in function body: v = None a, d = [], {} x = 1 y, z = 2, 3 |
v = nil a, d = [], {} x = 1 y, z = 2, 3 |
regions which define local scope | top level: function or method body nestable (with use clause): anonymous function body |
top level: file nestable: function body anonymous function body anonymous block |
nestable (read only): function or method body |
top level: file class block module block method body nestable: anonymous function block anonymous block |
global variable | list($g1, $g2) = array(7, 8); function swap_globals() { global $g1, $g2; list($g1, $g2) = array($g2, $g1); } |
our ($g1, $g2) = (7, 8); sub swap_globals() { ($g1, $g2) = ($g2, $g1); } |
g1, g2 = 7, 8 def swap_globals(): global g1, g2 g1, g2 = g2, g1 |
$g1, $g2 = 7, 8 def swap_globals() $g1, $g2 = $g2, $g1 end |
constant declaration |
define("PI", 3.14); | use constant PI => 3.14; | # uppercase identifiers # constant by convention PI = 3.14 |
# warning if capitalized # identifier is reassigned PI = 3.14 |
to-end-of-line comment |
// comment # comment |
# comment | # comment | # comment |
comment out multiple lines |
/* comment line another line */ |
=for comment line another line =cut |
use triple quote string literal: '''comment line another line''' |
=begin comment line another line =end |
null |
NULL # case insensitive | undef | None | nil |
null test |
is_null($v) ! isset($v) |
! defined $v | v == None v is None |
v == nil v.nil? |
undefined variable access |
NULL | error under use strict; otherwise undef | raises NameError | raises NameError |
undefined test |
same as null test; no distinction between undefined variables and variables set to NULL | same as null test; no distinction between undefined variables and variables set to undef | not_defined = False try: v except NameError: not_defined = True |
! defined?(v) |
arithmetic and logic | ||||
php | perl | python | ruby | |
true and false |
TRUE FALSE # case insensitve | 1 '' | True False | true false |
falsehoods |
FALSE NULL 0 0.0 '' '0' array() | undef 0 0.0 '' '0' () | False None 0 0.0 '' [] {} | false nil |
logical operators |
&& || ! lower precedence: and or xor |
&& || ! lower precedence: and or xor not |
and or not | && || ! lower precedence: and or not |
conditional expression |
$x > 0 ? $x : -$x | $x > 0 ? $x : -$x | x if x > 0 else -x | x > 0 ? x : -x |
comparison operators |
== != or <> > < >= <= no conversion: === !== |
numbers only: == != > < >= <= strings: eq ne gt lt ge le |
== != > < >= <= | == != > < >= <= |
three way comparison | none | 0 <=> 1 "bar" cmp "foo" |
removed from Python 3: cmp(0, 1) cmp("bar", "foo") |
0 <=> 1 "bar" <=> "foo" |
convert from string, to string |
7 + '12' 73.9 + '.037' 'value: ' . 8 |
7 + '12' 73.9 + '.037' 'value: ' . 8 |
7 + int('12') 73.9 + float('.037') 'value: ' + str(8) |
7 + "12".to_i 73.9 + ".037".to_f "value: " + "8".to_s |
arithmetic operators |
+ - * / none % pow(b,e) | + - * / none % ** | + - * / // % ** | + - * x.fdiv(y) / % ** |
integer division |
(int) (13 / 5) none |
int ( 13 / 5 ) none |
13 // 5 q, r = divmod(13, 5) |
13 / 5 q, r = 13.divmod(5) |
float division |
13 / 5 | 13 / 5 | float(13) / 5 # python 3: 13 / 5 |
13.to_f / 5 or 13.fdiv(5) |
arithmetic functions |
sqrt exp log sin cos tan asin acos atan atan2 | use Math::Trig qw( tan asin acos atan); sqrt exp log sin cos tan asin acos atan atan2 |
from math import sqrt, exp, log, \ sin, cos, tan, asin, acos, atan, atan2 |
include Math sqrt exp log sin cos tan asin acos atan atan2 |
arithmetic truncation |
(int)$x round($x) ceil($x) floor($x) abs($x) |
use POSIX qw(ceil floor); int($x) install Number::Format for round ceil($x) floor($x) abs($x) |
import math int(x) int(round(x)) math.ceil(x) math.floor(x) abs(x) |
x.to_i x.round x.ceil x.floor x.abs |
min and max |
min(1,2,3) max(1,2,3) $a = array(1,2,3) call_user_func_array(min, $a) call_user_func_array(max, $a) |
use List::Util qw(min max); min(1,2,3); max(1,2,3); @a = (1,2,3); min(@a); max(@a); |
min(1,2,3) max(1,2,3) min([1,2,3]) max([1,2,3]) |
[1,2,3].min [1,2,3].max |
division by zero |
returns FALSE with warning | error | raises ZeroDivisionError | integer division raises ZeroDivisionError float division returns Infinity |
integer overflow |
converted to float | converted to float; use Math::BigInt to create arbitrary length integers | becomes arbitrary length integer of type long | becomes arbitrary length integer of type Bignum |
float overflow |
INF | inf | raises OverflowError | Infinity |
sqrt -2 |
NaN | error unless use Math::Complex in effect | # raises ValueError: import math math.sqrt(-2) # returns complex float: import cmath cmath.sqrt(-2) |
raises Errno::EDOM |
rational numbers |
none | use Math::BigRat; my $x = Math::BigRat->new('22/7'); $x->numerator(); $x->denominator(); |
from fractions import Fraction x = Fraction(22,7) x.numerator x.denominator |
require 'rational' x = Rational(22,7) x.numerator x.denominator |
complex numbers |
none | use Math::Complex; my $z = 1 + 1.414 * i; Re($z); Im($z); |
z = 1 + 1.414j z.real z.imag |
require 'complex' z = 1 + 1.414.im z.real z.imag |
random integer, uniform float, normal float | rand(0,99) lcg_value() none |
int(rand() * 100) rand() none |
import random random.randint(0,99) random.random() random.gauss(0,1) |
rand(100) rand none |
bit operators |
<< >> & | ^ ~ | << >> & | ^ ~ | << >> & | ^ ~ | << >> & | ^ ~ |
binary, octal, and hex literals | none 052 0x2a |
0b101010 052 0x2a |
0b101010 052 0x2a |
0b101010 052 0x2a |
base conversion | base_convert("42", 10, 7); base_convert("60", 7, 10); |
install Math::BaseCalc use Math::BaseCalc; $c = new Math::BaseCalc(digits=> [0..6]); $c->to_base(42); $c->from_base("60"); |
none int("60", 7) |
42.to_s(7) "60".to_i(7) |
strings | ||||
php | perl | python | ruby | |
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\"" |
newline in literal |
yes | yes | no, use escape or triple quote literal | yes |
backslash escapes |
single quoted: \' \\ double quoted: \f \n \r \t \v \xhh \$ \" \ooo |
single quoted: \' \\ double quoted: \a \b \cx \e \f \n \r \t \xhh \x{hhhh} \ooo |
\newline \\ \' \" \a \b \f \n \r \t \v \ooo \xhh python 3: \uhhhh |
single quoted: \' \\ double quoted: \a \b \cx \e \f \n \r \s \t \uhhhh \u{hhhhh} \v \xhh \ooo |
variable interpolation |
$count = 3; $item = "ball"; echo "$count ${item}s\n"; |
my $count = 3; my $item = "ball"; print "$count ${item}s\n"; |
none | count = 3 item = "ball" puts "#{count} #{item}s" |
custom delimiters | my $s1 = q[foo bar]; my $s2 = qq[$s1 baz]; |
s1 = %q[foo bar] s2 = %Q[#{s1} baz] |
||
sprintf |
$fmt = "foo: %s %d %f"; sprintf($fmt, 'bar', 13, 3.7); |
my $fmt = "foo: %s %d %f"; sprintf($fmt, 'bar', 13, 3.7) |
'foo: %s %d %f' % ('bar',13,3.7) fmt = 'foo: {0} {1} {2}' str.format(fmt, 'bar', 13, 3.7) |
"foo: %s %d %f" % ['bar',13,3.7] |
here document |
$computer = 'PC'; $s = <<<EOF here document there $computer EOF; |
$computer = 'PC'; $s = <<EOF; here document there $computer EOF |
none | computer = 'PC' s = <<EOF here document there #{computer} EOF |
concatenate |
"hello, " . "world" | "hello, " . "world" | 'hello, ' + 'world' | "hello, " + "world" |
replicate |
$hbar = str_repeat('-', 80); | my $hbar = '-' x 80; | hbar = '-' * 80 | hbar = '-' * 80 |
split |
explode(" ","foo bar baz") preg_split('/\s+/',"foo bar baz") |
split(/\s+/,"foo bar baz") | 'foo bar baz'.split() | "foo bar baz".split |
join |
$a = array("foo","bar","baz"); implode(" ", $a) |
join(' ',("foo","bar","baz")) | ' '.join(['foo','bar','baz']) | ['foo','bar','baz'].join(' ') |
case manipulation | strtoupper("hello") strtolower("HELLO") ucfirst("hello") |
uc("hello") lc("HELLO") ucfirst("hello") |
'hello'.upper() 'HELLO'.lower() 'hello'.capitalize() |
"hello".upcase "HELLO".downcase "hello".capitalize |
strip |
trim(" foo ") ltrim(" foo") rtrim("foo ") |
install Text::Trim or use regex substitution | ' foo '.strip() ' foo'.lstrip() 'foo '.rstrip() |
" foo ".strip " foo".lstrip "foo ".rstrip |
pad on right, on left |
str_pad("hello", 10) str_pad("hello", 10, " ", STR_PAD_LEFT) |
sprintf("%-10s","hello") sprintf("%10s","hello") |
'hello'.ljust(10) 'hello'.rjust(10) |
"hello".ljust(10) "hello".rjust(10) |
length |
strlen("hello") | length("hello") | len('hello') | "hello".length "hello".size |
index of substring |
strpos("foo bar", "bar") returns FALSE if not found |
index("foo bar","bar") returns -1 if not found |
'foo bar'.index('bar') raises ValueError if not found |
"foo bar".index("bar") returns nil if not found |
extract substring |
substr("foo bar", 4, 3) | substr("foo bar",4,3) | "foo bar"[4:7] | "foo bar"[4,3] |
extract character | syntax error to use index notation directly on string literal: $s = "foo bar"; $s[4]; |
can't use index notation with strings: substr("foo bar",4,1) |
"foo bar"[4] | "foo bar"[4] |
chr and ord |
chr(65) ord("A") |
chr(65) ord("A") |
chr(65) ord('A') |
65.chr "A".ord |
character count |
$a = count_chars("(3*(7+12))"); $a[ord('(')] |
"(3*(7+12))" =~ tr/(// | '(3*(7+12))'.count('(') | '(3*(7+12))'.count('(') |
character translation |
$ins = implode(range('a','z')); $outs = substr($ins,13,13) . substr($ins,0,13); strtr("hello",$ins,$outs) |
$s = "hello"; $s =~ tr/a-z/n-za-m/; |
from string import lowercase as ins from string import maketrans outs = ins[13:] + ins[:13] "hello".translate(maketrans(ins,outs)) |
"hello".tr('a-z','n-za-m') |
regex match |
preg_match('/^\d{4}/',"1999") preg_match('/^[a-z]+/',"foo BAR") preg_match('/[A-Z]+/',"foo BAR") |
"1999" =~ /^\d{4}$/ "foo BAR" =~ /^[a-z]+/ "foo BAR" =~ /[A-Z]+/ |
import re re.match("\d{4}$","1999") re.match("[a-z]+","foo BAR") re.search("[A-Z]+","foo BAR") |
"1999".match(/^\d{4}$/) "foo BAR".match(/^[a-z]+/) "foo BAR".match(/[A-Z]+/) |
match, prematch, postmatch |
none | my $s = "A 17 B 12"; while ( $s =~ /\d+/ ) { my $discard = $`; my $number = $&; $s = $'; print $number . "\n"; } |
s = "A 17 B 12" while True: m = re.search('\d+',s) if not m: break discard = s[0:m.start(0)] number = m.group() s = s[m.end(0):len(s)] print(s) |
s = "A 17 B 12" while (/\d+/.match(s)) do discard = $` number = $& s = $' puts number end |
substring matches |
$a = array(); $s = "2010-06-03"; $r = '/(\d{4})-(\d{2})-(\d{2})/'; preg_match($r, $s, $a); list($_, $yr, $mn, $dy) = $a; |
"2010-06-03" =~ /(\d{4})-(\d{2})-(\d{2})/; ($yr, $mn, $dy) = ($1, $2, $3); |
import re reg = "(\d{4})-(\d{2})-(\d{2})" m = re.search(reg, "2010-06-03") yr,mn,dy = m.groups() |
reg = /(\d{4})-(\d{2})-(\d{2})/ m = reg.match("2010-06-03") yr,mn,dy = m[1..3] |
scan |
$s = "foo bar baz"; preg_match_all('/\w+/', $s, $a); $a[0] |
$s = "foo bar baz"; @a = $s =~ m/\w+/g; |
import re s = 'foo bar baz' re.compile('\w+').findall(s) |
"foo bar baz".scan(/\w+/) |
single substitution |
$s = 'foo bar bar'; preg_replace('/bar/','baz',$s,1); |
$s = "foo bar bar"; $s =~ s/bar/baz/; $s |
import re s = 'foo bar bar' re.compile('bar').sub('baz', s, 1) |
"foo bar bar".sub(/bar/,'baz') |
global substitution |
$s = 'foo bar bar'; preg_replace('/bar/', 'baz', $s); |
$s = "foo bar bar"; $s =~ s/bar/baz/g; $s |
import re s = 'foo bar bar' re.compile('bar').sub('baz', s) |
"foo bar bar".gsub(/bar/,'baz') |
dates and time | ||||
php | perl | python | ruby | |
date/time type |
integer with Unix epoch or DateTime | integer with Unix epoch or tm array | datetime.datetime | Time |
current date/time | contains Unix epoch; hence always UTC: $t = time(); DateTime objects: $dt = new DateTime("now"); $utc_dtz = new DateTimeZone("UTC"); $utc = new DateTime("now", $utc_dtz); |
contains Unix epoch; hence always UTC: $t = time; tm arrays: @tm = localtime($t); @tm_utc = gmtime($t); |
import datetime t = datetime.datetime.now() utc = datetime.datetime.utcnow() |
t = Time.now utc = Time.now.utc |
local timezone | DateTime objects can be instantiated without specifying the timezone if a default is set: $tmz = "America/Los_Angeles"; date_default_timezone_set($tmz); |
tm arrays do not contain the offset or timezone name | a datetime object has no timezone information unless a tzinfo object is provided when it is created | if no timezone is specified the local timezone is used |
strftime | strftime("%Y-%m-%d %H:%M:%S", $t); date("Y-m-d H:i:s", $t); $dt->format("Y-m-d H:i:s"); |
use POSIX qw(strftime); @tm = localtime(time); $fmt = "%Y-%m-%d %H:%M:%S"; print strftime($fmt, @tm); |
t.strftime("%Y-%m-%d %H:%M:%S") | t.strftime("%Y-%m-%d %H:%M:%S") |
strptime | $fmt = "Y-m-d H:i:s"; $s = "2011-05-03 10:00:00"; $dt = DateTime::createFromFormat($fmt, $s); |
install Date::Parse use Time::Local; use Date::Parse; $s = "2011-05-03 10:00:00"; $fmt = "%Y-%m-%d %H:%M:%S"; @tm = strptime($s, $fmt); $t = timelocal(@tm); |
from datetime import datetime s = "2011-05-03 10:00:00" fmt = "%Y-%m-%d %H:%M:%S" t = datetime.stptime(s, fmt) |
require 'date' s = "2011-05-03 10:00:00" fmt = "%Y-%m-%d %H:%M:%S" t = Date.strptime(s, fmt).to_time |
parse date | $t = strtotime("July 7, 1999"); | install Date::Parse use Date::Parse; $t = str2time('July 7, 1999'); |
install python-dateutil import dateutil.parser s = 'July 7, 1999' t = dateutil.parser.parse(s) |
s = 'July 7, 1999' t = Date.parse(s).to_time |
date subtraction | DateInterval object if diff method used: $fmt = "Y-m-d H:i:s"; $s = "2011-05-03 10:00:00"; $then = DateTime::createFromFormat($fmt, $s); $now = new DateTime("now"); $interval = $now->diff($then); |
Unix epoch values yield integer time difference in seconds | datetime.timedelta object | Float containing time difference in seconds |
add time duration | $now = new DateTime("now"); $now->add(new DateInterval("PT10M3S"); |
$now = time; $now += 10 * 60 + 3; |
import datetime d = datetime.timedelta( minutes=10, seconds=3) t = datetime.datetime.now + d |
require 'date/delta' s = '10 min, 3 s' d = Date::Delta.parse(s).in_secs t = Time.now + d |
to unix epoch, from unix epoch | $dt->getTimestamp(); $dt2 = new DateTime(); $dt2->setTimestamp(1304442000); |
use Time::Local; $t = timelocal(@tm); @tm2 = localtime(1304442000); |
from datetime import datetime int(t.strftime("%s")) datetime.fromtimestamp(1312604983) |
t.to_i Time.at(1312604983) |
timezone name; offset from UTC; is daylight savings? | $dtz = date_timezone_get($dt); timezone_name_get($dtz); date_offset_get($dt) / 3600; $dt->format("I"); |
install 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); |
import time tm = time.localtime() time.tzname[tm.tm_isdst] (time.timezone / -3600) + tm.tm_isdst tm.tm_isdst |
t.zone t.utc_offset / 3600 t.dst? |
microseconds | list($frac, $sec) = explode(" ", microtime()); $usec = $frac * 1000 * 1000; |
use Time::HiRes qw(gettimeofday); ($sec, $usec) = gettimeofday; |
t.microsecond | t.usec |
sleep | a float argument will be truncated to an integer: sleep(1); |
a float argument will be truncated to an integer: sleep 1; |
import time time.sleep(0.5) |
sleep(0.5) |
timeout | use set_time_limit to limit execution time of the entire script; use stream_set_timeout to limit time spent reading from a stream opened with fopen or fsockopen | eval { $SIG{ALRM}= sub {die "timeout!";}; alarm 5; sleep 10; }; alarm 0; |
import signal import time class Timeout(Exception): pass def timeout_handler(signo, fm): raise Timeout() signal.signal(signal.SIGALRM, timeout_handler) try: signal.alarm(5) time.sleep(10) except Timeout: pass signal.alarm(0) |
require 'timeout' begin Timeout.timeout(5) do sleep(10) end rescue Timeout::Error end |
arrays | ||||
php | perl | python | ruby | |
literal |
$a = array(1,2,3,4); | @a = (1,2,3,4); | a = [1,2,3,4] | a = [1,2,3,4] |
quote words |
@a = qw(foo bar baz); | a = 'foo bar baz'.split() | a = %w(foo bar baz) | |
size |
count($a) | $#a + 1 or scalar(@a) |
len(a) | a.size a.length # same as size |
lookup |
$a[0] | $a[0] | a[0] | a[0] |
update |
$a[0] = 'foo'; | $a[0] = 'foo'; | a[0] = 'foo' | a[0] = 'foo' |
out-of-bounds behavior | $a = array(); evaluates as NULL: $a[10]; increases array size to one: $a[10] = 'foo'; |
@a = (); evaluates as undef: $a[10]; increases array size to 11: $a[10] = 'foo'; |
a = [] raises IndexError: a[10] raises IndexError: a[10] = 'foo' |
a = [] evaluates as nil: a[10] increases array size to 11: a[10] = 'foo' |
index of array element | $a = array('x','y','z'); $i = array_search('y', $a); |
use List::Util 'first'; @a = qw(x y z); $i = first {$a[$_] eq 'y'} (0..$#a); |
a = ['x','y','z'] i = a.index('y') |
a = ['x','y','z'] i = a.index('y') |
slice |
# 3rd arg is length of slice: array_slice($a,1,2) |
@a[1..2] | a[1:3] | a[1..2] |
slice to end |
array_slice($a, 1) | @a[1..$#a] | a[1:] | a[1..-1] |
manipulate back |
$a = array(6,7,8); array_push($a, 9); array_pop($a); |
@a = (6,7,8); push @a, 9; pop @a; |
a = [6,7,8] a.append(9) a.pop() |
a = [6,7,8] a.push(9) a << 9 # same as push a.pop |
manipulate front |
$a = array(6,7,8); array_unshift($a, 5); array_shift($a); |
@a = (6,7,8); unshift @a, 5; shift @a; |
a = [6,7,8] a.insert(0,5) a.pop(0) |
a = [6,7,8] a.unshift(5) a.shift |
concatenate | $a = array(1,2,3); $a2 = array_merge($a,array(4,5,6)); $a = array_merge($a,array(4,5,6)); |
@a = (1,2,3); @a2 = (@a,(4,5,6)); push @a, (4,5,6); |
a = [1,2,3] a2 = a + [4,5,6] a.extend([4,5,6]) |
a = [1,2,3] a2 = a + [4,5,6] a.concat([4,5,6]) |
address copy, shallow copy, deep copy | $a = array(1,2,array(3,4)); $a2 =& $a; none $a4 = $a; |
@a = (1,2,[3,4]); $a2 = \@a; @a3 = @a; use Clone qw(clone); $a4 = clone(\@a); |
a = [1,2,[3,4]] a2 = a a3 = list(a) import copy a4 = copy.deepcopy(a) |
a = [1,2,[3,4]] a2 = a a3 = a.dup a4 = Marshal.load(Marshal.dump(a)) |
arrays as function arguments | parameter contains deep copy | each element passed as separate argument; use reference to pass array as single argument | parameter contains address copy | parameter contains address copy |
iteration |
foreach (array(1,2,3) as $i) { echo "$i\n"; } |
for $i (1 2 3) { print "$i\n" } | for i in [1,2,3]: print(i) |
[1,2,3].each { |i| puts i } |
indexed iteration | $a = array('foo','bar','baz'); foreach ($a as $i => $s) { echo "$s at index $i\n"; } |
none; use range iteration from 0 to $#a and use index to look up value in the loop body | for i, s in enumerate(['foo','bar','baz']): print("%s at index %d" % (s, i)) |
a = ['foo','bar','baz'] a.each_with_index do |s,i| puts "#{s} at index #{i}" end |
iterate over range | not space efficient; use C-style for loop | for $i (1..1_000_000) { code } |
for i in xrange(1, 1000001): code |
(1..1_000_000).each do |i| code end |
instantiate range as array | $a = range(1, 10); | @a = 1..10; | a = range(1, 11) | a = (1..10).to_a |
sort | $a = array(3,1,4,2); none sort($a); |
@a = (3,1,4,2); sort @a; @a = sort @a; sort { $a <=> $b } @a; |
a = [3,1,4,2] sorted(a) a.sort() |
a = [3,1,4,2] a.sort a.sort! a.sort { |m,n| m <=> n} |
reverse | $a = array(1,2,3); array_reverse($a); $a = array_reverse($a); |
@a = (1,2,3); reverse @a; @a = reverse @a; |
a = [1,2,3] a[::-1] a.reverse() |
a = [1,2,3] a.reverse a.reverse! |
membership |
in_array(7, $a) | scalar(grep { 7 == $_ } @a) | 7 in a | a.include?(7) |
intersection |
$a = array(1,2); $b = array(2,3,4) array_intersect($a, $b) |
set.intersection(set([1,2]), set([2,3,4])) |
[1,2] & [2,3,4] | |
union |
set.union(set([1,2]),set([2,3,4])) | [1,2] | [2,3,4] | ||
map |
$t2 = create_function('$x', 'return $x*$x;') array_map($t2, array(1,2,3)) |
map { $_ * $_ } (1,2,3) | map(lambda x: x * x, [1,2,3]) # or use list comprehension: [x*x for x in [1,2,3]] |
[1,2,3].map { |o| o*o } |
filter |
$gt1 = create_function('$x','return $x>1;'); array_filter( array(1,2,3), $gt1) |
grep { $_ > 1 } (1,2,3) | filter(lambda x: x > 1,[1,2,3]) # or use list comprehension: [x for x in [1,2,3] if x > 1] |
[1,2,3].select { |o| o > 1 } |
reduce |
$add = create_function('$x,$y','return $x+$y;'); array_reduce(array(1,2,3),$add,0) |
reduce { $x + $y } 0, (1,2,3) | # import needed in python 3 only import reduce from functools reduce(lambda x,y:x+y,[1,2,3],0) |
[1,2,3].inject(0) { |m,o| m+o } |
universal test |
use array_filter | install List::AllUtils or use grep | all(i%2 == 0 for i in [1,2,3,4]) | [1,2,3,4].all? {|i| i.even? } |
existential test |
use array_filter | install List::AllUtils or use grep | any(i%2 == 0 for i in [1,2,3,4]) | [1,2,3,4].any? {|i| i.even? } |
shuffle and sample | $a = array(1, 2, 3, 4); shuffle($a); none |
use List::Util 'shuffle'; @a = (1, 2, 3, 4); shuffle(@a); none |
from random import shuffle, sample a = [1, 2, 3, 4] shuffle(a) sample(a, 2) |
[1, 2, 3, 4].shuffle ruby 1.9: [1, 2, 3, 4].sample(2) |
zip |
none | none | zip([1,2,3],['a','b','c']) | [1,2,3].zip(['a','b','c']) |
dictionaries | ||||
php | perl | python | ruby | |
literal |
$d = array('t' => 1, 'f' => 0); | %d = ( t => 1, f => 0 ); | d = { 't':1, 'f':0 } | d = { 't' => 1, 'f' => 0 } |
size |
count($d) | scalar(keys %d) | len(d) | d.size d.length # same as size |
lookup |
$d['t'] | $d{'t'} | d['t'] | d['t'] |
out-of-bounds behavior |
$d = array(); evaluates as NULL: $d['foo']; adds key/value pair: $d['foo'] = 'bar'; |
%d = (); evaluates as undef: $d{'foo'}; adds key/value pair: $d{'foo'} = 'bar'; |
d = {} raises KeyError: d['foo'] adds key/value pair: d['foo'] = 'bar' |
d = {} evaluates as nil: d['foo'] adds key/value pair: d['foo'] = 'bar' |
is key present |
array_key_exists('y', $d); | exists $d{'y'} | 'y' in d | d.has_key?('y') |
delete entry | $d = array(1 => 't', 0 => 'f'); unset($d[1]); |
%d = ( 1 => 't', 0 => 'f' ); delete $d{1}; |
d = {1: True, 0: False} del d[1] |
d = {1 => true, 0 => false} d.delete(1) |
merge | $d1 = array('a'=>1, 'b'=>2); $d2 = array('b'=>3, 'c'=>4); $d1 = array_merge($d1, $d2); |
%d1 = (a=>1, b=>2); %d2 = (b=>3, c=>4); %d1 = (%d1, %d2); |
d1 = {'a':1, 'b':2} d2 = {'b':3, 'c':4} d1.update(d2) |
d1 = {'a'=>1, 'b'=>2} d2 = {'b'=>3, 'c'=>4} d1.merge!(d2) |
invert | $to_num = array('t'=>1, 'f'=>0); $to_let = array_flip($to_num); |
%to_num = (t=>1, f=>0); %to_let = reverse %to_num; |
to_num = {'t':1, 'f':0} a = [[v,k] for k,v in to_num.items()] to_let = dict(a) |
to_num = {'t'=>1, 'f'=>0} to_let = to_num.invert |
iteration |
foreach ($d as $k => $v ) { | while ( ($k, $v) = each %d ) { | for k,v in d.iteritems(): code |
d.each { |k,v| code } |
keys and values as arrays | array_keys($d) array_values($d) |
keys %d values %d |
d.keys() d.values() |
d.keys d.values |
default value | class CountArray extends ArrayObject { public function offsetExists($i) { return true; } public function offsetGet($i) { if(!parent::offsetExists($i)) { parent::offsetSet($i, 0); } return parent::offsetGet($i); } } $counts = new CountArray(); |
define a tied hash | class CountDict(dict): def __missing__(self, k): return 0 counts = CountDict() |
counts = Hash.new do |h,k| h[k] = 0 end |
functions | ||||
php | perl | python | ruby | |
function declaration |
function add($a, $b) { return $a + $b; } |
sub add { $_[0] + $_[1] } | def add(a,b): return a+b |
def add(a,b) a+b end |
function invocation | function names are case insensitive: ADD(3,7); |
add(1,2); | add(1,2) | add(1,2) |
missing argument behavior |
set to NULL with warning | set to undef | raises TypeError | raises ArgumentError |
default value |
function my_log($x, $base=10) { | sub my_log { my $x = shift; my $base = shift || 10; |
def log(x,base=10): | def log(x,base=10) |
arbitrary number of arguments | function add() { return array_sum(func_get_args()); } |
@_ contains all values | def add(first,*rest): if not rest: return first else: return first+add(*rest) |
def add(first, *rest) if rest.empty? first else first + add(*rest) end end |
named parameter definition |
none | none | def foo(**d): | def foo(h) |
named parameter invocation |
none | none | foo(eps=0.01) | foo(:eps => 0.01) |
pass number or string by reference |
function foo(&$x, &$y) { $x += 1; $y .= 'ly'; } $n = 7; $s = 'hard'; foo($n, $s); |
sub foo { $_[0] += 1; $_[1] .= 'ly'; } my $n = 7; my $s = 'hard'; foo($n, $s); |
not possible | not possible |
pass array or dictionary by reference |
function foo(&$x, &$y) { $x[2] = 5; $y['f'] = -1; } $a = array(1,2,3); $d = array('t'=>1,'f'=>0); foo($a, $d); |
sub foo { $_[0][2] = 5; $_[1]{'f'} = -1; } my @a = (1,2,3); my %d = ('t'=> 1, 'f' => 0); foo(\@a, \%d); |
def foo(x, y): x[2] = 5 y['f'] = -1 a = [1,2,3] d = {'t':1, 'f':0} foo(a, d) |
def foo(x, y) x[2] = 5 y['f'] = -1 end a = [1,2,3] d = {'t'=> 1, 'f' => 0 } foo(a, d) |
return value |
return arg or NULL | return arg or last expression evaluated | return arg or None | return arg or last expression evaluated |
multiple return values |
function first_and_second(&$a) { return array($a[0], $a[1]); } $a = array(1,2,3); list($x, $y) = first_and_second($a); |
sub first_and_second { return ($_[0], $_[1]); } @a = (1,2,3); ($x, $y) = first_and_second(@a); |
def first_and_second(a): return a[0], a[1] x, y = first_and_second([1,2,3]) |
def first_and_second(a) return a[0], a[1] end x, y = first_and_second([1,2,3]) |
lambda declaration |
$sq = create_function('$x','return $x*$x;'); | $sq = sub { $_[0] * $_[0] } | sq = lambda x: x * x | sq = lambda { |x| x * x } |
lambda invocation |
$sq(2) | $sq->(2) | sq(2) | sq.call(2) |
function with private state | function counter() { static $i = 0; return ++$i; } echo counter(); |
use feature state; sub counter { state $i = 0; ++$i; } print counter() . "\n"; |
# state not private: def counter(): counter.i += 1 return counter.i counter.i = 0 print(counter()) |
none |
closure | function make_counter() { $i = 0; return function () use (&$i) { return ++$i; }; } $nays = make_counter(); echo $nays(); |
sub make_counter() { my $i = 0; return sub() { ++$i }; } my $nays = make_counter(); print $nays->() . "\n"; |
# python 3: def make_counter(): i = 0 def counter(): nonlocal i i += 1 return i return counter nays = make_counter() |
def make_counter() i = 0 return lambda { i +=1; i } end nays = make_counter puts nays.call |
generator | none | none | def make_counter(): i = 0 while True: i += 1 yield(i) nays = make_counter() print(nays.next()) |
# ruby 1.9: def make_counter() return Fiber.new do i = 0 while true i += 1 Fiber.yield i end end end nays = make_counter puts nays.resume |
execution control | ||||
php | perl | python | ruby | |
if |
if ( 0 == $n ) { echo "no hits\n"; } elseif ( 1 == $n ) { echo "one hit\n"; } else { echo "$n hits\n"; } |
if ( 0 == $n ) { print "no hits\n" } elsif ( 1 == $n ) { print "one hit\n" } else { print "$n hits\n" } |
if 0 == n: print("no hits") elif 1 == n: print("one hit") else: print(str(n) + " hits") |
if n == 0 puts "no hits" elsif 1 == n puts "one hit" else puts "#{n} hits" end |
switch | switch ($n) { case 0: echo "no hits\n"; break; case 1: echo "one hit\n"; break; default: echo "$n hits\n"; } |
use feature 'switch'; given ($n) { when (0) { print "no hits\n"; } when (1) { print "one hit\n"; } default { print "$n hits\n"; } } |
none | case n when 0 puts "no hits" when 1 puts "one hit" else puts "#{n} hits" end |
while |
while ( $i < 100 ) { $i++; } | while ( $i < 100 ) { $i++ } | while i < 100: i += 1 |
while i < 100 do i += 1 end |
c-style for |
for ($i = 1; $i <= 10; $i++) { echo "$i\n"; } |
for ( $i=0; $i <= 10; $i++ ) { print "$i\n"; } |
none | none |
break, continue, redo |
break continue none | last next redo | break continue none | break next redo |
control structure keywords | case default do else elseif for foreach goto if switch while | do else elsif for foreach goto if unless until while | elif else for if while | case do else elsif end for loop when while unless until |
what do does | starts body of a do-while or do-until loop | executes following block and returns value of last statement executed | raises NameError unless a value was assigned to it | starts an anonymous block. Also starts the body of a loop, while, or until loop |
statement modifiers |
none | print "positive\n" if $i > 0; print "nonzero\n" unless $i == 0; |
none | puts 'positive' if i > 0 puts 'nonzero' unless i == 0 |
raise exception |
throw new Exception("bad arg"); | die "bad arg"; | raise Exception("bad arg") | # raises RuntimeError raise "bad arg" |
catch exception |
try { risky(); } catch (Exception $e) { echo 'risky failed: ', $e->getMessage(), "\n"; } |
eval { risky }; if ($@) { print "risky failed: $@\n"; } |
try: risky() except: print("risky failed") |
# catches StandardError begin risky rescue print "risky failed: " puts $!.message end |
global variable for last exception | none | $EVAL_ERROR: $@ $OS_ERROR: $! $CHILD_ERROR: $? |
none | last exception: $! backtrace array of exc.: $@ exit status of child: $? |
define exception | class Bam extends Exception { function __construct() { parent::__construct("bam!"); } } |
none | class Bam(Exception): def __init__(self): super(Bam, self).__init__("bam!") |
class Bam < Exception def initialize super("bam!") end end |
catch exception by type | try { throw new Bam; } catch (Bam $e) { echo $e->getMessage(), "\n"; } |
none | try: raise Bam() except Bam as e: print(e) |
begin raise Bam.new rescue Bam => e puts e.message end |
finally/ensure |
none | none | try: acquire_resource() risky() finally: release_resource() |
begin acquire_resource risky ensure release_resource end |
uncaught exception behavior |
stderr and exit | stderr and exit | stderr and exit | |
start thread |
none | use threads; $f = sub { sleep 10 }; $t = threads->new($f); |
class sleep10(threading.Thread): def run(self): time.sleep(10) t = sleep10() t.start() |
t = Thread.new { sleep 10 } |
wait on thread |
none | $t->join; | t.join() | t.join |
environment and i/o | ||||
php | perl | python | ruby | |
external command |
exec('ls'); | system('ls'); | import os os.system('ls') |
system('ls') |
backticks |
$files = `ls`; | my $files = `ls`; | import os os.popen('ls').read() |
files = `ls` |
command line args, script name |
count($argv) $argv[0] $argv[1] … $_SERVER["SCRIPT_NAME"] |
$#ARGV + 1 $ARGV[0] $ARGV[1] … $0 |
import sys len(sys.argv)-1 sys.argv[1] sys.argv[2] … sys.argv[0] |
ARGV.size ARGV[0] ARGV[1] … $0 |
print to standard out |
echo "hi world\n"; | print "hi world\n"; | print("hi world") | puts "hi world" |
standard filehandles |
$stdin = fopen('php://stdin','r'); $stdout = fopen('php://stdout','w'); $stderr = fopen('php://stderr','w'); |
STDIN STDOUT STDERR | import sys sys.stdin sys.stdout sys.stderr |
$stdin $stdout $stderr |
open file |
$f = fopen('/etc/hosts','r'); | open FILE, '/etc/hosts'; | f = open('/etc/hosts') | f = File.open('/etc/hosts') or File.open('/etc/hosts') { |f| |
open file for writing |
$f = fopen('/tmp/php_test','w'); | open FILE, ">/tmp/perl_test"; | f = open('/tmp/test','w') | f = File.open('/tmp/test','w') or File.open('/tmp/test','w') { |f| |
close file |
fclose($f); | close FILE; | f.close() | f.close |
read line |
$line = fgets($f); | $line = <FILE> | f.readline() | f.gets |
iterate over a file by line |
while (!feof($f)) { $line = fgets($f); |
while ($line = <FILE>) { | for line in f: | f.each do |line| |
chomp |
chop($line); | chomp $line; | line = line.rstrip('\r\n') | line.chomp! |
read entire file into array or string | $a = file('/etc/hosts'); $s = file_get_contents('/etc/hosts'); |
@a = <FILE>; $/ = undef; $s = <FILE>; |
a = f.readlines() s = f.read() |
a = f.lines.to_a s = f.read |
write to file |
fwrite($f, 'hello'); | print FILE "hello"; | f.write('hello') | f.write('hello') |
flush file |
use IO::Handle; FILE->flush(); |
f.flush() | f.flush | |
environment variable |
getenv('HOME') | $ENV{'HOME'} | import os os.getenv('HOME') |
ENV['HOME'] |
exit |
exit 0; | exit 0; | import sys sys.exit(0) |
exit(0) |
set signal handller |
$SIG{INT} = sub { die "exiting…\n"; }; |
import signal def handler(signo, frame): print("exiting…") exit -1 signal.signal(signal.SIGINT, handler) |
Signal.trap("INT", lambda { |signo| puts "exiting…"; exit }) | |
libraries and modules | ||||
php | perl | python | ruby | |
load library |
require_once('foo.php'); | require 'Foo.pm'; # or require Foo; # or use Foo; |
import foo | require 'foo' # or require 'foo.rb' |
reload library |
require('foo.php'); | do 'Foo.pm'; | reload(foo) | load 'foo.rb' |
library path |
$o = ini_get('include_path'); $n = $o . ':/some/path'; ini_set('include_path', $n); |
push @INC, '/some/path'; | import sys sys.path.append('/some/path') |
$: << '/some/path' |
library path environment variable | none | PERL5LIB | PYTHONPATH | RUBYLIB |
library path command line option | none | -I | none | -I |
main in library | unless (caller) { code } |
if __name__ == "__main__": code |
if $0 == __FILE__ code end |
|
module declaration |
namespace Foo; | package Foo; require Exporter; our @ISA = ("Exporter"); our @EXPORT_OK = ('bar', 'baz'); |
put declarations in foo.py | class Foo or module Foo |
submodule declaration | namespace Foo\Bar; | package Foo::Bar; | create directory foo in library path containing file bar.py | module Foo::Bar or module Foo module Bar |
module separator |
\Foo\Bar\baz(); | Foo::Bar::baz(); | foo.bar.baz() | Foo::Bar.baz |
import module |
none, but a long module name can be shortened | # imports symbols in @EXPORT: use Foo; |
from foo import * | |
import definitions |
only class names can be imported | # bar and baz must be in # @EXPORT or @EXPORT_OK: use Foo ('bar', 'baz'); |
from foo import bar, baz | none |
managing multiple installations | $ virtualenv -p /usr/bin/python foo $ source foo/bin/activate |
|||
list installed packages, install a package |
$ pear list $ pear install Math_BigInteger |
$ perldoc perllocal $ cpan -i Moose |
$ pip freeze $ pip install jinja2 |
$ gem list $ gem install rails |
objects | ||||
php | perl | python | ruby | |
define class |
class Int { public $value; function __construct($int=0) { $this->value = $int; } } |
package Int; use Moose; has 'value' => ( is => 'rw' ); around BUILDARGS => sub { my $orig = shift; my $class = shift; my $v = $_[0] || 0; $class->$orig(value => $v); }; no Moose; |
class Int: def __init__(self, v=0): self.value = v |
class Int attr_accessor :value def initialize(i=0) @value = i end end |
create object |
$i = new Int(); | my $i = new Int(); # or my $i = Int->new(); |
i = Int() | i = Int.new |
get and set attribute |
$v = $i->value; $i->value = $v+1; |
my $v = $i->value; $i->value($v+1); |
v = i.value i.value = v+1 |
v = i.value i.value = v+1 |
instance variable accessibility | must be declared | private by default | public; attributes starting with underscore private by convention | private by default; use attr_reader, attr_writer, attr_accessor to make public |
define method |
function plus($i) { return $this->value + $i; } |
# in package: sub plus { my $self = shift; $self->value + $_[0]; } |
def plus(self,v): return self.value + v |
def plus(i) value + i end |
invoke method |
$i->plus(7) | $i->plus(7) | i.plus(7) | i.plus(7) |
destructor |
function __destruct() { echo "bye, $this->value\n"; } |
# in package: sub DEMOLISH { my $self = shift; my $v = $self->value; print "bye, $v\n"; } |
def __del__(self): print("bye, %", self.value) |
val = i.value ObjectSpace.define_finalizer(int) { puts "bye, #{val}" } |
method missing |
function __call($name, $args) { $argc = count($args); echo "no def: $name " . "arity: $argc\n"; } |
# in package: our $AUTOLOAD; sub AUTOLOAD { my $self = shift; my $argc = scalar(@_); print "no def: $AUTOLOAD" . " arity: $argc\n"; } |
def __getattr__(self, name): s = "no def: "+name+" arity: %d" return lambda *a: print(s % len(a)) |
def method_missing(name, *a) puts "no def: #{name}" + " arity: #{a.size}" end |
inheritance |
class Counter extends Int { private static $instances = 0; function __construct($int=0) { Counter::$instances += 1; parent::__construct($int); } function incr() { $this->value++; } static function getInstances() { return $instances; } } |
package Counter; use Moose; extends 'Int'; my $instances = 0; sub BUILD { $instances += 1; } sub incr { my $self = shift; my $v = $self->value; $self->value($v + 1); } sub instances { $instances; } no Moose; |
class Counter(Int): instances = 0 def __init__(self, v=0): Counter.instances += 1 Int.__init__(self, v) def incr(self): self.value += 1 |
class Counter < Int @@instances = 0 def initialize @@instances += 1 super end def incr self.value += 1 end def self.instances @@instances end end |
invoke class method |
Counter::getInstances() | Counter->instances(); | Counter.instances | Counter.instances |
reflection | ||||
php | perl | python | ruby | |
class |
get_class($a) | ref $a | type(a) | a.class |
has method? |
method_exists($a, 'reverse') | $a->can('reverse') | hasattr(a,'reverse') | a.respond_to?('reverse') |
message passing |
for ($i = 1; $i <= 10; $i++) { call_user_func(array($a, "phone$i"), NULL); } |
for $i (0..10) { $meth = "phone$i"; $a->$meth(undef); } |
for i in range(1,10): getattr(a,"phone"+str(i))(None) |
(1..9).each do |i| a.send("phone#{i}="nil) } |
eval |
while(<>) { print ((eval), "\n"); } |
while True: print(eval(sys.stdin.readline())) |
loop do puts eval(gets) end |
|
methods |
$class = ref($a); keys eval "%${class}::"; |
[m for m in dir(a) if callable(getattr(a,m))] | a.methods | |
attributes |
keys %$a; | dir(a) | a.instance_variables | |
pretty print |
$d = array('foo'=>1, 'bar'=>array(2,3)); print_r($d); |
use Data::Dumper; %d = (foo=>1, bar=>[2, 3]); print Dumper(\%d); |
import pprint d = {'foo':1, 'bar':[2,3] } pprint.PrettyPrinter().pprint(d) |
require 'pp' d = { 'foo'=>1, 'bar'=>[2,3] } pp d |
source line number and file name | __LINE__ __FILE__ |
__LINE__ __FILE__ |
import inspect c = inspect.currentframe() c.f_lineno c.f_code.co_filename |
__LINE__ __FILE__ |
check syntax |
$ php -l foo.php | $ perl -c foo.pl | # precompile to bytecode: import py_compile py_compile.compile("foo.py") |
$ ruby -c foo.rb |
flags for stronger and strongest warnings | none | $ perl -w foo.pl $ perl -W foo.pl |
$ python -t foo.py $ python -3t foo.py |
$ ruby -w foo.rb $ ruby -W2 foo.rb |
web | ||||
php | perl | python | ruby | |
http get |
$h = 'http://www.google.com'; $ch = curl_init($h); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); $output |
require HTTP::Request; require LWP::UserAgent; $h = 'http://www.google.com'; $r = HTTP::Request->new(GET=>$h); $ua = LWP::UserAgent->new; $resp = $ua->request($r); $resp->content() |
import httplib h = 'www.google.com' f = httplib.HTTPConnection(h) f.request("GET",'/') f.getresponse().read() |
require 'net/http' h = 'www.google.com' r = Net::HTTP.start(h, 80) do |f| f.get('/') end r.body |
url encode/decode |
urlencode("hello world"); urldecode("hello+world"); |
use CGI; CGI::escape('hello world') CGI::unescape('hello+world') |
import urllib urllib.quote_plus("hello world") urllib.unquote_plus("hello+world") |
require 'cgi' CGI::escape('hello world'); CGI::unescape('hello+world'); |
build xml | $x = '<a></a>'; $d = new SimpleXMLElement($x); $d->addChild('b', 'foo'); echo $d->asXML(); |
# not ported to python 3 from xmlbuilder import XMLBuilder builder = XMLBuilder() with builder.a: with builder.b: builder << "foo" print(str(builder)) |
# gem install builder require 'builder' builder = Builder::XmlMarkup.new xml = builder.a do |child| child.b("foo") end puts xml |
|
parse xml | $x = '<a><b>foo</b></a>'; $d = simplexml_load_string($x); foreach ($d->children() as $c) { break; } echo $c; |
# download XML::Simple from CPAN: use XML::Simple; $xml = new XML::Simple; $s = '<a><b>foo</b></a>'; $doc = $xml->XMLin($s); print $doc->{'b'}; |
from xml.etree import ElementTree xml = '<a><b>foo</b></a>' doc = ElementTree.fromstring(xml) print(doc[0].text) |
require 'rexml/document' xml = '<a><b>foo</b></a>' doc = REXML::Document.new(xml) puts doc[0][0].text |
xpath | $x = '<a><b><c>foo</c></b></a>'; $d = simplexml_load_string($x); $n = $d->xpath('/a/b/c'); echo $n[0]; |
from xml.etree import ElementTree xml = '<a><b><c>foo</c></b></a>' doc = ElementTree.fromstring(xml) node = doc.find("b/c") print(node.text) |
require 'rexml/document' include REXML xml = '<a><b><c>foo</c></b></a>' doc = Document.new(xml) node = XPath.first(doc,'/a/b/c') puts node.text |
|
json | $a = array('t'=>1, 'f'=>0); $s = json_encode($a); $d = json_decode($s, TRUE); |
# download JSON from CPAN: use JSON; $raw = { 't' => 1, 'f' => 0 }; $json = JSON->new->allow_nonref; $s = $json->encode($raw); $d = $json->decode($s); |
import json s = json.dumps({'t':1, 'f':0}) d = json.loads(s) |
require 'json' s = {'t'=> 1,'f'=> 0}.to_json d = JSON.parse(s) |
__________________________________________ | __________________________________________ | __________________________________________ | __________________________________________ |
The versions used for testing code in the reference sheet.
How to get the version.
php:
The function phpversion() will return the version number as a string.
perl:
Also available in the predefined variable $], or in a different format in $^V and $PERL_VERSION.
python:
The following function will return the version number as a string:
import platform
platform.python_version()
ruby:
Also available in the global constant VERSION (ruby 1.8.7) or RUBY_VERSION (ruby 1.9.1).
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 ?>.
The customary name of the repl.
php:
Submit each line of code to php -a as <?= php code ?> to have the line executed as php code and the result displayed.
perl:
The perl repl lacks readline and does not save or display the result of an expression. Actually, 'perl -d' runs the perl debugger, and 'perl -e' runs code provided on the command line.
python:
The python repl saves the result of the last statement in _.
ruby:
irb saves the result of the last statement in _.
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.
python:
Newline does not terminate a statement when:
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:
Ruby permits newlines in array [] or hash literals, but only after a comma , or associator =>. Putting a newline before the comma or associator results in a syntax error.
A newline that would normally terminate a statement can be escaped with a backslash.
How blocks are delimited.
perl:
Curly brackets {} delimit blocks. They are also used for:
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 encouters 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.
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.
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;
python:
If the variable on the left has not previously been defined in the current scope, then it is created. This may hide a variable in a containing scope.
Assignment does not return a value and cannot be used in an expression. Thus, assignment cannot be used in a conditional test, removing the possibility of using assignment (=) in place of an equality test (==). Assignments can nevertheless be chained to assign a value to multiple variables:
a = b = 3
ruby:
Assignment operators have right precedence and evaluate to the right argument, so they can be chained. If the variable on the left does not exist, then it is created.
How to assign values to variables in parallel.
python:
The r-value can be a list or tuple:
nums = [1,2,3]
a,b,c = nums
more_nums = (6,7,8)
d,e,f = more_nums
Nested sequences of expression can be assigned to a nested sequences of l-values, provided the nesting matches. This assignment will set a to 1, b to 2, and c to 3:
(a,[b,c]) = [1,(2,3)]
This assignment raises a TypeError:
ruby:
The r-value can be an array:
nums = [1,2,3]
a,b,c = nums
How to swap the values held by two variables.
Compound assignment operators mutate a variable, setting it to the value of an operation which takes the value of the variable as an argument.
First row: arithmetic operator assignment: addition, subtraction, multiplication, (float) division, integer division, modulus, and exponentiation.
Second row: string concatenation assignment and string replication assignment
Third row: logical operator assignment: and, or, xor
Fourth row: bit operator assignment: left shift, right shift, and, or, xor.
python:
Python compound assignment operators do not return a value and hence cannot be used in expressions.
php:
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--;
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--;
ruby:
The Integer class defines succ, pred, and next, which is a synonym for succ.
The String class defines succ, succ!, next, and next!. succ! and next! mutate the string.
How to declare variables which are local to the scope defining region which immediately contain them.
php:
Variables do not need to be declared and there is no syntax for declaring a local variable. If a variable with no previous reference is accessed, its value is NULL.
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. local declarations became obsolete with the introduction of the my declaration introduced in Perl 5.
python:
A variable is created by assignment if one does not already exist. If the variable is inside a function or method, then its scope is the body of the function or method. Otherwise it is a global.
ruby:
Variables are created by assignment. If the variable does not have a dollar sign ($) or ampersand (@) as its first character then its scope is scope defining region which most immediately contains it.
A lower case name can refer to a local variable or method. If both are defined, the local variable takes precedence. To invoke the method make the receiver explicit: e.g. self.name. However, outside of class and modules local variables hide functions because functions are private methods in the class Object. Assignment to name will create a local variable if one with that name does not exist, even if there is a method name.
A list of regions which define a scope for the local variables they contain.
Local variables defined inside the region are only in scope while code within the region is executing. If the language does not have closures, then code outside the region has no access to local variables defined inside the region. If the language does have closures, then code inside the region can make local variables accessible to code outside the region by returning a reference.
A region which is top level hides local variables in the scope which contains it from the code it contains. A region can also be top level if the syntax requirements of the language prohibit it from being placed inside another scope defining region.
A region is nestable if it can be placed inside another cope defining region, and if code in the inner region can access local variables in the outer region.
php:
Only function bodies and method bodies define scope. Function definitions can be nested, but when this is done lexical variables in the outer function are not visible to code in the body of the inner function.
Braces can be used to set off blocks of codes in a manner similar to the anonymous blocks of Perl. However, these braces do not define a scope. Local variables created inside the braces will be visible to subsequent code outside of the braces.
Local variables cannot be created in class bodies.
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. In this way Perl resembles Ruby and contrasts with PHP and Python. In PHP and Python, any variable defined outside a function definition is global.
In Perl, 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.
python:
Only functions and methods define scope. Function definitions can be nested. When this is done, inner scopes have read access to variables defined in outer scopes. Attempting to write (i.e. assign) to a variable defined in an outer scope will instead result in a variable getting created in the inner scope. Python trivia question: what would happen if the following code were executed?
def foo():
v = 1
def bar():
print(v)
v = 2
print(v)
bar()
foo()
ruby:
Note that though the keywords if, unless, case, while, and until each define a block which is terminated by an end keyword, none of these blocks have their own scope.
Anonymous functions can be created with the lambda keyword. Ruby anonymous blocks can be provided after a function invocation and are bounded by curly brackets { } or the do and end keywords. Both anonymous functions and anonymous blocks can have parameters which are specified at the start of the block within pipes. Here are some examples:
id = lambda { |x| x }
[3,1,2,4].sort { |a,b| a <=> b }
10.times do |i|
print "#{i}..."
end
In Ruby 1.8, the scope of the parameter of an anonymous block or function or block is local to the block or function body if the name is not already bound to a variable in the containing scope. However, if it is, then the variable in the containing scope will be used. This behavior was changed in Ruby 1.9 so that parameters are always local to function body or block. Here is an example of code which behaves differently under Ruby 1.8 and Ruby 1.9:
x = 3
id = lambda { |x| x }
id.call(7)
puts x # 1.8 prints 7; 1.9 prints 3
Ruby 1.9 also adds the ability mark variables as local, even when they are already defined in the containing scope. All such variables are listed inside the parameter pipes, separated from the parameters by a semicolon:
x = 3
noop = lambda { |; x| x = 15 } # bad syntax under 1.8
noop.call
# x is still 3
How to declare and access a variable with global scope.
php:
A variable is global if it is used at the top level (i.e. outside any function definition) or if it is declared inside a function with the global keyword. A function must use the global keyword to access the 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.
python:
A variable is is global if it is defined at the top level of a file (i.e. outside any function definition). Although the variable is global, it must be imported individuality or be prefixed with the module name prefix to be accessed from another file. To be accessed from inside a function or method it must be declared with the global keyword.
ruby:
A variable is global if it starts with a dollar sign: $.
How to declare a constant.
php:
A constant can be declared inside a class:
class Math {
const pi = 3.14;
}
Refer to a class constant like this:
Math::pi
ruby:
Capitalized variables contain constants and class/module names. By convention, constants are all caps and class/module names are camel case. The ruby interpreter does not prevent modification of constants, it only gives a warning. Capitalized variables are globally visible, but a full or relative namespace name must be used to reach them: e.g. Math::PI.
How to create a comment that ends at the next newline.
How to comment out multiple lines.
python:
The triple single quote ''' and triple double quote """ syntax is a syntax for string literals.
The null literal.
How to test if a variable contains null.
php:
$v == NULL does not imply that $v is NULL, since any comparison between NULL and a falsehood will return true. In particular, the following comparisons are true:
$v = NULL;
if ($v == NULL) { echo "true"; }
$v = 0;
if ($v == NULL) { echo "sadly true"; }
$v = '';
if ($v == NULL) { echo "sadly true"; }
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"; }
The result of attempting to access an undefined variable.
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.
Literals for the booleans.
These are the return values of the comparison operators.
php:
Any identifier which matches TRUE case-insensitive can be used for the TRUE boolean. Similarly for FALSE.
In general, PHP variable names are case-sensitive, but function names are case-insensitive.
When converted to a string for display purposes, TRUE renders as "1" and FALSE as "". The equality tests TRUE == 1 and FALSE == "" evaluate as TRUE but the equality tests TRUE === 1 and FALSE === "" evaluate as FALSE.
Values which behave like the false boolean in a conditional context.
Examples of conditional contexts are the conditional clause of an if statement and the test of a while loop.
python:
Whether a object evaluates to True or False in a boolean context can be customized by implementing a __nonzero__ instance method for the class.
Logical and, or, and not.
php, perl, ruby:
&& and || have higher precedence than assignment, compound assignment, and the ternary operator (?:), which have higher precedence than and and or.
How to write a conditional expression. A ternary operator is an operator which takes three arguments. Since
condition ? true value : false value
is the only ternary operator in C, it is unambiguous to refer to it as the ternary operator.
python:
The Python conditional expression comes from Algol.
ruby:
The Ruby if statement is also an expression:
x = if x > 0
x
else
-x
end
Equality, inequality, greater than, less than, greater than or equal, less than or equal.
Also known as the relational operators.
php:
Most of the comparison operators will convert a string to a number if the other operand is a number. Thus 0 == "0" is true. The operators === and !== do not perform this conversion, so 0 === "0" is false.
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.
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.
How to convert string data to numeric data and vice versa.
php:
PHP 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.
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.
python:
float and int raise an error if called on a string and any part of the string is not numeric.
ruby:
to_i and to_f always succeed on a string, returning the numeric value of the digits at the start of the string, or zero if there are no initial digits.
The operators for addition, subtraction, multiplication, float division, integer division, modulus, and exponentiation.
How to get the integer quotient of two integers. How to get the integer quotient and remainder.
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;
How to perform floating point division, even if the operands might be integers.
Some arithmetic functions. Trigonometric functions are in radians unless otherwise noted. Logarithms are natural unless otherwise noted.
python:
Python also has math.log10. To compute the log of x for base b, use:
math.log(x)/math.log(b)
ruby:
Ruby also has Math.log2, Math.log10. To compute the log of x for base b, use
Math.log(x)/Math.log(b)
How to truncate a float to the nearest integer towards zero; how to round a float to the nearest integer; how to find the nearest integer above a float; how to find the nearest integer below a float; how to take the absolute value.
perl:
The CPAN module Number::Format provides a round function. The 2nd argument specifies the number of digits to the right of the radix. The default is 2.
use Number::Format 'round';
round(3.14, 0);
How to get the min and max.
What happens when division by zero is performed.
What happens when the largest representable integer is exceeded.
What happens when the largest representable float is exceeded.
The result of taking the square root of negative two.
How to create rational numbers and get the numerator and denominator.
ruby:
Require the library mathn and integer division will yield rationals instead of truncated integers.
python:
Most of the functions in math have analogues in cmath which will work correctly on complex numbers.
How to generate a random integer between 0 and 99, include, float between zero and one in a uniform distribution, or a float in a normal distribution with mean zero and standard deviation one.
The bit operators for left shift, right shift, and, inclusive or, exclusive or, and negation.
Binary, octal, and hex integer literals
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")
python
Python has the functions bin, oct, and hex which take an integer and return a string encoding the integer in base 2, 8, and 16.
bin(42)
oct(42)
hex(42)
The syntax for string literals.
Whether newlines are permitted in string literals.
python:
Newlines are not permitted in single quote and double quote string literals. A string can continue onto the following line if the last character on the line is a backslash. In this case, neither the backslash nor the newline are taken to be part of the string.
Triple quote literals, which are string literals terminated by three single quotes or three double quotes, can contain newlines:
'''This is
two lines'''
"""This is also
two lines"""
Backslash escape sequences for inserting special characters into string literals.
python:
Before python 3, it was possible to enter a character by Unicode point using the following syntax:
u'\u03bb'
How to interpolate variables into strings.
python:
Python lacks interpolating quotes. Except for the fact that they can contain single quotes, double quotes are identical to single quotes.
How to specify custom delimiters 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.
How to create a string using a printf style format.
python:
Escape curly braces by doubling:
'to insert parameter {0} into a format, use {{{0}}}'.format(3)
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 identifer in single quotes to prevent variable interpolation and backslash escape interpretation:
s = <<'EOF';
Perl code uses variables with dollar
signs, e.g. $var
EOF
python:
Python lacks variable interpolation in strings. Triple quotes honor the same backslash escape sequences as regular quotes,
so triple quotes can otherwise be used like here documents:
s = '''here document
there computer
'''
ruby:
Put the customer identifier in single quotes to prevent variable interpolation and backslash escape interpretation:
s = <<'EOF'
Ruby code uses #{var} type syntax
to interpolate variables into strings.
EOF
The string concatenation operator.
The string replication operator.
How to split a string containing a separator into an array of substrings.
ruby:
The argument to split can be a string or regular expression. A 2nd argument will put a limit on the number of elements in the array; the last element will contain the reaminder of the string. To split a string into an array of single character strings, use
"abcdefg".split('')
How to concatenate the elements of an array into a string with a separator.
How to put a string into all caps or all lower case letters. How to capitalize the first letter of a string.
How to remove whitespace from the ends of a string.
How to pad the edge of a string with spaces so that it is a prescribed length.
How to get the length in characters of a string.
How to find the index of the leftmost occurrence of a substring in a string.
How to extract a substring from a string by index.
How to extract a character from a string by its index.
Converting characters to ASCII codes and back.
The languages in this reference sheet do not have character literals, so characters are represented by strings of length one.
how to count the number times a character occurs in a string
perl:
The translate characters tr operator returns the number of characters replaced. Normally it performs a destructive operation on the string, but not if the second half of the translation specification is empty.
How to apply a character mapping to a string.
How to test whether a string matches a regular expression.
perl:
The =~ operator performs the substitution in place on the string, and returns the number of substitutions performed.
python:
The 3rd argument of sub indicates the maximum number of substitutions to be performed. The default value is zero, in which case there is no limit to the number of substitutions performed.
ruby:
The sub operator returns a copy of the string with the substitution made, if any. The sub! performs the substitution on the original string and returns the modified string.
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.
ruby:
The gsub operator returns a copy of the string with the substitution made, if any. The gsub! performs the substitution on the original string and returns the modified string.
In ISO 8601 terminology, a date specifies a day in the Gregorian calendar and a time does not contain date information; it merely specifies a time of day. A data type which combines both date and time information is probably more useful than one which contains just date information or just time information; it is unfortunate that ISO 8601 doesn't provide a name for this entity. The word timestamp often gets used to denote a combined date and time. PHP and Python use the compound noun datetime for combined date and time values.
An useful property of ISO 8601 dates, times, and date/time combinations is that they are correctly ordered by a lexical sort on their string representations. This is because they are big-endian (the year is the leftmost element) and they used fixed-length fields for each term in the string representation.
The C standard library provides two methods for representing dates. The first is the UNIX epoch, which is the seconds since January 1, 1970 in UTC. If such a time were stored in a 32-bit signed integer, the rollover would happen on January 18, 2038.
The other method of representing dates is the tm struct, a definition of which can be found on Unix systems in /usr/include/time.h:
struct tm {
int tm_sec; /* seconds after the minute [0-60] */
int tm_min; /* minutes after the hour [0-59] */
int tm_hour; /* hours since midnight [0-23] */
int tm_mday; /* day of the month [1-31] */
int tm_mon; /* months since January [0-11] */
int tm_year; /* years since 1900 */
int tm_wday; /* days since Sunday [0-6] */
int tm_yday; /* days since January 1 [0-365] */
int tm_isdst; /* Daylight Savings Time flag */
long tm_gmtoff; /* offset from CUT in seconds */
char *tm_zone; /* timezone abbreviation */
};
Perl and Python both use and expose the tm struct of the standard library. In the case of Perl, the first nine values of the struct (up to the member tm_isdst) are put into an array. Python, meanwhile, has a module called time which is a thin wrapper to the standard library functions which operate on this struct. Here is how get a tm struct in Python:
import time
utc = time.gmtime(time.time())
t = time.localtime(time.time())
The tm struct is a low level entity, and interacting with it directly should be avoided. In the case of Python it is usually sufficient to use the datetime module instead. Avoiding the tm struct in Perl is a bit more difficult and might require downloading CPAN modules.
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. The modules Time::Local and Date::Parse can both be used to 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.
How to get the combined date and time for the present moment in both local time and UTC.
Do date/time values include timezone information. When a date/time value for the local time is created, how the local timezone is determined.
A date/time value can represent a local time but not have any timezone information associated with it.
On Unix systems processes determine the local timezone by inspecting the file /etc/localtime.
php:
The default timezone can also be set in the php.ini file.
date.timezone = "America/Los_Angeles"
Here is the list of timezones supported by PHP.
perl:
Although the tm struct from the standard library has a tm_zone member, the Perl tm array does not have a corresponding element.
How to format a timestamp as a string using the format notation of the strftime function from the standard C library. This same format notation is used by the Unix date command.
php:
PHP supports strftime but it also has its own time formatting system used by date, DateTime::format, and DateTime::createFromFormat. The letters used in the PHP time formatting system are described here.
How to parse a timestamp using the format notation of strptime function from the standard C library.
How to parse a date without providing a format string.
The data type that results when subtraction is performed on two combined date and time values.
perl
It is not useful to subtract arrays holding tm values as the arrays will first be converted to scalar values indicating their size.
How to add a time duration to a timestamp.
A time duration can easily be added to a date/time value when the value is a Unix epoch value.
ISO 8601 distinguishes between a time interval, which is defined by two date/time endpoints, and a duration, which is the length of a time interval and can be defined by a unit of time such as '10 minutes'. A time interval can also be defined by date and time representing the start of the interval and a duration.
ISO 8601 defines notation for durations. This notation starts with a 'P' and uses a 'T' to separate the day and larger units from the hour and smaller units. Observing the location relative to the 'T' is important for interpreting the letter 'M', which is used for both months and minutes.
perl
The technique illustrated, namely using an arithmetic expression to calculate the length of a duration in seconds, is probably the most practical one when working in Perl. There is also the following CPAN module:
use Time::Interval;
$now = time;
$now += convertInterval( minutes=>10, seconds=>3, ConvertTo=>"seconds");
How to convert the native timestamp type to the Unix epoch which is the number of seconds since the start of January 1, 1970 UTC.
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.
ruby
The Time class has a zone method which returns the time zone abbreviation for the object. There is a tzinfo gem which can be used to create timezone objects using the Olson database name. This can in turn be used to convert between UTC times and local times which are daylight saving aware.
How to get the microseconds component of a combined date and time value. The SI abbreviations for milliseconds and microseconds are ms and μs, respectively. The C standard library uses the letter u as an abbreviation for micro. Here is a struct defined in /usr/include/sys/time.h:
struct timeval {
time_t tv_sec; /* seconds since Jan. 1, 1970 */
suseconds_t tv_usec; /* and microseconds */
};
How to put the process to sleep for a specified number of seconds. Python and Ruby support sleeping for a fractional number of seconds.
php:
PHP provides usleep which takes an argument in microseconds:
usleep(500000);
perl:
The Perl standard library includes a version of sleep which supports fractional seconds:
use Time::HiRes qw(sleep);
sleep 0.5;
How to cause a process to timeout if it takes too long.
Scripting languages have the same basic container types but the terminology is not universal:
php | perl | python | ruby | |
---|---|---|---|---|
array | array | array, list | list, tuple, sequence | Array, Enumerable |
dictionary | array | hash | dict, mapping | Hash |
php:
PHP uses the same data structure for arrays and dictionaries.
perl:
array refers to a data type. list refers to a context.
python:
Python has the mutable list and the immutable tuple. Both are sequences. To be a sequence, a class must implement __getitem__, __setitem__, __delitem__, __len__, __contains__, __iter__, __add__, __mul__, __radd__, and __rmul__.
ruby:
Ruby provides an Array datatype. If a class defines an each iterator and a comparison operator <=>, then it can mix in the Enumerable module.
Array literal syntax.
perl:
Square brackets create an array and return a reference to it:
$a = [1,2,3]
The quote words operator, which is a literal for arrays of strings where each string contains a single word.
For languages without this operator, the easiest way to specify such an array of strings is provided.
How to get the number of elements in an array.
perl:
The idiomatic way to test whether an array is empty in perl:
if ( not @a ) {
print "@a is empty\n";
}
python:
The idiomatic way to test whether a list is empty in python:
if not a:
print "a is empty"
ruby:
The empty list evaluates to true in a condition test. Use the empty? predicate to determine if an array is empty:
if a.empty?
puts "a is empty"
end
How to access a value in an array by index.
perl:
A negative index refers to the length - index element.
python:
A negative index refers to the length - index element.
>>> a = [1,2,3]
>>> a[-1]
3
ruby:
A negative index refers to to the length - index element.
How to update the value at an index.
What happens when the value at an out-of-bounds index is refererenced.
perl:
Some techniques for getting the index of an array element.
How to slice a subarray from an array.
perl:
Perl does not directly support slices. Rather Perl arrays can take an array of indices as the index value. As a result 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)];
python:
Slices can leave the first or last index unspecified, in which case the first or last index of the sequence is used:
>>> a=[1,2,3,4,5]
>>> a[:3]
[1, 2, 3]
Python has notation for taking every nth element:
>>> a=[1,2,3,4,5]
>>> a[::2]
[1, 3, 5]
The third argument in the colon-delimited slice argument can be negative, which reverses the order of the result:
>>> a = [1,2,3,4]
>>> a[::-1]
[4, 3, 2, 1]
ruby:
There is notation for specifying the first index and the number of items in the slice
irb> nums = [1,2,3,4,5]
=> [1, 2, 3, 4, 5]
irb> nums[1,3]
=> [2, 3, 4]
How to slice to the end of an array.
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.
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.
How to create an array by concatenating two arrays; how to modify an array by concatenating another array to the end of it.
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 because it makes @$b and @a refer to the same array. To make @b and @a refer to the same array, use typeglobs:
*b = *a;
python:
The slice operator can be used to make a shallow copy:
c = a[:]
How arrays are passed as arguments.
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.
How to iterate through the elements of an array while keeping track of the index of each element.
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.
How to convert a range to an array.
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.
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]))
How to test for membership in an array.
How to compute an intersection.
python:
Python has a set data type which is built-in as of version 2.4. Furthermore, Python has literal syntax for sets: {1,2,3}.
The example computes the intersection by converting the lists to sets. The return value is a set; it can be converted to a list with the list constructor.
ruby:
The intersect operator & always produces an array with no duplicates.
python:
The python example computes the union by converting the lists to sets. The return value is a set; it can be converted to a list with the list constructor.
ruby:
The union operator | always produces an array with no duplicates.
Create an array by applying an function to each element of a source array.
ruby:
The map! method will apply the function to the elements of the source array in place.
Create an array containing the elements of a source array which match a predicate.
Return the result of applying a binary operator to all the elements of the array.
perl:
The reduce function was added in Perl 5.10.
How to test whether a condition holds for all members of an array. Always true for an empty array.
A universal test can be implemented with a filter: filter the set on the negation of the predicate and test whether the result is empty.
How to test whether an item in an array exists for which a condition holds. Always false for an empty array.
An existential test can be implemented with a filter: filter the set on the predicate and test whether the result is non-empty.
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 = array(1, 2, 3, 4);
$sample = array();
foreach (array_rand($a, 2) as $i) { array_push($sample, $a[$i]); }
How to interleave arrays. In the case of two arrays the result is an array of pairs or an associative list.
perl:
There is a zip function in List::MoreUtils, but it produces a flattened array instead of an array of arrays. In the following example @a contains 6 elements:
use List::MoreUtils 'zip';
@nums = (1,2,3);
@lets = ('a','b','c');
@a = zip @nums, @lets;
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']};
perl:
Curly brackets create a hash and return a reference to it:
$h = { 'hello' => 5, 'goodbye' => 7 }
How to get the number of dictionary keys in a dictionary.
How to lookup a dictionary value using a dictionary 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')}
What happens when a lookup is performed on a key that is not in a dictionary.
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.
How to remove a key/value pair from a dictionary.
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.
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.
How to iterate through the key/value pairs in a dictionary.
python:
If d contains a dictionary then d.items() returns the dictionary as an associative list and d.iteritems() returns an iterator on the dictionary as an associative list.
How to convert the keys of a dictionary to an array; how to convert the values of a dictionary to an array.
How to create a dictionary with a specified default value for missing keys.
perl:
How to use a tied hash. If the CPAN module Tie::ExtraHash is installed there is a shorter way.
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.
How to define a function.
How to invoke a function.
python:
When invoking methods and functions, 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.
Starting with 3.0, print is treated as a function instead of a keyword. Thus parens are mandatory around the print 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. As of Ruby 1.9, it is mandatory that the left paren not be separated from the method name by whitespace.
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.
python:
TypeError is raised if the number of arguments is incorrect.
ruby:
ArgumentError is raised if the number of arguments is incorrect.
How to declare a default value for an argument.
How to write a function which accepts a variable number of argument.
php:
It is also possible to use func_num_args and func_get_arg to access the arguments:
for ($i = 1; $i < func_num_args(); $i++) {
echo func_get_arg($i);
}
How to write a function which uses named parameters and how to invoke it.
python:
In a function definition, 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.
In a function definition the double splat operator ** collects named parameters into a dictionary. In a function invocation, the double splat expands a dictionary into named parameters.
ruby:
perl:
Scalars are passed by reference.
How to pass an array or dictionary without making a copy of it.
perl:
Arrays and hashes are not passed by reference by default. If an array is provided as a argument, each element of the array will be assigned to a parameter. A change to the parameter will change the corresponding value in the original array, but the number of elements in the array cannot be increased. To write a function which changes the size of the array the array must be passed by reference using the backslash notation.
When a hash is provided as a argument each key of the has will be assigned to a parameter and each value of the hash will be assigned to a parameter. In other words the number of parameters seen by the body of the function will be twice the size of the hash. Each value parameter will immediately follow its key parameter.
How the return value of a function is determined.
How to return multiple values from a function.
How to define and invoke 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 nest
n = make_nest(12*2)
print(n(23))
Python closures are read only.
How to create a function with private state which persists between function invocations.
How to create a first class function with access to the local variables of the local scope in which it was created.
python:
Python 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.
How to create a function which can yield a value back to its caller and suspend execution.
perl:
CPAN provides a module called Coro which implements coroutines. Some notes on the distinction between coroutines and generators.
python:
Python generators can be used in for/in statements and list comprehensions.
ruby:
Ruby generators are called fibers.
The if 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;
perl:
When an if block is the last statement executed in a subroutine, the return value is the value of the branch that executed.
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
1
else
0
end
The switch statement.
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);
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.
ruby:
Ruby provides a loop with no exit condition:
def yes(expletive="y")
loop do
puts expletive
end
end
Ruby also provides the until loop.
Ruby loops can be used in expression contexts but they always evaluate to nil.
How to write a C-style for loop.
break exits a for or while loop immediately. continue goes to the next iteration of the loop. redo goes back to the beginning of the current iteration.
A list of control structure keywords. The loop control keywords from the previous line are excluded.
The list summarizes the available control structures. It excludes the keywords for exception handling, loading libraries, and returning from functions.
How the do keyword is used.
perl:
The do keyword can convert an if statement to a conditional expression:
my $m = do {
if ($n) { 1 }
else { 0 }
};
Clauses added to the end of a statement to control execution.
Perl and Ruby have conditional statement modifers. Ruby also has looping statement modifers.
ruby:
Ruby has the looping statement modifiers while and until:
i = 0
i += 1 while i < 10
j = 10
j -= 1 until j < 0
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.
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
end
end
The global variable name for the last exception raised.
How to define a new variable class.
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.
Clauses that are guaranteed to be executed even if an exception is thrown or caught.
System behavior if an exception goes uncaught. Most interpreters print the exception message to stderr and exit with a nonzero status.
ruby:
Ruby 1.8 threads are green threads, and the interpreter is limited to a single operating system thread.
How to make a thread wait for another thread to finish.
When using tclsh as a shell or repl, external commands that do not have the same name as a built-in or user defined function can be executed directly without using the exec command.
How to invoke an external command and read its output into a variable.
The use of backticks for this operation goes back to the Bourne shell (1977).
python:
print appends a newline to the output. To suppress this behavior, put a trailing comma after the last argument. If given multiple arguments, print joins them with spaces.
ruby:
puts appends a newline to the output. print does not.
ruby:
When File.open is given a block, the file is closed when the block terminates.
Remove a newline, carriage return, or carriage return newline pair from the end of a line if there is one.
php:
chop removes all trailing whitespace. It is an alias for rtrim.
perl:
chomp modifies its argument, which thus must be a scalar, not a string literal.
python:
Python strings are immutable. rstrip returns a modified copy of the string. rstrip('\r\n') is not identical to chomp because it removes all contiguous carriage returns and newlines at the end of the string.
ruby:
chomp! modifies the string in place. chomp returns a modified copy.
How to read the contents of a file into memory.
How to write to a file handle.
How to flush a file handle that has been written to.
python:
It is possible to register code to be executed upon exit:
import atexit
atexit.register(print, "goodbye")
It is possible to terminate a script without executing registered exit code by calling os._exit.
ruby:
It is possible to register code to be executed upon exit:
at_exit { puts "goodbye" }
The script can be terminated without executing registered exit code by calling exit!.
How terminology is used in this sheet:
A few notes:
According to our terminology, Perl and Java packages are modules, not packages.
PHP and C++ namespaces are another of example of modules.
We prefer to reserve the term namespace for divisions of the set of names imposed by the parser. For example, the identifier foo in the Perl variables $foo and @foo belong to different namespaces. Another example of namespaces in this sense is the Lisp-1 vs. Lisp-2 distinction: Scheme is a Lisp-1 and has a single namespace, whereas Common Lisp is a Lisp-2 and has multiple namespaces.
Some languages (e.g. Python, Java) impose a one-to-one mapping between libraries and modules. All the definitions for a module must be in a single file, and there are typically restrictions on how the file must be named and where it is located on the filesystem. Other languages allow the definitions for a module to be spread over multiple files or permit a file to contain multiple modules. Ruby and C++ are such languages.
Execute the specified file. Normally this is used on a file which only contains declarations at the top level.
php:
include_once behaves like require_once except that it is not fatal if an error is encountered executing the library.
If it is desirable to reload the library even if it might already have been loaded, use require or include.
perl:
The last expression in a perl library must evaluate to true. When loading a library with use, the suffix of the file must be .pm.
The do directive will re-execute a library even if it has already been loaded.
How to reload a library. Altered definitions in the library will replace previous versions of the definition.
How to augment the library path by calling a function or manipulating a global variable.
How to augment the library path by setting an environment variable before invoking the interpreter.
How to augment the library path by providing a command line option when invoking the interpreter.
How to put code in a library which executes when the file is run as a top-level script and not when the file is loaded as a library.
How to declare a section of code as belonging to a module.
How to declare a section of code as belonging to a submodule.
The punctuation used to separate the labels in the full name of a submodule.
How to import all the definitions in a module.
How to import specific definitions from a module.
How to manage multiple versions of the interpreter on the same machine, or the same interpreter with a different set of installed 3rd party packages.
python:
Virtualenv must be downloaded and installed. It is a tarball and it only works on Unix.
How to show the installed 3rd party packages, and how to install a new 3rd party package.
perl
cpanm is an alternative to cpan which is said to be easier to use.
How to use cpan to install cpanm:
$ sudo cpan -i App::cpanminus
How to install a module with cpanm:
$ sudo cpanm Moose
python
Another way to get the installed modules:
$ python
>>> help('modules')
A Unix specific way to install a Python module that bypasses package management:
$ tar xf libxml2-python-2.6.0.tar.gz
$ cd libxml2-python-2.6.0
$ sudo python setup.py install
php:
Properties (i.e. instance variables) must be declared public, protected, or private. Methods can optionally be declared public, protected, or private. Methods without a visibility modifier are public.
perl:
The cheatsheet shows how to create objects using the CPAN module Moose. To the client, a Moose object behaves like a traditional Perl object; it's when a class needs to be defined that Moose code looks different from traditional Perl code.
Moose provides these additional features:
Moose objects are illustrated instead of Perl objects because Moose is used by the Catalyst web framework, and some of the features in Moose are in the Perl 6 object system. Here is how to define a class in the traditional Perl way:
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'};
}
sub add {
my $self = shift;
$self->value + $_[0];
}
sub DESTROY {
my $self = shift;
my $v = $self->value;
print "bye, $v\n";
}
python:
As of Python 2.2, classes are of two types: new-style classes and old-style classes. The class type is determined by the type of class(es) the class inherits from. If no superclasses are specified, then the class is old-style. As of Python 3.0, all classes are new-style.
New-style classes have these features which old-style classes don't:
perl:
Other getters:
$i->value()
$i->{'value'}
Other setters:
$i->{'value'} = $v;
python:
Defining explicit setters and getters in Python is considered poor style. If it becomes necessary to extra logic to attribute, this can be achieved without disrupting the clients of the class by creating a property:
def getValue(self):
print("getValue called")
return self.__dict__['value']
def setValue(self,v):
print("setValue called")
self.__dict__['value'] = v
value = property(fget=getValue, fset = setValue)
perl:
If the method does not take any arguments, the parens are not necessary to invoke the method.
perl:
Perl destructors are called when the garbage collector reclaims the memory for an object, not when all references to the object go out of scope. In traditional Perl OO, the destructor is named DESTROY, but in Moose OO it is named DEMOLISH.
python:
Python destructors are called when the garbage collector reclaims the memory for an object, not when all references to the object go out of scope.
ruby:
Ruby lacks a destructor. It is possible to register a block to be executed before the memory for an object is released by the garbage collector. A ruby
interpreter may exit without releasing memory for objects that have gone out of scope and in this case the finalizer will not get called. Furthermore, if the finalizer block holds on to a reference to the object, it will prevent the garbage collector from freeing the object.
php:
Define the method __callStatic to handle calls to undefined class methods.
python:
__getattr__ is invoked when an attribute (instance variable or method) is missing. By contrast, __getattribute__, which is only available in Python 3, is always invoked, and can be used to intercept access to attributes that exist. __setattr__ and __delattr__ are invoked when attempting to set or delete attributes that don't exist. The del statement is used to delete an attribute.
ruby:
Define the method self.method_missing to handle calls to undefined class methods.
perl:
Here is how inheritance is handled in traditional Perl OO:
package Counter;
our @ISA = "Int";
my $instances = 0;
our $AUTOLOAD;
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;
}
sub AUTOLOAD {
my $self = shift;
my $argc = scalar(@_);
print "undefined: $AUTOLOAD " .
"arity: $argc\n";
}
perl:
$a->can() returns a reference to the method if it exists, otherwise it returns undef/.
python:
hasattr(o,'reverse') will return True if there is an instance variable named 'reverse'.
perl:
The following code
$class = ref($a);
keys eval "%${class}::";
gets all symbols defined in the namespace of the class of which $a is an instance. The can method can be used to narrow the list to instance methods.
perl:
keys %$a assumes the blessed object is a hash reference.
python:
dir(o) returns methods and instance variables.
How to display the contents of a data structure for debugging purposes.
How to get the current line number and file name of the source code.
How to check the syntax of code without executing it.
Flags to increase the warnings issued by the interpreter:
python:
The -t flag warns about inconsistent use of tabs in the source code. The -3 flag is a Python 2.X option which warns about syntax which is no longer valid in Python 3.X.
PHP Manual
General Style and Syntax Codeigniter
Coding Standards Pear
PHP Style Guide Apache
perldoc
core modules
man perlstyle
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 scalar to an array will set 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 always 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 '=>' 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 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:
2.6: Language, Standard Library
2.7: Language, Standard Library
Why Python3 Summary of Backwardly Non-compatible Changes in Python 3
3.2: Language, Standard Library
PEP 8: Style Guide for Python Code van Rossum
Python uses leading whitespace to indicate block structure. It is not recommended to mix tabs and spaces in leading whitespace, but when this is done, a tab is equal to 8 spaces. The command line options '-t' and '-tt' will warn and raise an error respectively when tabs are used inconsistently for indentation.
Regular expressions and functions for interacting with the operating system are not available by default and must be imported to be used, i.e.
import re, sys, os
Identifiers in imported modules must be fully qualified unless imported with from/import:
from sys import path
from re import *
There are two basic sequence types: the mutable list and the immutable tuple. The literal syntax for lists uses square brackets and commas [1,2,3] and the literal syntax for tuples uses parens and commas (1,2,3).
The dictionary data type literal syntax uses curly brackets, colons, and commas { “hello”:5, “goodbye”:7 }. Python 3 adds a literal syntax for sets which uses curly brackets and commas: {1,2,3}. Dictionaries and sets are implemented using hash tables and as a result 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.
1.8.7 core, stdlib
1.9 core, stdlib
Ruby Style Neukirchen
The Unofficial Ruby Usage Guide Macdonald
Ruby consistently treats all values as objects. Classes are objects. Methods, however, are not objects. The system provided classes are open: i.e. the user can add methods to String, Array, or Fixnum. Another difference from python (and perl) is that ruby only permits single inheritance. However, 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.
In ruby, there is no difference between named functions and methods: top level ‘functions’ are in fact methods defined on the main object. All methods have a receiver which can be referenced with the self: the receiver does not needed to be treated as an argument like in perl and python.
Ruby has syntax which aids functional programming: a ruby method invocation can be followed by a block, which is a closure. The invoked method can call the block with yield(arg1,…). Also, the invoked method can store the block in a variable if its signature ends with &<varname>. The block can then be invoked with <varname>.call(arg1,…).