Tuesday, 23 June 2015
JavaScript, PHP, Python, Ruby complete basic syntaxt guide with interpretation in one sheet
JavaScript, PHP, Python, Ruby |
version | ||||
---|---|---|---|---|
javascript | php | python | ruby | |
version used | 5.5 | 2.7; 3.3 | 1.9; 2.0 | |
show version | $ node --version | $ php --version | $ python -V $ python --version | $ ruby --version |
implicit prologue | <script src="underscore.js"> </script> | none | import os, re, sys | none |
grammar and execution | ||||
javascript | php | python | ruby | |
interpreter | $ node foo.js | $ php -f foo.php | $ python foo.py | $ ruby foo.rb |
repl | $ node mac: $ osascript -l JavaScript -i | $ php -a | $ python | $ irb |
command line program | $ node -e 'var sys = require("sys"); sys.puts("hi world!");' mac: $ osascript -l JavaScript -e '1 + 1' | $ php -r 'echo "hi\n";' | $ python -c 'print("hi")' | $ ruby -e 'puts "hi"' |
block delimiters | {} | {} | : and offside rule | {} do end |
statement separator | ; or newline newline not separator inside (), [], {}, "", '', or after binary operator newline sometimes not separator when following line would not parse as a valid statement | ; statements must be semicolon terminated inside {} | newline or ; newlines not separators inside (), [], {}, triple quote literals, or after backslash: \ | newline or ; newlines not separators inside (), [], {}, ``, '', "", or after binary operator or backslash: \ |
source code encoding | none | Python 3 source is UTF-8 by default # -*- coding: utf-8 -*- | Ruby 2.0 source is UTF-8 by default # -*- coding: utf-8 -*- | |
end-of-line comment | // comment | // comment # comment | # comment | # comment |
multiple line comment | /* line another line */ | /* comment line another line */ | use triple quote string literal: '''comment line another line''' | =begin comment line another line =end |
variables and expressions | ||||
javascript | php | python | ruby | |
local variable | var x = 1; var y = 2, z = 3; | # in function body: $v = NULL; $a = []; $d = []; $x = 1; list($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 lexical scope | top level: html page nestable: function | top level: function or method body nestable (with use clause): anonymous function body | nestable (read only): function or method body | top level: file class block module block method body nestable: anonymous function body anonymous block |
global variable | // assign without using var g = 1; function incr_global () { g++; } | list($g1, $g2) = [7, 8]; function swap_globals() { global $g1, $g2; list($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 | none | define("PI", 3.14); const PI = 3.14; | # uppercase identifiers # constant by convention PI = 3.14 | # warning if capitalized # identifier is reassigned PI = 3.14 |
assignment | x = 1; | $v = 1; | assignments can be chained but otherwise don't return values: v = 1 | v = 1 |
parallel assignment | none | list($x, $y, $z) = [1 ,2, 3]; # 3 is discarded: list($x, $y) = [1, 2, 3]; # $z set to NULL: list($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 discarded: x, y = 1, 2, 3 # z set to nil: x, y, z = 1, 2 |
swap | tmp = x; x = y; y = tmp; | list($x, $y) = [$y, $x]; | x, y = y, x | x, y = y, x |
compound assignment arithmetic, string, logical, bit | += -= *= /= none %= += none <<= >>= &= |= ^= | += -= *= none /= %= **= .= none &= |= none <<= >>= &= |= ^= | # do not return values: += -= *= /= //= %= **= += *= &= |= ^= <<= >>= &= |= ^= | += -= *= /= none %= **= += *= &&= ||= ^= <<= >>= &= |= ^= |
increment and decrement | var x = 1; var y = ++x; var z = --y; | $x = 1; $y = ++$x; $z = --$y; | none | x = 1 # x and y not mutated: y = x.succ z = y.pred |
null | null | NULL # case insensitive | None | nil |
null test | v === null | is_null($v) ! isset($v) | v == None v is None | v == nil v.nil? |
undefined variable | undefined | NULL | raises NameError | raises NameError |
conditional expression | x > 0 ? x : -x | $x > 0 ? $x : -$x | x if x > 0 else -x | x > 0 ? x : -x |
arithmetic and logic | ||||
javascript | php | python | ruby | |
true and false | true false | TRUE FALSE # case insensitive | True False | true false |
falsehoods | false null undefined "" 0 NaN | FALSE NULL 0 0.0 "" "0" [] | False None 0 0.0 '' [] {} | false nil |
logical operators | && || ! | && || ! lower precedence: and or xor | and or not | && || ! lower precedence: and or not |
relational operators | === !== < > >= <= perform type coercion: == != | == != or <> > < >= <= no conversion: === !== | relational operators are chainable: == != > < >= <= | == != > < >= <= |
min and max | Math.min(1, 2, 3) Math.max(1, 2, 3) Math.min.apply(Math, [1, 2, 3]) Math.max.apply(Math, [1, 2, 3]) | 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 |
three value comparison | none | none | removed from Python 3: cmp(0, 1) cmp('do', 're') | 0 <=> 1 "do" <=> "re" |
arithmetic operators addition, subtraction, multiplication, float division, quotient, remainder | + - * / none % | + - * / none % | + - * see note // % Python 2 does not have an operator which performs float division on integers. In Python 3 / always performs float division. | + - * x.fdiv(y) / % |
integer division | Math.floor(x / y) | (int)(13 / 5) | 13 // 5 | 13 / 5 |
divmod | none | none | q, r = divmod(13, 5) | q, r = 13.divmod(5) |
integer division by zero | returns assignable value Infinity, NaN, or -Infinity depending upon whether dividend is positive, zero, or negative. There are literals for Infinity and NaN. | returns FALSE with warning | raises ZeroDivisionError | raises ZeroDivisionError |
float division | 13 / 5 | 13 / 5 | float(13) / 5 # Python 3: 13 / 5 | 13.to_f / 5 or 13.fdiv(5) |
float division by zero | same behavior as for integers | returns FALSE with warning | raises ZeroDivisionError | returns -Infinity, NaN, or Infinity |
power | Math.pow(2, 32) | pow(2, 32) | 2**32 | 2**32 |
sqrt | Math.sqrt(2) | sqrt(2) | import math math.sqrt(2) | include Math sqrt(2) |
sqrt -1 | NaN | NaN | # raises ValueError: import math math.sqrt(-1) # returns complex float: import cmath cmath.sqrt(-1) | raises Errno::EDOM |
transcendental functions | Math.exp Math.log Math.sin Math.cos Math.tan Math.asin Math.acos Math.atan Math.atan2 | exp log sin cos tan asin acos atan atan2 | from math import exp, log, \ sin, cos, tan, asin, acos, atan, atan2 | include Math exp log sin cos tan asin acos atan atan2 |
transcendental constants π and e | Math.PI Math.E | M_PI M_E | import math math.pi math.e | include Math PI E |
float truncation | none Math.round(3.1) Math.floor(3.1) Math.ceil(3.1) | (int)$x round($x) ceil($x) floor($x) | import math int(x) int(round(x)) math.ceil(x) math.floor(x) | x.to_i x.round x.ceil x.floor |
absolute value | Math.abs(-3) | abs($x) | abs(x) | x.abs |
integer overflow | all numbers are floats | converted to float | becomes arbitrary length integer of typelong | becomes arbitrary length integer of typeBignum |
float overflow | Infinity | INF | raises OverflowError | Infinity |
rational construction | none | from fractions import Fraction x = Fraction(22, 7) | require 'rational' x = Rational(22, 7) | |
rational decomposition | none | x.numerator x.denominator | x.numerator x.denominator | |
complex construction | none | z = 1 + 1.414j | require 'complex' z = 1 + 1.414.im | |
complex decomposition real and imaginary component, argument, absolute value, conjugate | none | import cmath z.real z.imag cmath.phase(z) abs(z) z.conjugate() | z.real z.imag z.arg z.abs z.conj | |
random number uniform integer, uniform float, normal float | Math.floor(Math.random() * 100) Math.random() none | rand(0,99) lcg_value() none | import random random.randint(0, 99) random.random() random.gauss(0, 1) | rand(100) rand none |
random seed set, get, restore | none | srand(17); none | import random random.seed(17) seed = random.getstate() random.setstate(seed) | srand(17) seed = srand srand(seed) |
bit operators | << >> & | ^ ~ | << >> & | ^ ~ | << >> & | ^ ~ | << >> & | ^ ~ |
binary, octal, and hex literals | none 052 // deprecated 0x2a | 0b101010 052 0x2a | 0b101010 052 0x2a | 0b101010 052 0x2a |
radix convert integer to and from string with radix | (42).toString(7) ?? | base_convert("42", 10, 7); base_convert("60", 7, 10); | none int("60", 7) | 42.to_s(7) "60".to_i(7) |
strings | ||||
javascript | php | python | ruby | |
string type | String | string | str | String |
string literal | "don't say \"no\"" 'don\'t say "no"' | "don't say \"no\"" 'don\'t say "no"' | 'don\'t say "no"' "don't say \"no\"" "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 | 'first line second line' "first line second line" | triple quote literals only: '''first line second line''' """first line second line""" | 'first line second line' "first line second line" |
literal escapes | single and double quotes: \b \f \n \r \t \v \uhhhh \xhh \" \' \\ | double quoted: \f \n \r \t \v \xhh \$ \" \\ \ooo single quoted: \' \\ | single and double quoted: \newline \\ \' \" \a \b \f \n \r \t \v \ooo\xhh Python 3: \uhhhh \Uhhhhhhhh | double quoted: \a \b \cx \e \f \n \r \s \t \v \xhh \ooo\uhhhh \u{hhhhh} single quoted: \' \\ |
here document | none | $word = "amet"; $s = <<<EOF lorem ipsum dolor sit $word EOF; | none | word = "amet" s = <<EOF lorem ipsum dolor sit #{word} EOF |
variable interpolation | // None; use string concatenation. // Both of these expressions are '11': 1 + "1" "1" + 1 | $count = 3; $item = "ball"; echo "$count ${item}s\n"; | count = 3 item = 'ball' print('{count} {item}s'.format( **locals())) | count = 3 item = "ball" puts "#{count} #{item}s" |
expression interpolation | none | none | '1 + 1 = {}'.format(1 + 1) | "1 + 1 = #{1 + 1}" |
format string | // None; use string concatenation. // Evaluates to "12.35": 12.3456.toFixed(2) | $fmt = "lorem %s %d %f"; sprintf($fmt, "ipsum", 13, 3.7); | 'lorem %s %d %f' % ('ipsum', 13, 3.7) fmt = 'lorem {0} {1} {2}' fmt.format('ipsum', 13, 3.7) | "lorem %s %d %f" % ["ipsum", 13, 3.7] |
are strings mutable? | no | $s = "bar"; $s2 = $s; # sets s to "baz"; s2 is unchanged: $s[2] = "z"; | no | s = "bar" s2 = s # sets s and s2 to "baz": s[2] = "z" |
copy string | none | $s2 = $s; | none | s = "bar" s2 = s.clone # s2 is not altered: s[2] = "z" |
concatenate | s = "Hello, " + "World!"; | $s = "Hello, "; $s2 = $s . "World!"; | s = 'Hello, ' s2 = s + 'World!' # juxtaposition can be used to # concatenate literals: s2 = 'Hello, ' "World!" | s = "Hello, " s2 = s + "World!" # juxtaposition can be used to # concatenate literals: s2 = "Hello, " 'World!' |
replicate | var hbar = Array(80).join("-"); | $hbar = str_repeat("-", 80); | hbar = '-' * 80 | hbar = "-" * 80 |
translate case to upper, to lower | "lorem".toUpperCase() "LOREM".toLowerCase() | strtoupper("lorem") strtolower("LOREM") | 'lorem'.upper() 'LOREM'.lower() | "lorem".upcase "LOREM".downcase |
capitalize string, words | none | ucfirst("lorem") ucwords("lorem ipsum") | import string 'lorem'.capitalize() string.capwords('lorem ipsum') | "lorem".capitalize none |
trim both sides, left, right | " lorem ".trim() # some browsers: " lorem".trimLeft() "lorem ".trimRight() | trim(" lorem ") ltrim(" lorem") rtrim("lorem ") | ' lorem '.strip() ' lorem'.lstrip() 'lorem '.rstrip() | " lorem ".strip " lorem".lstrip "lorem ".rstrip |
pad on right, on left, centered | none | str_pad("lorem", 10) str_pad("lorem", 10, " ", STR_PAD_LEFT) str_pad("lorem", 10, " ", STR_PAD_BOTH) | 'lorem'.ljust(10) 'lorem'.rjust(10) 'lorem'.center(10) | "lorem".ljust(10) "lorem".rjust(10) "lorem".center(10) |
number to string | "value: " + 8 | "value: " . 8 | 'value: ' + str(8) | "value: " + 8.to_s |
string to number | 7 + parseInt("12", 10) 73.9 + parseFloat(".037") // 12: parseInt("12A") // NaN: parseInt("A") | 7 + "12" 73.9 + ".037" # 12: 0 + "12A" # 0: 0 + "A" | 7 + int('12') 73.9 + float('.037') # raises ValueError: int('12A') # raises ValueError: int('A') | 7 + "12".to_i 73.9 + ".037".to_f # 12: "12A".to_i # 0: "A".to_i |
string join | ["do", "re", "mi"].join(" ") | $a = ["do", "re", "mi", "fa"]; implode(" ", $a) | ' '.join(['do', 're', 'mi', 'fa']) # raises TypeError: ' '.join([1, 2, 3]) | %w(do re mi fa).join(' ') # implicitly converted to strings: [1, 2, 3].join(' ') |
split | // [ "do", "re", "", "mi", "" ]: "do re mi ".split(" ") // [ "do", "re", "mi", "" ]: "do re mi ".split(/\s+/) | # [ "do", "re", "", "mi", "" ]: explode(" ", "do re mi ") # [ "do", "re", "mi", "" ]: preg_split('/\s+/', "do re mi ") | # ['do', 're', '', 'mi', '']: 'do re mi '.split(' ') # ['do', 're', 'mi']: 'do re mi '.split() | # ["do", "re", "", "mi"]: "do re mi ".split(/ /) # ["do", "re", "mi"]: "do re mi ".split |
split in two | none | preg_split('/\s+/', "do re mi fa", 2) | 'do re mi fa'.split(None, 1) | "do re mi fa".split(/\s+/, 2) |
split and keep delimiters | none | preg_split('/(\s+)/', "do re mi fa", NULL, PREG_SPLIT_DELIM_CAPTURE) | re.split('(\s+)', 'do re mi fa') | "do re mi fa".split(/(\s+)/) |
prefix and suffix test | "foobar".startsWith("foo") "foobar".endsWith("bar") | 'foobar'.startswith('foo') 'foobar'.endswith('bar') | 'foobar'.start_with?('foo') 'foobar'.end_with?('bar') | |
length | "lorem".length | strlen("lorem") | len('lorem') | "lorem".length "lorem".size |
index of substring first, last | // returns -1 if not found: "lorem ipsum".indexOf("ipsum") | # returns FALSE if not found: strpos("do re re", "re") strrpos("do re re", "re") | # raises ValueError if not found: 'do re re'.index('re') 'do re re'.rindex('re') # returns -1 if not found: 'do re re'.find('re') 'do re re'.rfind('re') | # returns nil if not found: "do re re".index("re") "do re re".rindex("re") |
extract substring by start and length, by start and end, by successive starts | "lorem ipsum".substr(6, 5) "lorem ipsum".substring(6, 11) | substr("lorem ipsum", 6, 5) none none | none none 'lorem ipsum'[6:11] | "lorem ipsum"[6, 5] "lorem ipsum"[6..10] "lorem ipsum"[6...11] |
character lookup | "lorem ipsum"[6] | # syntax error to use index notation # directly on string literal: $s = "lorem ipsum"; $s[6]; | 'lorem ipsum'[6] | "lorem ipsum"[6] |
chr and ord | String.fromCharCode(65) "A".charCodeAt(0) | chr(65) ord("A") | chr(65) ord('A') # Python 3: chr(0x3bb) ord('\u03bb') | 65.chr "A".ord 0x3bb.chr('UTF-8') "\u03bb".codepoints.first |
to array of characters | "abcd".split("") | str_split("abcd") | list('abcd') | "abcd".split("") |
translate characters | none | $ins = implode(range("a", "z")); $outs = substr($ins, 13, 13) . substr($ins, 0, 13); strtr("hello", $ins, $outs) | 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") |
delete characters | none | $vowels = str_split("aeiou"); $s = "disemvowel me"; $s = str_replace($vowels, "", $s); | "disemvowel me".translate(None, "aeiou") | "disemvowel me".delete("aeiou") |
squeeze characters | none | $s = "too much space"; $s = = preg_replace('/(\s)+/', '\1', $s); | re.sub('(\s)+', r'\1', 'too much space') | "too much space".squeeze(" ") |
regular expressions | ||||
javascript | php | python | ruby | |
literal, custom delimited literal | /lorem|ipsum/ | '/lorem|ipsum/' '(/etc/hosts)' | re.compile('lorem|ipsum') none | /lorem|ipsum/ %r(/etc/hosts) |
character class abbreviations | . \d \D \s \S \w \W | . \d \D \h \H \s \S \v \V \w \W | . \d \D \s \S \w \W | . \d \D \h \H \s \S \w \W |
anchors | ^ $ \b \B | ^ $ \A \b \B \z \Z | ^ $ \A \b \B \Z | ^ $ \A \b \B \z \Z |
match test | if (s.match(/1999/)) { alert("party!"); } | if (preg_match('/1999/', $s)) { echo "party!\n"; } | if re.search('1999', s): print('party!') | if /1999/.match(s) puts "party!" end |
case insensitive match test | "Lorem".match(/lorem/i) | preg_match('/lorem/i', "Lorem") | re.search('lorem', 'Lorem', re.I) | /lorem/i.match("Lorem") |
modifiers | g i m | e i m s x | re.I re.M re.S re.X | i o m x |
substitution | s = "do re mi mi mi"; s.replace(/mi/g, "ma"); | $s = "do re mi mi mi"; $s = preg_replace('/mi/', "ma", $s); | s = 'do re mi mi mi' s = re.compile('mi').sub('ma', s) | s = "do re mi mi mi" s.gsub!(/mi/, "ma") |
match, prematch, postmatch | m = /\d{4}/.exec(s); if (m) { match = m[0]; # no prematch or postmatch } | none | m = re.search('\d{4}', s) if m: match = m.group() prematch = s[0:m.start(0)] postmatch = s[m.end(0):len(s)] | m = /\d{4}/.match(s) if m match = m[0] prematch = m.pre_match postmatch = m.post_match end |
group capture | rx = /^(\d{4})-(\d{2})-(\d{2})$/; m = rx.exec('2009-06-03'); yr = m[1]; mo = m[2]; dy = m[3]; | $s = "2010-06-03"; $rx = '/(\d{4})-(\d{2})-(\d{2})/'; preg_match($rx, $s, $m); list($_, $yr, $mo, $dy) = $m; | rx = '(\d{4})-(\d{2})-(\d{2})' m = re.search(rx, '2010-06-03') yr, mo, dy = m.groups() | rx = /(\d{4})-(\d{2})-(\d{2})/ m = rx.match("2010-06-03") yr, mo, dy = m[1..3] |
named group capture | none | $s = "foo.txt"; $rx = '/^(?P<file>.+)\.(?P<suffix>.+)$/'; preg_match($rx, $s, $m); $m["file"] $m["suffix"] | rx = '^(?P<file>.+)\.(?P<suffix>.+)$' m = re.search(rx, ''foo.txt') m.groupdict()['file'] m.groupdict()['suffix'] | rx = /^(?<file>.+)\.(?<suffix>.+)$/ m = rx.match('foo.txt') m["file"] m["suffix"] |
scan | var a = "dolor sit amet".match(/\w+/g); | $s = "dolor sit amet"; preg_match_all('/\w+/', $s, $m); $a = $m[0]; | s = 'dolor sit amet' a = re.findall('\w+', s) | a = "dolor sit amet".scan(/\w+/) |
backreference in match and substitution | /(\w+) \1/.exec("do do") "do re".replace(/(\w+) (\w+)/, '$2 $1') | preg_match('/(\w+) \1/', "do do") $s = "do re"; $rx = '/(\w+) (\w+)/'; $s = preg_replace($rx, '\2 \1', $s); | none rx = re.compile('(\w+) (\w+)') rx.sub(r'\2 \1', 'do re') | /(\w+) \1/.match("do do") "do re".sub(/(\w+) (\w+)/, '\2 \1') |
recursive regex | none | '/\(([^()]*|($R))\)/' | none | /(?<foo>\(([^()]*|\g<foo>)*\))/ |
dates and time | ||||
javascript | php | python | ruby | |
broken-down datetime type | Date | DateTime | datetime.datetime | Time |
current datetime | var t = new Date(); | $t = new DateTime("now"); $utc_tmz = new DateTimeZone("UTC"); $utc = new DateTime("now", $utc_tmz); | import datetime t = datetime.datetime.now() utc = datetime.datetime.utcnow() | t = Time.now utc = Time.now.utc |
current unix epoch | (new Date()).getTime() / 1000 | $epoch = time(); | import datetime t = datetime.datetime.now() epoch = int(t.strftime("%s")) | epoch = Time.now.to_i |
broken-down datetime to unix epoch | Math.round(t.getTime() / 1000) | $epoch = $t->getTimestamp(); | from datetime import datetime as dt epoch = int(t.strftime("%s")) | epoch = t.to_i |
unix epoch to broken-down datetime | var epoch = 1315716177; var t2 = new Date(epoch * 1000); | $t2 = new DateTime(); $t2->setTimestamp(1304442000); | t = dt.fromtimestamp(1304442000) | t = Time.at(1304442000) |
format datetime | none | strftime("%Y-%m-%d %H:%M:%S", $epoch); date("Y-m-d H:i:s", $epoch); $t->format("Y-m-d H:i:s"); | t.strftime('%Y-%m-%d %H:%M:%S') | t.strftime("%Y-%m-%d %H:%M:%S") |
parse datetime | none | $fmt = "Y-m-d H:i:s"; $s = "2011-05-03 10:00:00"; $t = DateTime::createFromFormat($fmt, $s); | from datetime import datetime s = '2011-05-03 10:00:00' fmt = '%Y-%m-%d %H:%M:%S' t = datetime.strptime(s, fmt) | require 'date' s = "2011-05-03 10:00:00" fmt = "%Y-%m-%d %H:%M:%S" t = DateTime.strptime(s, fmt).to_time |
parse datetime w/o format | var t = new Date("July 7, 1999"); | $epoch = strtotime("July 7, 1999"); | # pip install python-dateutil import dateutil.parser s = 'July 7, 1999' t = dateutil.parser.parse(s) | require 'date' s = "July 7, 1999" t = Date.parse(s).to_time |
date parts | t.getFullYear() t.getMonth() + 1 t.getDate() # getDay() is day of week | (int)$t->format("Y") (int)$t->format("m") (int)$t->format("d") | t.year t.month t.day | t.year t.month t.day |
time parts | t.getHours() t.getMinutes() t.getSeconds() | (int)$t->format("H") (int)$t->format("i") (int)$t->format("s") | t.hour t.minute t.second | t.hour t.min t.sec |
build broken-down datetime | var yr = 1999; var mo = 9; var dy = 10; var hr = 23; var mi = 30; var ss = 0; var t = new Date(yr, mo - 1, dy, hr, mi, ss); | import datetime yr = 1999 mo = 9 dy = 10 hr = 23 mi = 30 ss = 0 t = datetime.datetime(yr, mo, dy, hr, mi, ss) | yr = 1999 mo = 9 dy = 10 hr = 23 mi = 30 ss = 0 t = Time.new(yr, mo, dy, hr, mi, ss) | |
datetime subtraction | number containing time difference in milliseconds | # 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); | datetime.timedelta object use total_seconds() method to convert to float representing difference in seconds | Float containing time difference in seconds |
add duration | var t1 = new Date(); var delta = (10 * 60 + 3) * 1000; var t2 = new Date(t1.getTime() + delta); | $now = new DateTime("now"); $now->add(new DateInterval("PT10M3S"); | import datetime delta = datetime.timedelta( minutes=10, seconds=3) t = datetime.datetime.now() + delta | require 'date/delta' s = "10 min, 3 s" delta = Date::Delta.parse(s).in_secs t = Time.now + delta |
local time zone determination | # DateTime objects can be instantiated without # specifying the time zone if a default is set: $s = "America/Los_Angeles"; date_default_timezone_set($s); | a datetime object has no time zone information unless a tzinfo object is provided when it is created | if no time zone is specified the local time zone is used | |
nonlocal time zone | # pip install pytz import pytz import datetime tmz = pytz.timezone('Asia/Tokyo') utc = datetime.datetime.utcnow() utc_dt = datetime.datetime( *utc.timetuple()[0:5], tzinfo=pytz.utc) jp_dt = utc_dt.astimezone(tmz) | # gem install tzinfo require 'tzinfo' tmz = TZInfo::Timezone.get("Asia/Tokyo") jp_time = tmz.utc_to_local(Time.now.utc) | ||
time zone info name and UTC offset | $tmz = date_timezone_get($t); timezone_name_get($tmz); date_offset_get($t) / 3600; | import time tm = time.localtime() time.tzname[tm.tm_isdst] (time.timezone / -3600) + tm.tm_isdst | t.zone t.utc_offset / 3600 | |
daylight savings test | $t->format("I"); | import time tm = time.localtime() tm.tm_isdst | t.dst? | |
microseconds | list($frac, $sec) = explode(" ", microtime()); $usec = $frac * 1000 * 1000; | t.microsecond | t.usec | |
sleep | none | # 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; usestream_set_timeout to limit time spent reading from a stream opened with fopen orfsockopen | import signal, time class Timeout(Exception): pass def timeout_handler(signo, fm): raise Timeout() signal.signal(signal.SIGALRM, timeout_handler) try: signal.alarm(5) might_take_too_long() except Timeout: pass signal.alarm(0) | require 'timeout' begin Timeout.timeout(5) do might_take_too_long end rescue Timeout::Error end | |
resizable arrays | ||||
javascript | php | python | ruby | |
literal | a = [1, 2, 3, 4] | $a = [1, 2, 3, 4]; # older syntax: $a = array(1, 2, 3, 4); | a = [1, 2, 3, 4] | a = [1, 2, 3, 4] # a = ['do', 're', 'mi'] a = %w(do re mi) |
size | a.length | count($a) | len(a) | a.size a.length # same as size |
empty test | // TypeError if a is null or undefined: a.length === 0 | # NULL tests as empty: !$a | # None tests as empty: not a | # NoMethodError if a is nil: a.empty? |
lookup | a[0] | $a[0] # PHP uses the same type for arrays and # dictionaries; indices can be negative # integers or strings | a[0] # returns last element: a[-1] | a[0] # returns last element: a[-1] |
update | a[0] = "lorem" | $a[0] = "lorem"; | a[0] = 'lorem' | a[0] = "lorem" |
out-of-bounds behavior | returns undefined | $a = []; # evaluates as NULL: $a[10]; # increases array size to one: $a[10] = "lorem"; | a = [] # raises IndexError: a[10] # raises IndexError: a[10] = 'lorem' | a = [] # evaluates as nil: a[10] # increases array size to 11: a[10] = "lorem" |
element index first and last occurrence | // return -1 if not found: [6, 7, 7, 8].indexOf(7) [6, 7, 7, 8].lastIndexOf(7) | $a = ["x", "y", "y", "z"]; # returns FALSE if not found: $i = array_search("y", $a, TRUE); none | a = ['x', 'y', 'y', 'z'] # raises ValueError if not found: a.index('y') none | a = %w(x y y z) # return nil if not found: a.index('y') a.rindex('y') |
slice by endpoints, by length | // select 3rd and 4th elements: ["a", "b", "c", "d"].slice(2, 4) none | # select 3rd and 4th elements: none array_slice($a, 2, 2) | # select 3rd and 4th elements: a[2:4] a[2:2 + 2] | # select 3rd and 4th elements: a[2..3] a[2, 2] |
slice to end | ["a", "b", "c", "d"].slice(1) | array_slice($a, 1) | a[1:] | a[1..-1] |
manipulate back | a = [6, 7, 8]; a.push(9); i = a.pop(); | $a = [6, 7, 8]; array_push($a, 9); $a[] = 9; # same as array_push array_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 = [6, 7, 8]; a.unshift(5); i = a.shift(); | $a = [6, 7, 8]; array_unshift($a, 5); array_shift($a); | a = [6, 7, 8] a.insert(0, 5) a.pop(0) | a = [6, 7, 8] a.unshift(5) a.shift |
concatenate | a = [1, 2, 3].concat([4, 5, 6]); | $a = [1, 2, 3]; $a2 = array_merge($a, [4, 5, 6]); $a = array_merge($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]) |
replicate | none | $a = array_fill(0, 10, NULL); | a = [None] * 10 a = [None for i in range(0, 10)] | a = [nil] * 10 a = Array.new(10, nil) |
copy address copy, shallow copy, deep copy | a = [1, 2, [3, 4]]; a2 = a; a3 = a.slice(0); a4 = JSON.parse(JSON.stringify(a)); | $a = [1, 2, [3, 4]]; $a2 =& $a; none $a4 = $a; | import copy a = [1,2,[3,4]] a2 = a a3 = list(a) a4 = copy.deepcopy(a) | a = [1,2,[3,4]] a2 = a a3 = a.dup a4 = Marshal.load(Marshal.dump(a)) |
array as function argument | parameter contains address copy | parameter contains deep copy | parameter contains address copy | parameter contains address copy |
iterate over elements | _.each([1, 2, 3], function(n) { alert(n); }) | foreach ([1, 2, 3] as $i) { echo "$i\n"; } | for i in [1, 2, 3]: print(i) | [1, 2, 3].each { |i| puts i } |
iterate over indices and elements | var len = a.length; for (var i = 0; i < len; i++ ) { alert(a[i]); } | $a = ["do", "re", "mi" "fa"]; foreach ($a as $i => $s) { echo "$s at index $i\n"; } | a = ['do', 're', 'mi', 'fa'] for i, s in enumerate(a): print('%s at index %d' % (s, i)) | a = %w(do re mi fa) a.each_with_index do |s, i| puts "#{s} at index #{i}" end |
iterate over range | not space efficient; use C-style for loop | not space efficient; use C-style for loop | # use range() in Python 3: for i in xrange(1, 1000001): code | (1..1_000_000).each do |i| code end |
instantiate range as array | var a = _.range(1, 10); | $a = range(1, 10); | a = range(1, 11) Python 3: a = list(range(1, 11)) | a = (1..10).to_a |
reverse non-destructive, in-place | var a = [1, 2, 3]; a.reverse(); | $a = [1, 2, 3]; array_reverse($a); $a = array_reverse($a); | a = [1, 2, 3] a[::-1] a.reverse() | a = [1, 2, 3] a.reverse a.reverse! |
sort non-destructive, in-place, custom comparision | var a = [3, 1, 4, 2]; a.sort(); | $a = ["b", "A", "a", "B"]; none sort($a); none, but usort sorts in place | a = ['b', 'A', 'a', 'B'] sorted(a) a.sort() # custom binary comparision # removed from Python 3: a.sort(key=str.lower) | a = %w(b A a B) a.sort a.sort! a.sort do |x, y| x.downcase <=> y.downcase end |
dedupe non-destructive, in-place | var a = [1, 2, 2, 3]; var a2 = _.uniq(a); a = _.uniq(a); | $a = [1, 2, 2, 3]; $a2 = array_unique($a); $a = array_unique($a); | a = [1, 2, 2, 3] a2 = list(set(a)) a = list(set(a)) | a = [1, 2, 2, 3] a2 = a.uniq a.uniq! |
membership | _.contains(a, 7) | in_array(7, $a) | 7 in a | a.include?(7) |
intersection | _.intersection([1, 2], [2, 3, 4]) | $a = [1, 2]; $b = [2, 3, 4] array_intersect($a, $b) | {1, 2} & {2, 3, 4} | [1, 2] & [2 ,3, 4] |
union | _.union([1, 2], [2, 3, 4]) | $a1 = [1, 2]; $a2 = [2, 3, 4]; array_unique(array_merge($a1, $a2)) | {1, 2} | {2, 3, 4} | [1, 2] | [2, 3, 4] |
relative complement, symmetric difference | _.difference([1, 2, 3], [2]) none | $a1 = [1, 2, 3]; $a2 = [2]; array_values(array_diff($a1, $a2)) none | {1, 2, 3} - {2} {1, 2} ^ {2, 3, 4} | require 'set' [1, 2, 3] - [2] Set[1, 2] ^ Set[2 ,3, 4] |
map | // callback gets 3 args: // value, index, array a.map(function(x) { return x * x }) | array_map(function ($x) { return $x * $x; }, [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 | a.filter(function(x) { return x > 1 }) | array_filter([1, 2, 3], function ($x) { return $x>1; }) | 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 | a.reduce(function(m, o) { return m + o; }, 0) | array_reduce([1, 2, 3], function($x,$y) { return $x + $y; }, 0) | # import needed in Python 3 only from functools import reduce reduce(lambda x, y: x + y, [1, 2, 3], 0) | [1, 2, 3].inject(0) { |m, o| m + o } |
universal and existential tests | var a = [1, 2, 3, 4]; var even = function(x) { return x % 2 == 0; }; a.every(even) a.some(even) | use array_filter | all(i % 2 == 0 for i in [1, 2, 3, 4]) any(i % 2 == 0 for i in [1, 2, 3, 4]) | [1, 2, 3, 4].all? {|i| i.even? } [1, 2, 3, 4].any? {|i| i.even? } |
shuffle and sample | var a = [1, 2, 3, 4]; a = _.shuffle(a); var samp = _.sample([1, 2, 3, 4], 2); | $a = [1, 2, 3, 4]; shuffle($a); $samp = array_rand(|[1, 2, 3, 4], 2); | from random import shuffle, sample a = [1, 2, 3, 4] shuffle(a) samp = sample([1, 2, 3, 4], 2) | [1, 2, 3, 4].shuffle! samp = [1, 2, 3, 4].sample(2) |
flatten one level, completely | var a = [1, [2, [3, 4]]]; var a2 = _.flatten(a, true); var a3 = _.flatten(a); | none | none | a = [1, [2, [3, 4]]] a2 = a.flatten(1) a3 = a.flatten |
zip | var a = _.zip( [1, 2, 3], ["a", "b", "c"]); | $a = array_map(NULL, [1, 2, 3], ["a", "b", "c"]); | a = zip([1, 2, 3], ['a', 'b', 'c']) | a = [1, 2, 3].zip(["a", "b", "c"]) |
dictionaries | ||||
javascript | php | python | ruby | |
literal | d = {"t": 1, "f": 0}; // keys do not need to be quoted if they // are a legal JavaScript variable name //and not a reserved word | $d = ["t" => 1, "f" => 0]; # older syntax: $d = array("t" => 1, "f" => 0); | d = {'t': 1, 'f': 0} | d = {'t' => 1, 'f' => 0} # keys are symbols: symbol_to_int = {t: 1, f: 0} |
size | var size = 0; for (var k in d) { if (d.hasOwnProperty(k)) size++; } | count($d) | len(d) | d.size d.length # same as size |
lookup | d.t d["t"] | $d["t"] | d['t'] | d['t'] |
update | d["t"] = 2; d.t = 2; | $d["t"] = 2; | d['t'] = 2 | d['t'] = 2 |
missing key behavior | var d = {}; // sets s to undefined: var s = d["lorem"]; // adds key/value pair: d["lorem"] = "ipsum"; | $d = []; # sets $s to NULL: $s = $d["lorem"]; # adds key/value pair: $d["lorem"] = "ipsum"; | d = {} # raises KeyError: s = d['lorem'] # adds key/value pair: d['lorem'] = 'ipsum' | d = {} # sets s to nil: s = d['lorem'] # adds key/value pair: d['lorem'] = 'ipsum' |
is key present | d.hasOwnProperty("t"); | array_key_exists("y", $d); | 'y' in d | d.key?('y') |
delete | delete d["t"]; delete d.t; | $d = [1 => "t", 0 => "f"]; unset($d[1]); | d = {1: True, 0: False} del d[1] | d = {1 => true, 0 => false} d.delete(1) |
from array of pairs, from even length array | var a = [["a", 1], ["b", 2], ["c", 3]]; var d = _.object(a); none | a = [['a', 1], ['b', 2], ['c', 3]] d = dict(a) a = ['a', 1, 'b', 2, 'c', 3] d = dict(zip(a[::2], a[1::2])) | a = [['a', 1], ['b', 2], ['c', 3]] d = Hash[a] a = ['a', 1, 'b', 2, 'c', 3] d = Hash[*a] | |
merge | var d1 = {"a": 1, "b": 2}; var d2 = {"c": 3, "d": 4}; d1 = _.extend(d1, d2); | $d1 = ["a" => 1, "b" => 2]; $d2 = ["b" => 3, "c" => 4]; $d1 = array_merge($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 | var to_num = {'t': 1, 'f': 0}; var to_let = _.invert(to_num); | $to_num = ["t" => 1, "f" => 0]; $to_let = array_flip($to_num); | to_num = {'t': 1, 'f': 0} # dict comprehensions added in 2.7: to_let = {v: k for k, v in to_num.items()} | to_num = {'t' => 1, 'f' => 0} to_let = to_num.invert |
iterate | for (var k in d) { use k or d[k] } | foreach ($d as $k => $v) { code } | for k, v in d.iteritems(): code Python 3: for k, v in d.items(): code | d.each do |k,v| code end |
keys and values as arrays | _.keys(d) _.values(d) | array_keys($d) array_values($d) | d.keys() d.values() Python 3: list(d.keys()) list(d.values()) | d.keys d.values |
sort by values | function cmp2(a, b) { if (a[1] < b[1]) { return -1; } if (a[1] > b[1]) { return 1; } return 0; } for (p in _.pairs(d).sort(cmp2)) { alert(p[0] + ": " + p[1]); } | asort($d); foreach ($d as $k => $v) { print "$k: $v\n"; } | from operator import itemgetter pairs = sorted(d.iteritems(), key=itemgetter(1)) for k, v in pairs: print('{}: {}'.format(k, v)) | d.sort_by { |k, v| v }.each do |k, v| puts "#{k}: #{v}" end |
default value, computed value | none | $counts = []; $counts['foo'] += 1; extend ArrayObject for computed values and defaults other than zero or empty string. | from collections import defaultdict counts = defaultdict(lambda: 0) counts['foo'] += 1 class Factorial(dict): def __missing__(self, k): if k > 1: return k * self[k-1] else: return 1 factorial = Factorial() | counts = Hash.new(0) counts['foo'] += 1 factorial = Hash.new do |h,k| k > 1 ? k * h[k-1] : 1 end |
functions | ||||
javascript | php | python | ruby | |
define | function add(x, y) { return x+y; } | function add3($x1, $x2, $x3) { return $x1 + $x2 + $x3; } | def add3(x1, x2, x3): return x1 + x2 + x3 | def add3(x1, x2, x3) x1 + x2 + x3 end # parens are optional and customarily # omitted when defining functions # with no parameters |
invoke | add(1, 2) | add3(1, 2, 3); # function names are case insensitive: ADD3(1, 2, 3); | add3(1, 2, 3) | add3(1, 2, 3) # parens are optional: add3 1, 2, 3 |
missing argument behavior | set to undefined | set to NULL with warning | raises TypeError if number of arguments doesn't match function arity | raises ArgumentError if number of arguments doesn't match function arity |
extra argument behavior | ignored | ignored | raises TypeError if number of arguments doesn't match function arity | raises ArgumentError if number of arguments doesn't match function arity |
default argument | none | function my_log($x, $base=10) { return log($x) / log($base); } my_log(42); my_log(42, M_E); | import math def my_log(x, base=10): return math.log(x) / math.log(base) my_log(42) my_log(42, math.e) | def my_log(x, base=10) Math.log(x) / Math.log(base) end my_log(42) my_log(42, Math::E) |
variadic function | args in arguments[0], arguments[1], … with number of args in arguments.length | function first_and_last() { $arg_cnt = func_num_args(); if ($arg_cnt >= 1) { $n = func_get_arg(0); echo "first: " . $n . "\n"; } if ($arg_cnt >= 2) { $a = func_get_args(); $n = $a[$arg_cnt-1]; echo "last: " . $n . "\n"; } } | def first_and_last(*a): if len(a) >= 1: print('first: ' + str(a[0])) if len(a) >= 2: print('last: ' + str(a[-1])) | def first_and_last(*a) if a.size >= 1 puts "first: #{a[0]}" end if a.size >= 2 puts "last: #{a[-1]}" end end |
pass array elements as separate arguments | none | $a = [1, 2, 3]; call_user_func_array("add3", $a); | a = [2, 3] add3(1, *a) # splat operator can only be used once # and must appear after other # unnamed arguments | a = [2, 3] add3(1, *a) # splat operator can be used multiple # times and can appear before regular # arguments |
parameter alias | none | function first_and_second(&$a) { return [$a[0], $a[1]]; } | none | none |
named parameters | none | none | def fequal(x, y, eps=0.01): return abs(x - y) < eps fequal(1.0, 1.001) fequal(1.0, 1.001, eps=0.1**10) | def fequal(x, y, opts={}) eps = opts[:eps] || 0.01 (x - y).abs < eps end fequal(1.0, 1.001) fequal(1.0, 1.001, :eps=>0.1**10) # Ruby 2.0: def fequals(x, y, eps: 0.01) (x - y).abs < eps end fequals(1.0, 1.001) fequals(1.0, 1.001, eps: 0.1**10) |
return value | return arg or undefined. If invoked withnew and return value not an object, returnsthis | return arg or NULL | return arg or None | return arg or last expression evaluated |
multiple return values | none | function first_and_second(&$a) { return [$a[0], $a[1]]; } $a = [1, 2, 3]; list($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]) |
anonymous function literal | var sqr = function(x) { return x*x; } | $sqr = function ($x) { return $x * $x; }; | # body must be an expression: sqr = lambda x: x * x | sqr = lambda { |x| x * x } |
invoke anonymous function | sqr(2) | $sqr(2) | sqr(2) | sqr.call(2) or sqr[2] |
function as value | var func = add; | $func = "add"; | func = add | func = lambda { |*args| add(*args) } |
function with private state | function counter() { counter.i += 1; return counter.i; } counter.i = 0; alert(counter()); | function counter() { static $i = 0; return ++$i; } echo counter(); | # state not private: def counter(): counter.i += 1 return counter.i counter.i = 0 print(counter()) | none |
closure | function make_counter() { var i = 0; return function() { i += 1; return i; } } | function make_counter() { $i = 0; return function () use (&$i) { return ++$i; }; } $nays = make_counter(); echo $nays(); | # 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 | # PHP 5.5: function make_counter() { $i = 0; while (1) { yield ++$i; } } $nays = make_counter(); # does not return a value: $nays->next(); # runs generator if generator has not # yet yielded: echo $nays->current(); | # The itertools library contains # standard generators. # c.f. itertools.count() def make_counter(): i = 0 while True: i += 1 yield i nays = make_counter() print(nays.next()) | 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 | |
decorator | def logcall(f): def wrapper(*a, **opts): print('calling ' + f.__name__) f(*a, **opts) print('called ' + f.__name__) return wrapper @logcall def square(x): return x * x | |||
invoke operator like function | import operator operator.mul(3, 7) a = ['foo', 'bar', 'baz'] operator.itemgetter(2)(a) | 3.*(7) a = ['foo', 'bar', 'baz'] a.[](2) | ||
execution control | ||||
javascript | php | python | ruby | |
if | if (0 == n) { alert("no hits"); } else if (1 == n) { alert("1 hit"); } else { alert(n + " hits"); } | 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') 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: alert("no hits\n"); break; case 1: alert("one hit\n"); break; default: alert(n + " hits\n"); } | switch ($n) { case 0: echo "no hits\n"; break; case 1: echo "one hit\n"; break; default: echo "$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 += 1; } | while ( $i < 100 ) { $i++; } | while i < 100: i += 1 | while i < 100 do i += 1 end |
for | for (var i = 0; i < 10; i++) { alert(i); } | for ($i = 1; $i <= 10; $i++) { echo "$i\n"; } | none | none |
break | break | break | break | break |
continue | continue | continue | continue | next |
statement modifiers | none | none | none | puts "positive" if i > 0 puts "nonzero" unless i == 0 |
exceptions | ||||
javascript | php | python | ruby | |
base exception | Any value can be thrown. | Exception | BaseException User-defined exceptions should subclassException. In Python 2 old-style classes can be thrown. | Exception User-defined exceptions should subclassStandardError. |
predefined exceptions | Error EvalError RangeError ReferenceError SyntaxError TypeError URIError | Exception LogicException BadFunctionCallException BadMethodCallException DomainException InvalidArgumentException LengthException OutOfRangeException RuntimeException OutOfBoundsException OverflowException RangeException UnderflowException UnexpectedValueException | BaseException SystemExit KeyboardInterrupt GeneratorExit Exception StopIteration StandardError BufferError ArithmeticError FloatingPointError OverflowError ZeroDivisionError AssertionError AttributeError EnvironmentError EOFError ImportError LookupError IndexError KeyError MemoryError NameError ReferenceError RuntimeError NotImplementedError SyntaxError SystemError TypeError ValueError UnicodeError Python 3 has a different tree | Exception NoMemoryError ScriptError LoadError NotImplementedError SyntaxError SignalException StandardError ArgumentError IOError EOFError IndexError LocalJumpError NameError RangeError RegexpError RuntimeError SecurityError SocketError SystemCallError Errno::* SystemStackError ThreadError TypeError ZeroDivisionError SystemExit fatal |
raise exception | throw new Error("bad arg"); | throw new Exception("bad arg"); | raise Exception('bad arg') | # raises RuntimeError raise "bad arg" |
catch-all handler | try { risky(); } catch (e) { alert("risky failed: " + e.message); } | try { risky(); } catch (Exception $e) { echo "risky failed: ", $e->getMessage(), "\n"; } | try: risky() except: print('risky failed') | # catches StandardError begin risky rescue print "risky failed: " puts $!.message end |
re-raise exception | try { throw new Error("bam!"); } catch (e) { alert("re-raising..."); throw e; } | try: raise Exception('bam!') except: print('re-raising...') raise | begin raise "bam!" rescue puts "re-raising…" raise end | |
global variable for last exception | none | none | last exception: sys.exc_info()[1] | last exception: $! backtrace array of exc.: $@ exit status of child: $? |
define exception | function Bam(msg) { this.message = msg; } Bam.prototype = new Error; | class Bam extends Exception { function __construct() { parent::__construct("bam!"); } } | class Bam(Exception): def __init__(self): super(Bam, self).__init__('bam!') | class Bam < Exception def initialize super("bam!") end end |
handle exception | try { throw new Bam("bam!"); } catch (e) { if (e instanceof Bam) { alert(e.message); } else { throw e; } } | try { throw new Bam; } catch (Bam $e) { echo $e->getMessage(), "\n"; } | try: raise Bam() except Bam as e: print(e) | begin raise Bam.new rescue Bam => e puts e.message end |
finally block | acquire_resource(); try { risky(); } finally { release_resource(); } | PHP 5.5: acquire_resource(); try { risky(); } finally { release_resource(); } | acquire_resource() try: risky() finally: release_resource() | acquire_resource begin risky ensure release_resource end |
concurrency | ||||
javascript | php | python | ruby | |
start thread | none | class sleep10(threading.Thread): def run(self): time.sleep(10) thr = sleep10() thr.start() | thr = Thread.new { sleep 10 } | |
wait on thread | thr.join() | thr.join | ||
____________________________________________ | ____________________________________________ |
streams | ||||
---|---|---|---|---|
node | php | python | ruby | |
standard file handles | process.stdin process.stdout process.stderr | only set by CLI; not set when reading script from stdin: STDIN STDOUT STDERR | sys.stdin sys.stdout sys.stderr | $stdin $stdout $stderr |
read line from stdin | $line = fgets(STDIN); | line = sys.stdin.readline() | line = gets | |
end-of-file behavior | returns string without newline or FALSE | returns string without newline or '' | returns non-empty string without newline or raises EOFError | |
chomp | chop($line); | line = line.rstrip('\r\n') | line.chomp! | |
write line to stdout | console.log("Hello, World"); | echo "Hello, World!\n"; | print('Hello, World!') | puts "Hello, World!" |
write formatted string to stdout | printf("%.2f\n", M_PI); | import math print('%.2f' % math.pi) | printf("%.2f\n", Math::PI) | |
open file for reading | $f = fopen("/etc/hosts", "r"); | f = open('/etc/hosts') | f = File.open("/etc/hosts") | |
open file for writing | var f = fs.openSync("/tmp/test", "w"); | $f = fopen("/tmp/test", "w"); | f = open('/tmp/test', 'w') | f = File.open("/tmp/test", "w") |
set file handle encoding | import codecs fin = codecs.open('/tmp/foo', encoding='utf-8') fout = codecs.open('/tmp/bar', 'w', encoding='utf-8') | fin = File.open("/tmp/foo", "r:utf-8") fout = File.open("/tmp/bar", "w:utf-8") | ||
open file for appending | $f = fopen("/tmp/test", "a"); | f = open('/tmp/err.log', 'a') | f = File.open("/tmp/err.log", "a") | |
close file | fclose($f); | f.close() | f.close | |
close file implicitly | none | with open('/tmp/test', 'w') as f: f.write('lorem ipsum\n') | File.open("/tmp/test", "w") do |f| f.puts("lorem ipsum") end | |
i/o error | return false value and write warning to stderr | raise IOError exception | raise IOError or subclass ofSystemCallError exception | |
encoding error | raise UnicodeDecodeError on read; raiseUnicodeEncodeError on write | |||
read line | $line = fgets($f); | f.readline() | f.gets | |
iterate over file by line | while (!feof($f)) { $line = fgets($f); echo $line; } | for line in f: print(line) | f.each do |line| print(line) end | |
read file into array of strings | $a = file("/etc/hosts"); | a = f.readlines() | a = f.lines.to_a | |
read file into string | var fs = require('fs'); var s = fs.readFileSync('/etc/hosts', 'utf8'); | $s = file_get_contents( "/etc/hosts"); | s = f.read() | s = f.read |
write string | fwrite($f, "lorem ipsum"); | f.write('lorem ipsum') | f.write("lorem ipsum") | |
write line | fwrite($f, "lorem ipsum\n"); | f.write('lorem ipsum\n') | f.puts("lorem ipsum") | |
flush file handle | CLI output isn't buffered fflush($f); | f.flush() | f.flush | |
end-of-file test | feof($f) | none | f.eof? | |
file handle position get, set | ftell($f) fseek($f, 0); | f.tell() f.seek(0) | f.tell f.seek(0) f.pos f.pos = 0 | |
open temporary file | $f = tmpfile(); fwrite($f, "lorem ipsum\n"); # no way to get file name fclose($f); file is removed when file handle is closed | import tempfile f = tempfile.NamedTemporaryFile() f.write('lorem ipsum\n') print("tmp file: %s" % f.name) f.close() file is removed when file handle is closed | require 'tempfile' f = Tempfile.new('') f.puts "lorem ipsum" puts "tmp file: #{f.path}" f.close file is removed when file handle is garbage-collected or interpreter exits | |
in memory file | $meg = 1024 * 1024; $mem = "php://temp/maxmemory:$meg"; $f = fopen($mem, "r+"); fputs($f, "lorem ipsum"); rewind($f); $s = fread($f, $meg); | from StringIO import StringIO f = StringIO() f.write('lorem ipsum\n') s = f.getvalue() Python 3 moved StringIO to the io module | require 'stringio' f = StringIO.new f.puts("lorem ipsum") f.rewind s = f.read | |
files | ||||
node | php | python | ruby | |
file exists test, file regular test | var fs = require('fs'); var qry = fs.existsSync('/etc/hosts'); var stat = fs.statSync('/etc/hosts'); var qry2 = stat.isFile(); | file_exists("/etc/hosts") is_file("/etc/hosts") | os.path.exists('/etc/hosts') os.path.isfile('/etc/hosts') | File.exists?("/etc/hosts") File.file?("/etc/hosts") |
file size | var fs = require('fs'); var stat = fs.statSync('/etc/hosts'); var sz = stat.size; | filesize("/etc/hosts") | os.path.getsize('/etc/hosts') | File.size("/etc/hosts") |
is file readable, writable, executable | is_readable("/etc/hosts") is_writable("/etc/hosts") is_executable("/etc/hosts") | os.access('/etc/hosts', os.R_OK) os.access('/etc/hosts', os.W_OK) os.access('/etc/hosts', os.X_OK) | File.readable?("/etc/hosts") File.writable?("/etc/hosts") File.executable?("/etc/hosts") | |
set file permissions | var fs = require('fs'); fs.chmodSync('/tmp/foo', parseInt('755', 8)); | chmod("/tmp/foo", 0755); | os.chmod('/tmp/foo', 0755) | File.chmod(0755, "/tmp/foo") |
last modification time | var fs = require('fs'); var stat = fs.statSync('/etc/hosts'); var dt = stat.mtime; | # unix epoch: $t = stat('/etc/passwd')['mtime']; # DateTime object: $t2 = new DateTime('UTC'); $t2->setTimestamp($t); | from datetime import datetime as dt # unix epoch: t = os.stat('/etc/passwd').st_mtime # datetime object: t2 = dt.fromtimestamp(t) | # Time object: t2 = File.stat('/etc/passwd').mtime # unix epoch: t = t2.to_i |
copy file, remove file, rename file | # npm install fs-extra var fs = require('fs-extra'); fs.copySync('/tmp/foo', '/tmp/bar'); fs.unlinkSync('/tmp/foo'); fs.renameSync('/tmp/bar', '/tmp/foo'); | copy("/tmp/foo", "/tmp/bar"); unlink("/tmp/foo"); rename("/tmp/bar", "/tmp/foo"); | import shutil shutil.copy('/tmp/foo', '/tmp/bar') os.remove('/tmp/foo') shutil.move('/tmp/bar', '/tmp/foo') | require 'fileutils' FileUtils.cp("/tmp/foo", "/tmp/bar") FileUtils.rm("/tmp/foo") FileUtils.mv("/tmp/bar", "/tmp/foo") |
create symlink, symlink test, readlink | var fs = require('fs'); fs.symlinkSync('/etc/hosts', '/tmp/hosts'); var stat = fs.statSync('/tmp/hosts'); stat.isSymbolicLink(); var path = fs.readlinkSync( '/tmp/hosts'); | symlink("/etc/hosts", "/tmp/hosts"); is_link("/etc/hosts") readlink("/tmp/hosts") | os.symlink('/etc/hosts', '/tmp/hosts') os.path.islink('/tmp/hosts') os.path.realpath('/tmp/hosts') | File.symlink("/etc/hosts", "/tmp/hosts") File.symlink?("/etc/hosts") File.realpath("/tmp/hosts") |
generate unused file name | $path = tempnam("/tmp", "foo"); $f = fopen($path, "w"); | import tempfile f, path = tempfile.mkstemp( prefix='foo', dir='/tmp') | ||
file formats | ||||
node | php | python | ruby | |
parse csv | var fs = require('fs'); # npm install csv var csv = require('csv'); var s = fs.readFileSync('no-header.csv'); var a; csv().from.string(s).to.array(function(d) { a = d }); | $f = fopen("no-header.csv", "r"); while (($row = fgetcsv($f)) != FALSE) { echo implode("\t", $row) . "\n"; } | import csv with open('foo.csv') as f: cr = csv.reader(f) for row in cr: print('\t'.join(row)) | require 'csv' CSV.foreach("foo.csv") do |row| puts row.join("\t") end |
generate csv | # npm install csv var csv = require('csv'); var a = [['one', 'une', 'uno'], ['two', 'deux', 'dos']]; var s; csv().from.array(a).to.string(function (o) { s = o; }); | import csv with open('foo.csv', 'w') as f: cw = csv.writer(f) cw.writerow(['one', 'une', 'uno']) cw.writerow(['two', 'deux', 'dos']) | require 'csv' CSV.open("foo.csv", "w") do |csv| csv << ["one", "une", "uno"] csv << ["two", "deux", "dos"] end | |
parse json | var s1 = '{"t":1,"f":0}'; var d1 = JSON.parse(s1); | $s1 = '{"t":1,"f":0}'; $a1 = json_decode($s1, TRUE); | import json d = json.loads('{"t":1,"f":0}') | require 'json' d = JSON.parse('{"t":1,"f":0}') |
generate json | var d2 = {'t': 1, 'f': 0}; var s2 = JSON.stringify(d1); | $a2 = array("t" => 1, "f" => 0); $s2 = json_encode($a2); | import json s = json.dumps({'t': 1, 'f': 0}) | require 'json' s = {'t' => 1,'f' => 0}.to_json |
parse yaml | # sudo pip install PyYAML import yaml data = yaml.safe_load('{f: 0, t: 1}\n') | # sudo gem install safe_yaml require 'safe_yaml' data = YAML.safe_load("—-\nt: 1\nf: 0\n") | ||
generate yaml | # sudo pip install PyYAML import yaml s = yaml.safe_dump({'t': 1, 'f': 0}) | # sudo gem install safe_yaml require 'safe_yaml' s = YAML.dump({'t' => 1, 'f' => 0}) | ||
parse xml all nodes matching xpath query; first node matching xpath query | # npm install xmldom xpath var dom = require('xmldom').DOMParser; var xpath = require('xpath'); var xml = '<a><b><c ref="3">foo</c></b></a>'; var doc = new dom().parseFromString(xml); var nodes = xpath.select('/a/b/c', doc); nodes.length; nodes[0].firstChild.data; | $xml = "<a><b><c ref='3'>foo</c></b></a>"; # returns NULL and emits warning if not # well-formed: $doc = simplexml_load_string($xml); $nodes = $doc->xpath("/a/b/c"); echo count($nodes); echo $nodes[0]; $node = $nodes[0]; echo $node; echo $node["ref"]; | from xml.etree import ElementTree xml = '<a><b><c ref="3">foo</c></b></a>' # raises xml.etree.ElementTree.ParseError # if not well-formed: doc = ElementTree.fromstring(xml) nodes = doc.findall('b/c') print(len(nodes)) print(nodes[0].text) node = doc.find('b/c') print(node.text) print(node.attrib['ref']) | require 'rexml/document' include REXML xml = "<a><b><c ref='3'>foo</c></b></a>" # raises REXML::ParseException if # not well-formed: doc = Document.new(xml) nodes = XPath.match(doc,"/a/b/c") puts nodes.size puts nodes[0].text node = XPath.first(doc,"/a/b/c") puts node.text puts node.attributes["ref"] |
generate xml | # npm install xmlbuilder var builder = require('xmlbuilder'); var xml = builder.create('a').ele('b', {id: 123}, 'foo').end(); | $xml = "<a></a>"; $sxe = new SimpleXMLElement($xml); $b = $sxe->addChild("b", "foo"); $b->addAttribute("id", "123"); # <a><b id="123">foo</b></a>: echo $sxe->asXML(); | import xml.etree.ElementTree as ET builder = ET.TreeBuilder() builder.start('a', {}) builder.start('b', {'id': '123'}) builder.data('foo') builder.end('b') builder.end('a') et = builder.close() # <a><b id="123">foo</b></a>: print(ET.tostring(et)) | # gem install builder require 'builder' builder = Builder::XmlMarkup.new xml = builder.a do |child| child.b("foo", :id=>"123") end # <a><b id="123">foo</b></a>: puts xml |
parse html | $html = file_get_contents("foo.html"); $doc = new DOMDocument; $doc->loadHTML($html); $xpath = new DOMXPath($doc); $nodes = $xpath->query("//a/@href"); foreach($nodes as $href) { echo $href->nodeValue; } | # pip install beautifulsoup4 import bs4 html = open('foo.html').read() doc = bs4.BeautifulSoup(html) for link in doc.find_all('a'): print(link.get('href')) | # gem install nokogiri require 'nokogiri' html = File.open("foo.html").read doc = Nokogiri::HTML(html) doc = doc.xpath("//a").each do |link| puts link["href"] end | |
directories | ||||
node | php | python | ruby | |
working directory | var old_dir = process.cwd(); process.chdir("/tmp"); | $old_dir = getcwd(); chdir("/tmp"); | old_dir = os.path.abspath('.') os.chdir('/tmp') | old_dir = Dir.pwd Dir.chdir("/tmp") |
build pathname | "/etc" . DIRECTORY_SEPARATOR . "hosts" | os.path.join('/etc', 'hosts') | File.join("/etc", "hosts") | |
dirname and basename | dirname("/etc/hosts") basename("/etc/hosts") | os.path.dirname('/etc/hosts') os.path.basename('/etc/hosts') | File.dirname("/etc/hosts") File.basename("/etc/hosts") | |
absolute pathname and tilde expansion | # file must exist; symbolic links are # resolved: realpath("foo") realpath("/foo") realpath("../foo") realpath("./foo") # no function for tilde expansion | # symbolic links are not resolved: os.path.abspath('foo') os.path.abspath('/foo') os.path.abspath('../foo') os.path.abspath('./foo') os.path.expanduser('~/foo') | # symbolic links are not resolved: File.expand_path("foo") File.expand_path("/foo") File.expand_path("../foo") File.expand_path("./foo") File.expand_path("~/foo") | |
iterate over directory by file | if ($dir = opendir("/etc")) { while ($file = readdir($dir)) { echo "$file\n"; } closedir($dir); } | for filename in os.listdir('/etc'): print(filename) | Dir.open("/etc").each do |file| puts file end | |
glob paths | foreach (glob("/etc/*") as $file) { echo "$file\n"; } | import glob for path in glob.glob('/etc/*'): print(path) | Dir.glob("/etc/*").each do |path| puts path end | |
make directory | mkdir("/tmp/foo/bar", 0755, TRUE); | dirname = '/tmp/foo/bar' if not os.path.isdir(dirname): os.makedirs(dirname) | require 'fileutils' FileUtils.mkdir_p("/tmp/foo/bar") | |
recursive copy | none | import shutil shutil.copytree('/tmp/foodir', '/tmp/bardir') | require 'fileutils' FileUtils.cp_r("/tmp/foodir", "/tmp/bardir") | |
remove empty directory | rmdir("/tmp/foodir"); | os.rmdir('/tmp/foodir') | File.rmdir("/tmp/foodir") | |
remove directory and contents | none | import shutil shutil.rmtree('/tmp/foodir') | require 'fileutils' FileUtils.rm_rf("/tmp/foodir") | |
directory test | is_dir("/tmp") | os.path.isdir('/tmp') | File.directory?("/tmp") | |
generate unused directory | import tempfile path = tempfile.mkdtemp(dir='/tmp', prefix='foo') | require 'tmpdir' path = Dir.mktmpdir("/tmp/foo") | ||
system temporary file directory | sys_get_temp_dir() | import tempfile tempfile.gettempdir() | require 'tmpdir' Dir.tmpdir | |
processes and environment | ||||
node | php | python | ruby | |
command line arguments and script name | process.argv.slice(2) process.argv[1] // process.argv[0] contains "node" | $argv $_SERVER["SCRIPT_NAME"] | sys.argv[1:] sys.argv[0] | ARGV $PROGRAM_NAME |
environment variable get, set | process.env["HOME"] process.env["PATH"] = "/bin"; | getenv("HOME") putenv("PATH=/bin"); | os.getenv('HOME') os.environ['PATH'] = '/bin' | ENV["HOME"] ENV["PATH"] = "/bin" |
get pid, parent pid | process.pid none | posix_getpid() posix_getppid() | os.getpid() os.getppid() | Process.pid Process.ppid |
user id and name | $uid = posix_getuid(); $uinfo = posix_getpwuid($uid); $username = $uinfo["name"]; | import getpass os.getuid() getpass.getuser() | require 'etc' Process.uid Etc.getpwuid(Process.uid)["name"] | |
exit | process.exit(0); | exit(0); | sys.exit(0) | exit(0) |
set signal handler | import signal def handler(signo, frame): print('exiting...') sys.exit(1) signal.signal(signal.SIGINT, handler) | Signal.trap("INT", lambda do |signo| puts "exiting..." exit 1 end ) | ||
executable test | is_executable("/bin/ls") | os.access('/bin/ls', os.X_OK) | File.executable?("/bin/ls") | |
external command | system("ls -l /tmp", $retval); if ($retval) { throw new Exception("ls failed"); } | if os.system('ls -l /tmp'): raise Exception('ls failed') | unless system("ls -l /tmp") raise "ls failed" end | |
shell-escaped external command | $path = chop(fgets(STDIN)); $safe = escapeshellarg($path); system("ls -l " . $safe, $retval); if ($retval) { throw new Exception("ls failed"); } | import subprocess cmd = ['ls', '-l', '/tmp'] if subprocess.call(cmd): raise Exception('ls failed') | path = gets path.chomp! unless system("ls", "-l", path) raise "ls failed" end | |
command substitution | $files = `ls -l /tmp`; | import subprocess cmd = ['ls', '-l', '/tmp'] files = subprocess.check_output(cmd) | files = `ls -l /tmp` unless $?.success? raise "ls failed" end files = %x(ls) unless $?.success? raise "ls failed" end | |
option parsing | ||||
node | php | python | ruby | |
command line options boolean option, option with argument, usage | // $ npm install commander program = require('commander'); program.option('-f, —file <file>') .option('-v, —verbose') .parse(process.argv); var file = program.file; var verbose = program.verbose; // The flags -h and --help are generated // automatically. // // Processing stops at the first positional // argument. // // Positional arguments are available // in program.args. | $usage = "usage: " . $_SERVER["SCRIPT_NAME"] . " [-f FILE] [-v] [ARG ...]\n"; $opts = getopt("f:hv", array("file:", "help", "verbose")); if (array_key_exists("h", $opts) || array_key_exists("help", $opts)) { echo $usage; exit(0); } $file = $opts["f"] ? $opts["f"] : $opts["file"]; if (array_key_exists("v", $opts) || array_key_exists("verbose", $opts)) { $verbose = TRUE; } # Processing stops at first positional # argument. # # Unrecognized options are ignored. # An option declared to have an # argument is ignored if the argument # is not provided on the command line. # # getopt() does not modify $argv or # provide means to identify positional # arguments. | import argparse parser = argparse.ArgumentParser() parser.add_argument('positional_args', nargs='*', metavar='ARG') parser.add_argument('--file', '-f', dest='file') parser.add_argument('--verbose', '-v', dest='verbose', action='store_true') args = parser.parse_args() the_file = args.file verbose = args.verbose # The flags -h and --help and the # usage message are generated # automatically. # # Positional arguments are in # args.positional_args # # Options can follow positional # arguments. | require 'optparse' options = {} OptionParser.new do |opts| opts.banner = "usage: #{$0} [OPTIONS] [ARG ...]" opts.on("-f", "--file FILE") do |arg| options[:file] = arg end opts.on("-v", "--verbose") do |arg| options[:verbose] = arg end end.parse! file = options[:file] verbose = options[:verbose] # The flags -h and --help and the # usage message are generated # automatically. # # After calling OptionParser.parse! only # positional arguments are in ARGV. # # Options can follow positional args. |
libraries and namespaces | ||||
node | php | python | ruby | |
load library | var foo = require('./foo.js'); var foo = require('foo'); | require_once("foo.php"); | # searches sys.path for foo.pyc or foo.py: import foo | require 'foo.rb' # searches $LOAD_PATH for foo.rb, foo.so, # foo.o, foo.dll: require 'foo' |
load library in subdirectory | var bar = require('./foo/bar.js'); | require_once('foo/bar.php'); | # foo must contain __init__.py file import foo.bar | require 'foo/bar.rb' require 'foo/bar' |
hot patch | delete require.cache[require.resolve('./foo.js')]; var foo = require('./foo.js'); | require("foo.php"); | reload(foo) | load 'foo.rb' |
load error | raises Errror exception | require and require_once raise fatal error if library not found; include andinclude_once emit warnings | raises ImportError if library not found; exceptions generated when parsing library propagate to client | raises LoadError if library not found; exceptions generated when parsing library propagate to client |
main routine in library | if (require.main == module) { code } | none | if __name__ == '__main__': code | if $PROGRAM_NAME == __FILE__ code end |
library path | none | $libpath = ini_get("include_path"); ini_set("include_path", $libpath . ":/some/path"); | sys.path sys.path.append('/some/path') | # $: is synonym for $LOAD_PATH: $LOAD_PATH $LOAD_PATH << "/some/path" |
library path environment variable | $ NODE_PATH=~/lib node foo.js | none | $ PYTHONPATH=~/lib python foo.py | $ RUBYLIB=~/lib ruby foo.rb |
library path command line option | none | none | none | $ ruby -I ~/lib foo.rb |
simple global identifiers | variables defined outside of functions or with global keyword | built-in functions | variables which start with $ | |
multiple label identifiers | classes, interfaces, functions, and constants | modules | constants, classes, and modules | |
label separator | \Foo\Bar\baz(); | foo.bar.baz() | Foo::Bar.baz | |
root namespace definition | \foo | none | # outside of class or module; only # constants in root namespace: FOO = 3 # inside class or module: ::FOO = 3 | |
namespace declaration | namespace Foo; | put declarations in foo.py | class Foo # class definition end module Foo # module definition end | |
child namespace declaration | namespace Foo\Bar; | foo must be in sys.path: $ mkdir foo $ touch foo/__init__.py $ touch foo/bar.py | module Foo::Bar # module definitions end module Foo module Bar # module definitions end end # classes can nest inside classes or # modules; modules can nest in classes | |
import definitions | only class names can be imported | from foo import bar, baz | none | |
import all definitions in namespace | none | from foo import * | # inside class or module: include Foo | |
import all subnamespaces | # subnamespaces in list __all__ of # foo/__init__.py are imported from foo import * | |||
shadow-avoidance | use Foo as Fu; | # rename namespace: import foo as fu # rename identifier: from sys import path as the_path | Fu = Foo.dup include Fu | |
list installed packages, install a package | $ pear list $ pear install Math_BigInteger | $ pip freeze $ pip install jinja2 | $ gem list $ gem install rails | |
package specification format | in setup.py: #!/usr/bin/env python from distutils.core import setup setup( name='foo', author='Joe Foo', version='1.0', description='a package', py_modules=['foo']) | in foo.gemspec: spec = Gem::Specification.new do |s| s.name = "foo" s.authors = "Joe Foo" s.version = "1.0" s.summary = "a gem" s.files = Dir["lib/*.rb"] end | ||
objects | ||||
javascript | php | python | ruby | |
define class | function Int(i) { this.value = i === undefined ? 0 : i; } | class Int { public $value; function construct($int=0) { $this->value = $int; } } | class Int(object): def __init__(self, v=0): self.value = v | class Int attr_accessor :value def initialize(i=0) @value = i end end |
create object | var i = new Int(); var i2 = new Int(7); | $i = new Int(); $i2 = new Int(7); | i = Int() i2 = Int(7) | i = Int.new i2 = Int.new(7) |
instance variable visibility | public | visibility must be declared | public; attributes starting with underscore private by convention | private by default; use attr_reader, attr_writer, attr_accessor to make public |
get and set instance variable | var v = i.value; i.value = v + 1; | $v = $i->value; $i->value = $v + 1; | v = i.value i.value = v + 1 | v = i.value i.value = v + 1 |
define method | // inside constructor: this.plus = function(v) { return this.value + v; }; // outside constructor: Int.prototype.plus = function (v) { return this.value + v; } | function plus($i) { return $this->value + $i; } | def plus(self,v): return self.value + v | def plus(i) value + i end |
invoke method | i.plus(3); | $i->plus(7) | i.plus(7) | i.plus(7) |
define class method | @classmethod def get_instances(cls): return Counter.instances | class Foo def Foo.one puts "one" end end | ||
invoke class method | Counter::getInstances() | Counter.get_instances() | Foo.one | |
define class variable | class Foo: instances = 0 | class Foo @@instances = 1 end | ||
get and set class variable | class Foo: def __init(self): Foo.instances += 1 | class Foo def initialize @@instances += 1 end end | ||
handle undefined method invocation | function __call($name, $args) { $argc = count($args); echo "no def: $name " . "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 | |
alias method | class Point attr_reader :x, :y, :color alias_method :colour, :color def initialize(x, y, color=:black) @x, @y = x, y @color = color end end | |||
destructor | function __destruct() { echo "bye, $this->value\n"; } | def __del__(self): print('bye, %d' % self.value) | val = i.value ObjectSpace.define_finalizer(int) { puts "bye, #{val}" } | |
inheritance and polymorphism | ||||
javascript | php | python | ruby | |
subclass | 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; } } | 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 | |
mixin | ||||
overload operator | class Fixnum def /(n) self.fdiv(n) end end | |||
reflection | ||||
javascript | php | python | ruby | |
object id | none | id(o) | o.object_id | |
inspect type | typeof([]) === 'object' | gettype(array()) == "array" returns object for objects | type([]) == list | [].class == Array |
basic types | number string boolean undefined function object # these evaluate as 'object': typeof(null) typeof([]) typeof({}) | NULL boolean integer double string array object resource unknown type | NoneType bool int long float str SRE_Pattern datetime list array dict object file | NilClass TrueClass FalseClass Fixnum Bignum Float String Regexp Time Array Hash Object File |
inspect class | // returns prototype object: Object.getPrototypeOf(o) | returns FALSE if not an object: get_class($o) == "Foo" | o.__class__ == Foo isinstance(o, Foo) | o.class == Foo o.instance_of?(Foo) |
inspect class hierarchy | var pa = Object.getPrototypeOf(o) //prototype's of prototype object: var grandpa = Object.getPrototypeOf(pa) | get_parent_class($o) | o.__class__.__bases__ | o.class.superclass o.class.included_modules |
has method? | o.reverse && typeof(o.reverse) === 'function' | method_exists($o, "reverse") | hasattr(o, 'reverse') | o.respond_to?("reverse") |
message passing | not a standard feature | for ($i = 1; $i <= 10; $i++) { call_user_func(array($o, "phone$i"), NULL); } | for i in range(1,10): getattr(o, 'phone'+str(i))(None) | (1..9).each do |i| o.send("phone#{i}=", nil) end |
eval | eval('1 + 1') | eval evaluates to argument of returnstatement or NULL: while ($line = fgets(STDIN)) { echo eval($line) . "\n"; } | argument of eval must be an expression: while True: print(eval(sys.stdin.readline())) | loop do puts eval(gets) end |
list object methods | get_class_methods($o) | [m for m in dir(o) if callable(getattr(o,m))] | o.methods | |
list object attributes | get_object_vars($o) | dir(o) | o.instance_variables | |
list loaded libraries | # relative to directory in lib path: $LOADED_FEATURES $" | |||
list loaded namespaces | dir() | Class.constants.select do |c| Module.const_get(c).class == Class end | ||
inspect namespace | import urlparse dir(urlparse) | require 'uri' URI.constants URI.methods URI.class_variables | ||
pretty-print | $d = array("lorem"=>1, "ipsum"=>array(2,3)); print_r($d); | import pprint d = {'lorem':1, 'ipsum':[2,3]} pprint.PrettyPrinter().pprint(d) | require 'pp' d = {'lorem' => 1, 'ipsum' => [2, 3]} pp d | |
source line number and file name | __LINE__ __FILE__ | import inspect cf = inspect.currentframe() cf.f_lineno cf.f_code.co_filename | __LINE__ __FILE__ | |
command line documentation | none | $ pydoc math $ pydoc math.atan2 | $ ri -c $ ri Math $ ri Math.atan2 | |
net and web | ||||
javascript | php | python | ruby | |
get local hostname, dns lookup, reverse dns lookup | $host = gethostname(); $ip = gethostbyname($host); $host2 = gethostbyaddr($ip); | import socket host = socket.gethostname() ip = socket.gethostbyname(host) host2 = socket.gethostbyaddr(ip)[0] | require 'socket' hostname = Socket.gethostname ip = Socket.getaddrinfo( Socket.gethostname, "echo")[0][3] host2 = Socket.gethostbyaddr(ip)[0] | |
http get | $url = 'http://www.google.com'; $s = file_get_contents($url); | import httplib url = 'www.google.com' conn = httplib.HTTPConnection(url) conn.request("GET", '/') resp = conn.getresponse() if resp.status == httplib.OK: s = resp.read() | require 'net/http' url = "www.google.com" r = Net::HTTP.start(url, 80) do |f| f.get("/") end if r.code == "200" s = r.body end | |
http post | import httplib import urllib url = 'www.acme.com' conn = httplib.HTTPConnection(url) data = urllib.urlencode({ 'item': 'anvil', 'qty': 1}) conn.request('POST', '/orders', data) resp = conn.getresponse() if resp.status == httplib.OK: s = resp.read() | |||
serve working directory | $ php -S localhost:8000 | $ python -m SimpleHTTPServer 8000 | $ ruby -rwebrick -e \ 'WEBrick::HTTPServer.new(:Port => 8000, '\ ':DocumentRoot => Dir.pwd).start' | |
absolute url from base and relative url | none | import urlparse urlparse.urljoin('http://google.com', 'analytics') | require 'uri' URI.join("http://google.com", "analytics") | |
parse url | $url = "http://google.com:80/foo?q=3#bar"; $up = parse_url($url); $protocol = $up["scheme"]; $hostname = $up["host"]; $port = $up["port"]; $path = $up["path"]; $query_str = $up["query"]; $fragment = $up["fragment"]; # $params is associative array; if keys # are reused, later values overwrite # earlier values parse_str($query_str, $params); | # Python 3 location: urllib.parse import urlparse url = 'http://google.com:80/foo?q=3#bar' up = urlparse.urlparse(url) protocol = up.scheme hostname = up.hostname port = up.port path = up.path query_str = up.query fragment = up.fragment # returns dict of lists: params = urlparse.parse_qs(query_str) | require 'uri' url = "http://google.com:80/foo?q=3#bar" up = URI(url) protocol = up.scheme hostname = up.host port = up.port path = up.path query_str = up.query fragment = up.fragment # Ruby 1.9; returns array of pairs: params = URI.decode_www_form(query_str) | |
url encode/decode | urlencode("lorem ipsum?") urldecode("lorem+ipsum%3F") | # Python 3 location: urllib.parse import urllib urllib.quote_plus("lorem ipsum?") urllib.unquote_plus("lorem+ipsum%3F") | require 'cgi' CGI::escape("lorem ipsum?") CGI::unescape("lorem+ipsum%3F") | |
html escape escape character data, escape attribute value, unescape html entities | $s = htmlspecialchars("<>&"); $s2 = htmlspecialchars("<>&\"'", ENT_NOQUOTES | ENT_QUOTES); $s3 = htmlspecialchars_decode($s2); | import cgi from HTMLParser import HTMLParser s = cgi.escape('<>&') s2 = cgi.escape('<>&"', True) s3 = HTMLParser().unescape( | require 'cgi' s2 = CGI.escapeHTML('<>&"') s3 = CGI.unescapeHTML(s2) | |
base64 encode/decode | $s = file_get_contents("foo.png"); $b64 = base64_encode($s); $s2 = base64_decode($b64); | import base64 s = open('foo.png').read() b64 = base64.b64encode(s) s2 = base64.b64decode(b64) | require 'base64' s = File.open("foo.png").read b64 = Base64.encode64(s) s2 = Base64.decode64(b64) | |
gui | ||||
node | php | python | ruby | |
pop-up box | var app = Application.currentApplication() app.includeStandardAdditions = true app.displayAlert('hi world') | |||
unit tests | ||||
node | php | python | ruby | |
test class | // npm install -g nodeunit exports.testFoo = function(test) { test.ok(true, 'not true!.'); test.done(); } | # pear install pear.phpunit.de/PHPUnit <?php Class FooTest extends PHPUnit_Framework_TestCase { public function test_01() { $this->assertTrue(true, "not true!"); } } ?> | import unittest class TestFoo(unittest.TestCase): def test_01(self): self.assertTrue(True, 'not True!') if __name__ == '__main__': unittest.main() | require 'test/unit' class TestFoo < Test::Unit::TestCase def test_01 assert(true, "not true!") end end |
run tests, run test method | $ nodeunit test_foo.js $ nodeunit -t testFoo test_foo.js | $ phpunit test_foo.php $ phpunit --filter test_01 test_foo.php | $ python test_foo.py $ python test_foo.py TestFoo.test_01 | $ ruby test_foo.rb $ ruby test_foo.rb -n test_01 |
equality assertion | var s = 'do re mi'; test.equals(s, 'do re mi'); | $s = "do re me"; $this->assertEquals($s, "do re mi"); # also asserts args have same type: $this->assertSame($s, "do re mi"); | s = 'do re me' self.assertEqual('do re me', s, 's: {}'.format(s)) | s = "do re me" assert_equal("do re me", s) |
approximate assertion | $x = 10.0 * (1.0 / 3.0); $y = 10.0 / 3.0; $this->assertEquals($x, $y, "not within delta", pow(0.1, 6)); | x = 10.0 * (1.0 / 3.0) y = 10.0 / 3.0 # default for delta is 0.1**7 self.assertAlmostEqual(x, y, delta=0.1**6) | x = 10.0 * (1.0 / 3.0) y = 10.0 / 3.0 # default for delta is 0.001 assert_in_delta(x, y, 0.1**6) | |
regex assertion | $s = "lorem ipsum"; $this->assertRegExp("/lorem/", $s); | s = 'lorem ipsum' # uses re.search, not re.match: self.assertRegexpMatches(s, 'lorem') | s = "lorem ipsum" assert_match(/lorem/, s) | |
exception assertion | class Bam extends Exception {}; public function test_exc { $this->SetExpectedException("Bam"); throw new Bam("bam!"); } | a = [] with self.assertRaises(IndexError): a[0] | assert_raises(ZeroDivisionError) do 1 / 0 end | |
mock method | $mock = $this->getMock('Foo', ['foo']); $mock->expects($this->once()) ->method('foo') ->with(13) ->will($this->returnValue(7)); $mock->foo(13); | # pip install mock import mock foo = Foo() foo.run = mock.MagicMock(return_value=7) self.assertEqual(7, foo.run(13)) foo.run.assert_called_once_with(13) | # gem install mocha require 'mocha' foo = mock() foo.expects(:run).returns(7).with(13).once foo.run(13) | |
setup | exports.setUp = function(callback) { console.log('setting up...'); callback(); } | public function setUp() { echo "setting up\n"; } | # in class TestFoo: def setUp(self): print('setting up') | # in class TestFoo: def setup puts "setting up" end |
teardown | exports.tearDown = function(callback) { console.log('tearing down...'); callback(); } | public function tearDown() { echo "tearing down\n"; } | # in class TestFoo: def tearDown(self): print('tearing down') | # in class TestFoo: def teardown puts "tearing down" end |
debugging and profiling | ||||
javascript | php | python | ruby | |
check syntax | $ php -l foo.php | import py_compile # precompile to bytecode: py_compile.compile('foo.py') | $ ruby -c foo.rb | |
flags for stronger and strongest warnings | none | $ python -t foo.py $ python -3t foo.py | $ ruby -w foo.rb $ ruby -W2 foo.rb | |
lint | $ npm install jshint $ ./node_modules/jshint/bin/jshint foo.js | $ sudo pip install pylint $ pylint foo.py | $ sudo gem install rubocop $ rubocop -D foo.rb | |
source cleanup | $ sudo pip install pep8 $ pep8 foo.py | $ sudo gem install rubocop $ rubocop -D foo.rb | ||
run debugger | $ python -m pdb foo.py | $ sudo gem install ruby-debug $ rdebug foo.rb | ||
debugger commands | h l n s b c w u d p q | h l n s b c w u down p q | ||
benchmark code | import timeit timeit.timeit('i += 1', 'i = 0', number=1000000) | require 'benchmark' n = 1_000_000 i = 0 puts Benchmark.measure do n.times { i += 1 } end | ||
profile code | $ python -m cProfile foo.py | $ sudo gem install ruby-prof $ ruby-prof foo.rb | ||
java interoperation | ||||
javascript | php | python | ruby | |
version | Jython 2.5 compatible with Python 2.5 :( | JRuby 1.7 compatible with Ruby 1.9 | ||
repl | $ jython | $ jirb | ||
interpreter | $ jython | $ jruby | ||
compiler | none | $ jrubyc | ||
prologue | import java | none | ||
new | rnd = java.util.Random() | rnd = java.util.Random.new | ||
method | rnd.nextFloat() | rnd.next_float | ||
import | from java.util import Random rnd = Random() | java_import java.util.Random rnd = Random.new | ||
non-bundled java libraries | import sys sys.path.append('path/to/mycode.jar') import MyClass | require 'path/to/mycode.jar' | ||
shadowing avoidance | import java.io as javaio | module JavaIO include_package "java.io" end | ||
convert native array to java array | import jarray jarray.array([1, 2, 3], 'i') | [1, 2, 3].to_java(Java::int) | ||
are java classes subclassable? | yes | yes | ||
are java class open? | no | yes | ||
____________________________________________ | ____________________________________________ | ____________________________________________ | ____________________________________________ |
Subscribe to:
Post Comments
(
Atom
)
No comments :
Post a Comment