diff options
| -rw-r--r-- | hack.html.markdown | 307 | 
1 files changed, 307 insertions, 0 deletions
| diff --git a/hack.html.markdown b/hack.html.markdown new file mode 100644 index 00000000..dd163362 --- /dev/null +++ b/hack.html.markdown @@ -0,0 +1,307 @@ +--- +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](php.html.markdown). + +```php +<?hh + +// Hack syntax is only enabled for files starting with an <?hh marker +// <?hh markers cannot be interspersed with HTML the way <?php can be. +// Using the marker "<?hh //strict" puts the type checker in strict mode. + + +// Scalar parameter type hints +function repeat(string $word, int $count) +{ +    $word = trim($word); +    return str_repeat($word . ' ', $count); +} + +// Type hints for return values +function add(...$numbers) : int +{ +    return array_sum($numbers); +} + +// Functions that return nothing are hinted as "void" +function truncate(resource $handle) : void +{ +    // ... +} + +// Type hints must explicitly allow being nullable +function identity(?string $stringOrNull) : ?string +{ +    return $stringOrNull; +} + +// Type hints can be specified on class properties +class TypeHintedProperties +{ +    public ?string $name; +     +    protected int $id; + +    private float $score = 100.0; + +    // Hack's type checker enforces that typed properties either have a +    // default value or are set in the constructor. +    public function __construct(int $id) +    { +        $this->id = $id; +    } +} + + +// Concise anonymous functions (lambdas) +$multiplier = 5; +array_map($y ==> $y * $multiplier, [1, 2, 3]); + + +// Generics +class Box<T> +{ +    protected T $data; + +    public function __construct(T $data) { +        $this->data = $data; +    } + +    public function getData(): T { +        return $this->data; +    } +} + +function openBox(Box<int> $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<int, Vector<int>>; + +// 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<void> +{ +    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-<?hh code" +    // +    <<__Override>> +    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.
\ No newline at end of file | 
