--- language: Hack contributors: - ["Stephen Holdaway", "https://github.com/stecman"] filename: learnhack.hh --- Hack is a superset of PHP that runs under a virtual machine called HHVM. Hack is almost completely interoperable with existing PHP code and adds a bunch of useful features from statically typed languages. Only Hack-specific features are covered here. Details about PHP's syntax are available in the [PHP article](http://learnxinyminutes.com/docs/php/) on this site. ```php id = $id; } } // Concise anonymous functions (lambdas) $multiplier = 5; array_map($y ==> $y * $multiplier, [1, 2, 3]); // Generics class Box { protected T $data; public function __construct(T $data) { $this->data = $data; } public function getData(): T { return $this->data; } } function openBox(Box $box) : int { return $box->getData(); } // Shapes // // Hack adds the concept of shapes for defining struct-like arrays with a // guaranteed, type-checked set of keys type Point2D = shape('x' => int, 'y' => int); function distance(Point2D $a, Point2D $b) : float { return sqrt(pow($b['x'] - $a['x'], 2) + pow($b['y'] - $a['y'], 2)); } distance( shape('x' => -1, 'y' => 5), shape('x' => 2, 'y' => 50) ); // Type aliasing // // Hack adds a bunch of type aliasing features for making complex types readable newtype VectorArray = array>; // A tuple containing two integers newtype Point = (int, int); function addPoints(Point $p1, Point $p2) : Point { return tuple($p1[0] + $p2[0], $p1[1] + $p2[1]); } addPoints( tuple(1, 2), tuple(5, 6) ); // First-class enums enum RoadType : int { Road = 0; Street = 1; Avenue = 2; Boulevard = 3; } function getRoadType() : RoadType { return RoadType::Avenue; } // Constructor argument promotion // // To avoid boilerplate property and constructor definitions that only set // properties, Hack adds a concise syntax for defining properties and a // constructor at the same time. class ArgumentPromotion { public function __construct(public string $name, protected int $age, private bool $isAwesome) {} } class WithoutArugmentPromotion { public string $name; protected int $age; private bool $isAwesome; public function __construct(string $name, int $age, bool $isAwesome) { $this->name = $name; $this->age = $age; $this->isAwesome = $isAwesome; } } // Co-oprerative multi-tasking // // Two new keywords "async" and "await" can be used to perform mutli-tasking // Note that this does not involve threads - it just allows transfer of control async function cooperativePrint(int $start, int $end) : Awaitable { for ($i = $start; $i <= $end; $i++) { echo "$i "; // Give other tasks a chance to do something await RescheduleWaitHandle::create(RescheduleWaitHandle::QUEUE_DEFAULT, 0); } } // This prints "1 4 7 2 5 8 3 6 9" AwaitAllWaitHandle::fromArray([ cooperativePrint(1, 3), cooperativePrint(4, 6), cooperativePrint(7, 9) ])->getWaitHandle()->join(); // Attributes // // Attributes are a form of metadata for functions. Hack provides some // special built-in attributes that introduce useful behaviour. // The __Memoize special attribute causes the result of a function to be cached <<__Memoize>> function doExpensiveTask() : ?string { return file_get_contents('http://example.com'); } // The function's body is only executed once here: doExpensiveTask(); doExpensiveTask(); // The __ConsistentConstruct special attribute signals the Hack type checker to // ensure that the signature of __construct is the same for all subclasses. <<__ConsistentConstruct>> class ConsistentFoo { public function __construct(int $x, float $y) { // ... } public function someMethod() { // ... } } class ConsistentBar extends ConsistentFoo { public function __construct(int $x, float $y) { // Hack's type checker enforces that parent constructors are called parent::__construct($x, $y); // ... } // The __Override annotation is an optional signal for the Hack type // checker to enforce that this method is overriding a method in a parent // or trait. If not, this will error. <<__Override>> public function someMethod() { // ... } } class InvalidFooSubclass extends ConsistentFoo { // Not matching the parent constructor will cause a type checker error: // // "This object is of type ConsistentBaz. It is incompatible with this object // of type ConsistentFoo because some of their methods are incompatible" // public function __construct(float $x) { // ... } // Using the __Override annotation on a non-overriden method will cause a // type checker error: // // "InvalidFooSubclass::otherMethod() is marked as override; no non-private // parent definition found or overridden parent is defined in non-> public function otherMethod() { // ... } } // Traits can implement interfaces (standard PHP does not support this) interface KittenInterface { public function play() : void; } trait CatTrait implements KittenInterface { public function play() : void { // ... } } class Samuel { use CatTrait; } $cat = new Samuel(); $cat instanceof KittenInterface === true; // True ``` ## More Information Visit the [Hack language reference](http://docs.hhvm.com/manual/en/hacklangref.php) for detailed explainations of the features Hack adds to PHP, or the [official Hack website](http://hacklang.org/) for more general information. Visit the [official HHVM website](http://hhvm.com/) for HHVM installation instructions. Visit [Hack's unsupported PHP features article](http://docs.hhvm.com/manual/en/hack.unsupported.php) for details on the backwards incompatibility between Hack and PHP.