HHVM + HACK
A quick introduction
HHVM
• Stands for HipHop Virtual Machine
• Executes scripts written in PHP (5.4) and Hack
• Drop-in replacement for php-fpm
• Use together with FastCGI-enabled webserver
(like Apache or nginx)
Timeline
• 2008: Facebook begins work on HipHop, a PHP to C++ compiler
• 2010: Facebook opensources the compiler (HPHPc) and dev interpreter/
debugger (HPHPi and HPHPd)
• 2010: Facebook begins work on HHVM
• 2013: HPHPc deprecated, replaced by HHVM in Facebook production servers
• 2013: HHVM 2.3.0 adds FastCGI support
• 2014: HHVM 3.0.0 adds Hack support
Installation
• Ubuntu
add-apt-repository -y ppa:mapnik/boost!
wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add -!
echo "deb http://dl.hhvm.com/ubuntu precise main" > /etc/apt/sources.list.d/hhvm.list!
apt-get update!
apt-get install hhvm!
• Note: there is no more hhvm-fastcgi package. For the latest
code, you can use hhvm-nightly
• https://github.com/facebook/hhvm/wiki/Prebuilt-Packages-on-
Ubuntu-12.04
Installation
• OSX (using Homebrew)
brew tap homebrew/dupes!
brew tap homebrew/versions!
brew tap mcuadros/homebrew-hhvm!
brew install hhvm --HEAD!
• https://github.com/facebook/hhvm/wiki/Building-and-
installing-HHVM-on-OSX-10.9
• Unfortunately, the typechecker (hh_server / hh_client)
does not build on OSX
Installation
• Windows
• … just use Vagrant and Virtualbox
Usage
• Using from the command line

hhvm foobar.php
• Or you can make use of this:

sudo /usr/bin/update-alternatives --install 

/usr/bin/php php /usr/bin/hhvm 60
• Now you can run

php foobar.php
Usage
• Apache 2.2: install libapache2-mod-fastcgi
<IfModule mod_fastcgi.c>!
Alias /hhvm.fastcgi /var/www/fastcgi/hhvm.fastcgi!
FastCGIExternalServer /var/www/fastcgi/hhvm.fastcgi -socket /var/run/hhvm/socket -pass-header
!! ! Authorization -idle-timeout 300!
<Directory "/var/www/fastcgi">!
<Files "hhvm.fastcgi">!
Order deny,allow!
</Files>!
</Directory>!
!
AddHandler hhvm-hack-extension .hh!
AddHandler hhvm-php-extension .php!
!
Action hhvm-hack-extension /hhvm.fastcgi virtual!
Action hhvm-php-extension /hhvm.fastcgi virtual!
</IfModule>
Usage
• Apache 2.4: mod_proxy + mod_proxy_fcgi

ProxyPass / fcgi://127.0.0.1:9000/root/path
• Or

ProxyPassMatch ^/(.*.(hh|php)(/.*)?)$
fcgi://127.0.0.1:9000/root/path/$1
Usage
• nginx: just like your regular php-fpm

location ~ .(hh|php)$ {!
root /path/to/your/root!
fastcgi_pass 127.0.0.1:9000;!
fastcgi_index index.php;!
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;!
include /etc/nginx/fastcgi_params;!
}

Using with Composer
• Add to .bashrc or equivalent:

alias composer="hhvm -v ResourceLimit.SocketDefaultTimeout=30
-v Http.SlowQueryThreshold=30000 /usr/local/bin/composer"
• Up to 5x faster
Extensions
• HHVM ships with several common extensions, listed here:

https://github.com/facebook/hhvm/wiki/Extensions
• Usually, to add an extension, you write it in pure PHP (e.g. the Redis
extension) and place it alongside the source code, to be compiled
together with HHVM
• You may also use HNI (HHVM-Native Interface) for hybrid PHP/C++
implementations
• Can be fashioned as an externally buildable DSO, e.g. mongofill
Performance
• Up to 2x faster compared to PHP 5.5

(Sample benchmark performed by Christian Stocker with Symfony 2.4)

http://blog.liip.ch/archive/2013/10/29/hhvm-and-symfony2.html
Caveats
• PHP 5.5 generator syntax incompatibility (#1627, #1787, #1871)
• Missing PHP 5.4 Closure::bind and Closure::bindTo (#1203)
• Cannot set multiple cookies with same name but different path (#2494, #2526)
• func_get_args() returns arguments by references instead of values (#1027) (wontfix)
• array_key_exists(), reset(), end(), etc. don't work with ArrayAccess (#1221) (wontfix)
• missing fastcgi_finish_request() equivalent (#1230)
• https://github.com/facebook/hhvm/issues?labels=php5+incompatibility&state=open
Hack
• Basically a superset of PHP, the most important addition being static typing
• Hack files should begin with <?hh instead of <?php
• Can be used in 3 modes: "strict", "partial" (default) and "decl", e.g. <?hh //
strict
• "// UNSAFE" annotation used to disable type checking for a particular block
• Decl mode basically disables type checking for the entire file, enables strict
mode to call into legacy code
• Type annotations are thrown away at runtime
Type annotations
• This allows validation by the Hack typechecker before runtime
• Paired with IDE support, can be helpful when refactoring code
• Scalar type hinting is now possible

class MyClass {!
const int MyConst = 0;!
private string $x = '';!
!
public function increment(int $x): int {!
$y = $x + 1;!
return $y;!
}!
}
Supported types
• Primitives: int, float, string, bool, array
• User-defined classes: Foo, Vector<some type>
• Mixed: mixed
• Void: void
• Nullable: ?<type> (e.g., ?int, ?bool)
• Soft: @<type> (e.g. @int, @bool)
• Typed arrays: array<Foo>, array<string, array<string, Foo>>
• Tuples: (<type1>, <type2>, ....) e.g. (string, int)
Supported types
• XHP elements :x:frag, :x:base, :div, :xhp
• Generics: Foo<T>
• Closures: (function(<type1>, <type2>, ...): return_type)

e.g. (function(string, int): string)
• Resources: resource
• Continuation (generator): Continuation<T>
• Awaitable (async): Awaitable<T>
• Same type: this
Supported types
• Note that:
• Untyped arrays are not allowed in strict mode
• Do not annotate return values for __construct()
(typechecker will complain)
• "this" only checks for same type, not same instance
Generics
class Box<T> {!
protected T $data;!
!
public function __construct(T $data) {!
$this->data = $data;!
}!
public function setData(T $data): void {!
$this->data = $data;!
}!
public function getData(): T {!
return $this->data;!
}!
}!
!
function swap<T>(Box<T> $a, Box<T> $b): T {!
$temp = $a->getData();!
$a->setData($b->getData());!
$b->setData($temp);!
return $temp;!
}!
• For each instance, once a type is associated with T, it’s fixed
Nullable types
class NullableBox<T> {!
protected ?T $data;!
!
public function __construct(?T $data) {!
$this->data = $data;!
}!
!
public function getData(): ?T {!
return $this->data;!
}!
}!
!
$box = new NullableBox(null);!
!
!
function check_not_null(?int $x): int {!
return $x === null ? -1 : $x;!
}!
Soft types
• Apparently not documented
• Emits warnings rather than fatal errors for
invalid types
!
!
class Calculator {!
public function add(@int $a, @int $b): @string {}!
}!
!
$calc = new Calculator();!
$calc->add("1", "2");
Typed arrays
• Untyped arrays are only allowed in partial or decl mode
• In strict mode you must explicitly type the values:
array<Foo>!
• Or both keys and values:
array<string, ?string>!
• You can simulate PHP behaviour, but this defeats the
purpose:
array<mixed, mixed>
Type aliasing
• Redefine an existing type name
type MyInteger = int;!
• “Opaque” types disallow other files from accessing the
underlying implementation (e.g. concatenation for strings)
// File1.php!
newtype MyString = string;!
!
// File2.php!
require_once "File1.php";!
!
function modifyString(MyString $s): MyString {!
return $s . "1"; // Hack type checker will throw an error!
}
Tuples and shapes
• Tuples are basically immutable typed arrays
public function baz(): (string, int) {!
return tuple("Hello", 3);!
}!
• Shapes are kinda like structs
type MyShape = shape('id1' => string, 'id2' => int);!
function foo(MyShape $x): void {}
Collections
• Vector, Map, Set, Pair
• Immutable versions: ImmVector, ImmMap, ImmSet
• Can be initialised using literal syntax
$vec = Vector {'foo', 'foo', 'bar'}; // integer keys!
$map = Map {42 => 'foo', 73 => 'bar', 144 => 'baz'}; // ordered dictionary!
$set = Set {'php', 'hack', 'hhvm'}; // unordered unique values!
$par = Pair {'guid', 'ABC123'}; // only two pieces of data!
• Type annotation
function getTags(): Set<string> {!
return Set { "php", "hack", "hhvm" };!
}
Collections
• Some method signatures for Vector…
public function __construct(?Traversable<Tv> $it)!
public function add(Tv $value): Vector<Tv>!
public function addAll(?Traversable<Tv> $it): Vector<Tv>!
public function at(int $k): Tv!
public function clear(void): Vector<Tv>!
public function containsKey(int $k): bool!
public function count(void): int!
public function filter((function(Tv): bool) $callback): Vector<Tv>!
public function filterWithKey((function(int, Tv): bool) $callback): Vector<Tv>!
public function fromArray(array $arr): Vector<Tv>!
public function fromItems(?Traversable<Tv> $items): Vector<Tv>!
public function get(int $k): ?Tv!
public function getIterator(void): KeyedIterator<int, Tv>!
public function isEmpty(void): bool!
public function items(void): Iterable<Tv>!
public function keys(void): Vector<int>!
public function reverse(void): void!
public function set(int $k, Tv $v): Vector<Tv>!
public function setAll(?KeyedTraversable<int, Tv> $it): Vector<Tv>!
public function __toString(void): string!
public function toValuesArray(void): array!
public function zip<Tu>(Traversable<Tu> $iterable): Vector<Pair<Tv, Tu>>
In other words, Hack really, really wants you
to stop using simple arrays (or even
ArrayObjects) as a “catch-all” data container
Lambdas
• Use the lambda arrow ==>

(Because -> and => are already taken):
function concat(): (function(string, string): string) {!
return ($x, $y) ==> {!
return $y . $x;!
};!
}!
• Implicitly capture variables from outer scope

Can be an expression:
function foo(): (function(string): string) {!
$x = 'bar';!
return $y ==> $y . $x;!
}
Lambdas
• Type hints are not checked at the moment
• Doesn't support capturing variables by reference or
returning by reference yet
• Lambda arrow operator is right associative and can be
chained:
!
$f = $x ==> $y ==> $x + $y;!
$g = $f(7);!
echo $g(4); // 11
Variadic functions
function sum(...): int {!
$s = 0;!
foreach (func_get_args() as $e) {!
$s += $e;!
}!
return $s;!
}!
• Cannot be type annotated, unfortunately
Override attribute
• Signify that the parent method must exist
class Hello {!
public function render(): void {!
echo 'hello';!
}!
}!
!
class HelloWorld extends Hello!
{!
<<Override>> public function render(): void {!
parent::render();!
echo ' world';!
}!
}
Constructor arg promotion
class Person {!
private string $name;!
private int $age;!
!
public function __construct(string $name, int $age) {!
$this->name = $name;!
$this->age = $age;!
}!
}!
• can be written as
!
class Person {!
public function __construct(private string $name, private int $age) {}!
}
Callbacks
• This will not work in strict mode:
$func = 'myFunc';!
$x = $func(4);!
• fun() will return a callable, which allows the typechecker to properly validate:
$func = fun('myFunc');!
$x = $func(4);!
• Similar dubiously-named functions exist for calling static/instance methods:
// $bar = array_map(array('Foo', ‘doStuff'), [1, 2, 3]);!
$bar = array_map(class_meth('Foo', 'doStuff'), [1, 2, 3]);!
!
$foo = new Foo();!
$bar = array_map(instance_meth($foo, 'doStuff'), [1, 2, 3]);!
!
$func = meth_caller('Foo', 'doStuff');!
$foo = new Foo();!
$x = $func($foo);
Async and await
async function gen_foo(int $a): Awaitable<?Foo> {!
if ($a === 0) {!
return null;!
}!
$bar = await gen_bar($a);!
if ($bar !== null) {!
return $bar->getFoo();!
}!
return null;!
}!
!
async function gen_bar(int $a): Awaitable<?Bar> {!
if ($a === 0) {!
return null;!
}!
return new Bar();!
}!
!
gen_foo(4);
Running the type checker
• Run hh_client (it will launch hh_server for you) or
hh_server --check .
• Recursively looks for directories that contain
a .hhconfig file (it won’t run if this is missing)
• Optionally return output in json format
• Note: does not follow symlinks
Unsupported features
• Still runs in HHVM, but the type checker does not like the following:
• goto, if: … endif; etc
• AND, OR, XOR
• References (&)
• Error suppression (@)
• break N, continue N
• eval()
• globals
Unsupported features
• list(, $b) = array(3, 4); should be list($_, $b) = array(3, 4);
• Function calls are case-sensitive
• Strict mode does not support top-level code except for require() and
require_once(); i.e. everything else must be in a class or function
• Does not support "variable variables" (e.g. $$a) or extract()
• Cannot call parent::staticMethod()
• Cannot declare a class method with a name that collides with class name
• Cannot pass primitives by reference
Drawbacks
• Still new, not yet 100% compatibility (but catching up fast)
• Your favourite extension may not be available
• Limited IDE support at the moment (weekend project idea?)
• Hack-exclusive libraries? Package repos? Community
fragmentation?
• Clashes with PHP 5.5 and future 5.6 syntax

(generators and variadic functions)
• Generator functions are of the type
“Continuation” in HHVM (since they were
implemented earlier)
• The following is valid in PHP 5.5 but not in HHVM:
$data = (yield $value); // delete the brackets for HHVM!
$data = yield; // HHVM needs expression after yield!
• HHVM Continuations need to be “primed” unlike
PHP 5.5 Generators
$generator = construct_generator();!
$generator->current(); // must call next() first in HHVM!
• Proposed PHP 5.6 syntax for variadic
functions:
function fn($arg, ...$args) {}!
function fn($arg, &...$args) {}!
function fn($arg, callable ...$args) {}!
• Type-hinting and arguments by value not
supported in HHVM / Hack
function fn(...): void {}
Benefits
• Type safety!!! (Always use the type checker)
• Syntactic sugar from other languages
• Discard “bad” parts of PHP
• Active community (e.g. New Relic has released a
prototype HHVM extension, Heroku just announced
HHVM support)
Resources
• http://hhvm.com/
• http://hacklang.org/
• http://docs.hhvm.com/manual/en/hacklangref.php
• https://blog.engineyard.com/2014/hhvm-hack
• http://blog.vjeux.com/2014/javascript/hack-is-to-php-what-es6-is-to-
javascript.html
• https://github.com/facebook/hhvm
Thank you
Contact:
• Chris Heng <bigblah@gmail.com>
• https://github.com/gigablah

HHVM and Hack: A quick introduction

  • 1.
    HHVM + HACK Aquick introduction
  • 2.
    HHVM • Stands forHipHop Virtual Machine • Executes scripts written in PHP (5.4) and Hack • Drop-in replacement for php-fpm • Use together with FastCGI-enabled webserver (like Apache or nginx)
  • 3.
    Timeline • 2008: Facebookbegins work on HipHop, a PHP to C++ compiler • 2010: Facebook opensources the compiler (HPHPc) and dev interpreter/ debugger (HPHPi and HPHPd) • 2010: Facebook begins work on HHVM • 2013: HPHPc deprecated, replaced by HHVM in Facebook production servers • 2013: HHVM 2.3.0 adds FastCGI support • 2014: HHVM 3.0.0 adds Hack support
  • 4.
    Installation • Ubuntu add-apt-repository -yppa:mapnik/boost! wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add -! echo "deb http://dl.hhvm.com/ubuntu precise main" > /etc/apt/sources.list.d/hhvm.list! apt-get update! apt-get install hhvm! • Note: there is no more hhvm-fastcgi package. For the latest code, you can use hhvm-nightly • https://github.com/facebook/hhvm/wiki/Prebuilt-Packages-on- Ubuntu-12.04
  • 5.
    Installation • OSX (usingHomebrew) brew tap homebrew/dupes! brew tap homebrew/versions! brew tap mcuadros/homebrew-hhvm! brew install hhvm --HEAD! • https://github.com/facebook/hhvm/wiki/Building-and- installing-HHVM-on-OSX-10.9 • Unfortunately, the typechecker (hh_server / hh_client) does not build on OSX
  • 6.
    Installation • Windows • …just use Vagrant and Virtualbox
  • 7.
    Usage • Using fromthe command line
 hhvm foobar.php • Or you can make use of this:
 sudo /usr/bin/update-alternatives --install 
 /usr/bin/php php /usr/bin/hhvm 60 • Now you can run
 php foobar.php
  • 8.
    Usage • Apache 2.2:install libapache2-mod-fastcgi <IfModule mod_fastcgi.c>! Alias /hhvm.fastcgi /var/www/fastcgi/hhvm.fastcgi! FastCGIExternalServer /var/www/fastcgi/hhvm.fastcgi -socket /var/run/hhvm/socket -pass-header !! ! Authorization -idle-timeout 300! <Directory "/var/www/fastcgi">! <Files "hhvm.fastcgi">! Order deny,allow! </Files>! </Directory>! ! AddHandler hhvm-hack-extension .hh! AddHandler hhvm-php-extension .php! ! Action hhvm-hack-extension /hhvm.fastcgi virtual! Action hhvm-php-extension /hhvm.fastcgi virtual! </IfModule>
  • 9.
    Usage • Apache 2.4:mod_proxy + mod_proxy_fcgi
 ProxyPass / fcgi://127.0.0.1:9000/root/path • Or
 ProxyPassMatch ^/(.*.(hh|php)(/.*)?)$ fcgi://127.0.0.1:9000/root/path/$1
  • 10.
    Usage • nginx: justlike your regular php-fpm
 location ~ .(hh|php)$ {! root /path/to/your/root! fastcgi_pass 127.0.0.1:9000;! fastcgi_index index.php;! fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;! include /etc/nginx/fastcgi_params;! }

  • 11.
    Using with Composer •Add to .bashrc or equivalent:
 alias composer="hhvm -v ResourceLimit.SocketDefaultTimeout=30 -v Http.SlowQueryThreshold=30000 /usr/local/bin/composer" • Up to 5x faster
  • 12.
    Extensions • HHVM shipswith several common extensions, listed here:
 https://github.com/facebook/hhvm/wiki/Extensions • Usually, to add an extension, you write it in pure PHP (e.g. the Redis extension) and place it alongside the source code, to be compiled together with HHVM • You may also use HNI (HHVM-Native Interface) for hybrid PHP/C++ implementations • Can be fashioned as an externally buildable DSO, e.g. mongofill
  • 13.
    Performance • Up to2x faster compared to PHP 5.5
 (Sample benchmark performed by Christian Stocker with Symfony 2.4)
 http://blog.liip.ch/archive/2013/10/29/hhvm-and-symfony2.html
  • 14.
    Caveats • PHP 5.5generator syntax incompatibility (#1627, #1787, #1871) • Missing PHP 5.4 Closure::bind and Closure::bindTo (#1203) • Cannot set multiple cookies with same name but different path (#2494, #2526) • func_get_args() returns arguments by references instead of values (#1027) (wontfix) • array_key_exists(), reset(), end(), etc. don't work with ArrayAccess (#1221) (wontfix) • missing fastcgi_finish_request() equivalent (#1230) • https://github.com/facebook/hhvm/issues?labels=php5+incompatibility&state=open
  • 15.
    Hack • Basically asuperset of PHP, the most important addition being static typing • Hack files should begin with <?hh instead of <?php • Can be used in 3 modes: "strict", "partial" (default) and "decl", e.g. <?hh // strict • "// UNSAFE" annotation used to disable type checking for a particular block • Decl mode basically disables type checking for the entire file, enables strict mode to call into legacy code • Type annotations are thrown away at runtime
  • 16.
    Type annotations • Thisallows validation by the Hack typechecker before runtime • Paired with IDE support, can be helpful when refactoring code • Scalar type hinting is now possible
 class MyClass {! const int MyConst = 0;! private string $x = '';! ! public function increment(int $x): int {! $y = $x + 1;! return $y;! }! }
  • 17.
    Supported types • Primitives:int, float, string, bool, array • User-defined classes: Foo, Vector<some type> • Mixed: mixed • Void: void • Nullable: ?<type> (e.g., ?int, ?bool) • Soft: @<type> (e.g. @int, @bool) • Typed arrays: array<Foo>, array<string, array<string, Foo>> • Tuples: (<type1>, <type2>, ....) e.g. (string, int)
  • 18.
    Supported types • XHPelements :x:frag, :x:base, :div, :xhp • Generics: Foo<T> • Closures: (function(<type1>, <type2>, ...): return_type)
 e.g. (function(string, int): string) • Resources: resource • Continuation (generator): Continuation<T> • Awaitable (async): Awaitable<T> • Same type: this
  • 19.
    Supported types • Notethat: • Untyped arrays are not allowed in strict mode • Do not annotate return values for __construct() (typechecker will complain) • "this" only checks for same type, not same instance
  • 20.
    Generics class Box<T> {! protectedT $data;! ! public function __construct(T $data) {! $this->data = $data;! }! public function setData(T $data): void {! $this->data = $data;! }! public function getData(): T {! return $this->data;! }! }! ! function swap<T>(Box<T> $a, Box<T> $b): T {! $temp = $a->getData();! $a->setData($b->getData());! $b->setData($temp);! return $temp;! }! • For each instance, once a type is associated with T, it’s fixed
  • 21.
    Nullable types class NullableBox<T>{! protected ?T $data;! ! public function __construct(?T $data) {! $this->data = $data;! }! ! public function getData(): ?T {! return $this->data;! }! }! ! $box = new NullableBox(null);! ! ! function check_not_null(?int $x): int {! return $x === null ? -1 : $x;! }!
  • 22.
    Soft types • Apparentlynot documented • Emits warnings rather than fatal errors for invalid types ! ! class Calculator {! public function add(@int $a, @int $b): @string {}! }! ! $calc = new Calculator();! $calc->add("1", "2");
  • 23.
    Typed arrays • Untypedarrays are only allowed in partial or decl mode • In strict mode you must explicitly type the values: array<Foo>! • Or both keys and values: array<string, ?string>! • You can simulate PHP behaviour, but this defeats the purpose: array<mixed, mixed>
  • 24.
    Type aliasing • Redefinean existing type name type MyInteger = int;! • “Opaque” types disallow other files from accessing the underlying implementation (e.g. concatenation for strings) // File1.php! newtype MyString = string;! ! // File2.php! require_once "File1.php";! ! function modifyString(MyString $s): MyString {! return $s . "1"; // Hack type checker will throw an error! }
  • 25.
    Tuples and shapes •Tuples are basically immutable typed arrays public function baz(): (string, int) {! return tuple("Hello", 3);! }! • Shapes are kinda like structs type MyShape = shape('id1' => string, 'id2' => int);! function foo(MyShape $x): void {}
  • 26.
    Collections • Vector, Map,Set, Pair • Immutable versions: ImmVector, ImmMap, ImmSet • Can be initialised using literal syntax $vec = Vector {'foo', 'foo', 'bar'}; // integer keys! $map = Map {42 => 'foo', 73 => 'bar', 144 => 'baz'}; // ordered dictionary! $set = Set {'php', 'hack', 'hhvm'}; // unordered unique values! $par = Pair {'guid', 'ABC123'}; // only two pieces of data! • Type annotation function getTags(): Set<string> {! return Set { "php", "hack", "hhvm" };! }
  • 27.
    Collections • Some methodsignatures for Vector… public function __construct(?Traversable<Tv> $it)! public function add(Tv $value): Vector<Tv>! public function addAll(?Traversable<Tv> $it): Vector<Tv>! public function at(int $k): Tv! public function clear(void): Vector<Tv>! public function containsKey(int $k): bool! public function count(void): int! public function filter((function(Tv): bool) $callback): Vector<Tv>! public function filterWithKey((function(int, Tv): bool) $callback): Vector<Tv>! public function fromArray(array $arr): Vector<Tv>! public function fromItems(?Traversable<Tv> $items): Vector<Tv>! public function get(int $k): ?Tv! public function getIterator(void): KeyedIterator<int, Tv>! public function isEmpty(void): bool! public function items(void): Iterable<Tv>! public function keys(void): Vector<int>! public function reverse(void): void! public function set(int $k, Tv $v): Vector<Tv>! public function setAll(?KeyedTraversable<int, Tv> $it): Vector<Tv>! public function __toString(void): string! public function toValuesArray(void): array! public function zip<Tu>(Traversable<Tu> $iterable): Vector<Pair<Tv, Tu>>
  • 28.
    In other words,Hack really, really wants you to stop using simple arrays (or even ArrayObjects) as a “catch-all” data container
  • 29.
    Lambdas • Use thelambda arrow ==>
 (Because -> and => are already taken): function concat(): (function(string, string): string) {! return ($x, $y) ==> {! return $y . $x;! };! }! • Implicitly capture variables from outer scope
 Can be an expression: function foo(): (function(string): string) {! $x = 'bar';! return $y ==> $y . $x;! }
  • 30.
    Lambdas • Type hintsare not checked at the moment • Doesn't support capturing variables by reference or returning by reference yet • Lambda arrow operator is right associative and can be chained: ! $f = $x ==> $y ==> $x + $y;! $g = $f(7);! echo $g(4); // 11
  • 31.
    Variadic functions function sum(...):int {! $s = 0;! foreach (func_get_args() as $e) {! $s += $e;! }! return $s;! }! • Cannot be type annotated, unfortunately
  • 32.
    Override attribute • Signifythat the parent method must exist class Hello {! public function render(): void {! echo 'hello';! }! }! ! class HelloWorld extends Hello! {! <<Override>> public function render(): void {! parent::render();! echo ' world';! }! }
  • 33.
    Constructor arg promotion classPerson {! private string $name;! private int $age;! ! public function __construct(string $name, int $age) {! $this->name = $name;! $this->age = $age;! }! }! • can be written as ! class Person {! public function __construct(private string $name, private int $age) {}! }
  • 34.
    Callbacks • This willnot work in strict mode: $func = 'myFunc';! $x = $func(4);! • fun() will return a callable, which allows the typechecker to properly validate: $func = fun('myFunc');! $x = $func(4);! • Similar dubiously-named functions exist for calling static/instance methods: // $bar = array_map(array('Foo', ‘doStuff'), [1, 2, 3]);! $bar = array_map(class_meth('Foo', 'doStuff'), [1, 2, 3]);! ! $foo = new Foo();! $bar = array_map(instance_meth($foo, 'doStuff'), [1, 2, 3]);! ! $func = meth_caller('Foo', 'doStuff');! $foo = new Foo();! $x = $func($foo);
  • 35.
    Async and await asyncfunction gen_foo(int $a): Awaitable<?Foo> {! if ($a === 0) {! return null;! }! $bar = await gen_bar($a);! if ($bar !== null) {! return $bar->getFoo();! }! return null;! }! ! async function gen_bar(int $a): Awaitable<?Bar> {! if ($a === 0) {! return null;! }! return new Bar();! }! ! gen_foo(4);
  • 36.
    Running the typechecker • Run hh_client (it will launch hh_server for you) or hh_server --check . • Recursively looks for directories that contain a .hhconfig file (it won’t run if this is missing) • Optionally return output in json format • Note: does not follow symlinks
  • 37.
    Unsupported features • Stillruns in HHVM, but the type checker does not like the following: • goto, if: … endif; etc • AND, OR, XOR • References (&) • Error suppression (@) • break N, continue N • eval() • globals
  • 38.
    Unsupported features • list(,$b) = array(3, 4); should be list($_, $b) = array(3, 4); • Function calls are case-sensitive • Strict mode does not support top-level code except for require() and require_once(); i.e. everything else must be in a class or function • Does not support "variable variables" (e.g. $$a) or extract() • Cannot call parent::staticMethod() • Cannot declare a class method with a name that collides with class name • Cannot pass primitives by reference
  • 39.
    Drawbacks • Still new,not yet 100% compatibility (but catching up fast) • Your favourite extension may not be available • Limited IDE support at the moment (weekend project idea?) • Hack-exclusive libraries? Package repos? Community fragmentation? • Clashes with PHP 5.5 and future 5.6 syntax
 (generators and variadic functions)
  • 40.
    • Generator functionsare of the type “Continuation” in HHVM (since they were implemented earlier) • The following is valid in PHP 5.5 but not in HHVM: $data = (yield $value); // delete the brackets for HHVM! $data = yield; // HHVM needs expression after yield! • HHVM Continuations need to be “primed” unlike PHP 5.5 Generators $generator = construct_generator();! $generator->current(); // must call next() first in HHVM!
  • 41.
    • Proposed PHP5.6 syntax for variadic functions: function fn($arg, ...$args) {}! function fn($arg, &...$args) {}! function fn($arg, callable ...$args) {}! • Type-hinting and arguments by value not supported in HHVM / Hack function fn(...): void {}
  • 42.
    Benefits • Type safety!!!(Always use the type checker) • Syntactic sugar from other languages • Discard “bad” parts of PHP • Active community (e.g. New Relic has released a prototype HHVM extension, Heroku just announced HHVM support)
  • 43.
    Resources • http://hhvm.com/ • http://hacklang.org/ •http://docs.hhvm.com/manual/en/hacklangref.php • https://blog.engineyard.com/2014/hhvm-hack • http://blog.vjeux.com/2014/javascript/hack-is-to-php-what-es6-is-to- javascript.html • https://github.com/facebook/hhvm
  • 44.
    Thank you Contact: • ChrisHeng <bigblah@gmail.com> • https://github.com/gigablah