hack

About ME

  • Señor Developer @ Orba
  • self-proclaimed code magician
  • mentor & consultant
  • devThursday keeper

 

Some History

HipHop for PHP

  • Created by Facebook labs in early 2010
  • PHP to C++ compiler
  • 6x faster by PHP 5.3
  • Initial release in 2011
  • At production in Q1 2013
  • PHP/JIT compiler like Java/JVM
  • 3x faster than PHP 5.6
  • 1.1x faster than PHP 7.0 (slower than 7.2)
  • Open-source
  • In 2019 will abadon PHP
  • Easy extension create
  • PHP on steroids
  • Main Facebook backend language

HACK

HACK

PHP

<?hh
class MyClass {
  public function alpha(): int {
    return 1;
  }

  public function beta(): string {
    return 'hi test';
  }
}

function f(MyClass $my_inst): int {
  return $my_inst->alpha();
}

$object = new MyClass();
f($object);
<?php
class MyClass {
  public function alpha(): int {
    return 1;
  }

  public function beta(): string {
    return 'hi test';
  }
}

function f(MyClass $my_inst): int {
  return $my_inst->alpha();
}

$object = new MyClass();
f($object);

vs

HACK

PHP

vs

Example

<?hh

async function do_cpu_work(): Awaitable<void> {
  echo("Start CPU work\n");
  for ($i = 0; $i < 1000; ++$i) {
    echo "tick \n";
  }
  echo("End CPU work\n");
}

async function do_sleep(): Awaitable<void> {
  print("Start sleep\n");
  \sleep(1);
  print("End sleep\n");
}

async function main(): Awaitable<void> {
  print("Start of main()\n");
  await \HH\Asio\v([
    do_cpu_work(),
    do_sleep(),
  ]);
  print("End of main()\n");
}

\HH\Asio\join(main());

HACK

Features

Collections

HACK

PHP

Vector\ ImmVector

<?hh

$a = Vector {'a', 'b', 'c'};

function test(Vector $a) {
    $a[] = 'd';
}
test($a);

var_dump($a);
// object(HH\Vector)#1 (4) {
//  [0]=> string(1) "a"
//  [1]=> string(1) "b"
//  [2]=> string(1) "c"
//  [3]=> string(1) "d"
//}

$a['asda'] = 3;
//Fatal error: 
// Uncaught exception'InvalidArgumentException' 
// with message 
// 'Only integer keys may be used with Vectors'
<?php

$a = ['a', 'b', 'c'];
function test(array $a) {
    $a[] = 'd';
}
test($a);

var_dump($a);
// array(4) {
//  [0]=> string(1) "a"
//  [1]=> string(1) "b"
//  [2]=> string(1) "c"
//}

$a['asda'] = 3;

HACK

PHP

Map \ ImmMap

<?hh

$a = Map {"a" => 888, "b" => 23, "f" => 0,};

function test(Map $a) {
    $a[] = 'd';
}
test($a);

var_dump($a);
// object(HH\Map)#1 (4) {
//  ["a"]=> int(888)
//  ["b"]=> int(23)
//  ["f"]=> int(0)
//  ["c"]=> string(1) "d"
//}

$a[] = 'asda';

//Fatal error:
// Uncaught exception
// 'InvalidArgumentException' with message 
// 'Parameter must be an instance of Pair'
<?php

$a = ['a', 'b', 'c'];
function test(array $a) {
    $a[] = 'd';
}
test($a);

var_dump($a);
// array(3) {
//  ["a"]=> int(888)
//  ["b"]=> int(23)
//  ["f"]=> int(0)
//}

$a['asda'] = 3;

HACK

PHP

Set \ ImmSet

<?hh

$a = Set {"A", "B", "C"};

$a[] = "D";
$a[] = "A";

var_dump($a);

/*
object(HH\Set)#1 (4) {
  string(1) "A"
  string(1) "B"
  string(1) "C"
  string(1) "D"
}
<?php

$a = ["A", "B", "C"];

$a[] = "D";
$a[] = "A";

var_dump($a);

/*
array(5) {
  [0]=>
  string(1) "A"
  [1]=>
  string(1) "B"
  [2]=>
  string(1) "C"
  [3]=>
  string(1) "D"
  [4]=>
  string(1) "A"
}

Pair

<?hh

$a = Pair {"bar", 898339};

var_dump($a);

/*
object(HH\Pair)#1 (2) {
  [0]=> string(3) "bar"
  [1]=> int(898339
}

Shape

<?hh

type Point = shape('x' => int, 'y' => int);

function distance(Point $p1, Point $p2): float
{
  $dx = $p1['x'] - $p2['x'];
  $dy = $p1['y'] - $p2['y'];
  return \sqrt($dx*$dx + $dy*$dy);
}

$p1 = shape('x' => 4, 'y' => 6);
$p2 = array('x' => 9, 'y' => 2);
echo distance($p1, $p2); //6.4031242374328

/////
type Point = shape('x' => int, 'y' => int, ?'z' => int);
type Point = shape('x' => int, 'y' => int, 'z' => ?int);

is_array($p1); // true
$key = 'x';
$p1[$x] // Error
$p1[] = 'z' //Error
foreach($p1 as $key => $value) echo $key.' '.$value; //Error

Generic Types

class Box<T> {
  public T $value;
  public function __construct(T $v) {
    $this->value = $v;
  }
}

function swap<T>(Box<T> $a, Box<T> $b) : void {
  $temp = $a->value;
  $a->value = $b->value;
  $b->value = $temp;
}


final class Map<Tk, Tv> implements MutableMap<Tk, Tv> {
  …
  public function zip<Tu>(Traversable<Tu> $iter): Map<Tk, Pair<Tv, Tu>> { … }
}

Lambda Expression

HACK

PHP

Syntax

<?hh

$people = Vector {
      "Carlton",
      "Will",
      "Phil"
};
$people->map($name ==> $name . " Banks");

object(HH\Vector)#4 (3) {
  [0]=>
  string(13) "Carlton Banks"
  [1]=>
  string(10) "Will Banks"
  [2]=>
  string(10) "Phil Banks"
}

(string $a, string $b): string
===> { return $a.' '.$b;}
<?php

$people = array(
    "Carlton",
    "Will",
    "Phil"
);
$mapped = array_map(function ($name) {
    return $name . " Banks";
}, $people);

array(3) {
  [0]=>
  string(13) "Carlton Banks"
  [1]=>
  string(10) "Will Banks"
  [2]=>
  string(10) "Phil Banks"
}

function (string $a, string $b): string { 
    return $a.' '.$b;
}

Attributes (Annotations)

HACK

PHP

Syntax

<?hh

<<Foo('Foo')>>
class A {
    <<Bar('Bar')>>
    private $name;

    <<FooBar('FooBar')>>
    public function test() {}
}

$rc = new \ReflectionClass(A::Class);
$rc->getAttributes()['Foo']// Foo
<?php

/**
 * @Foo('Foo')
 */
class A {
    /**
     * @Bar('Bar')
     */
    private $name;

    /**
     * @FooBar('FooBar')
     */
    public function test() {}
}
$rc = new \ReflectionClass(A::Class);
$rc->getDocComment(); // @Foo('Foo')

Special Attributes

<?hh

class A {
  <<__ConsistentConstruct>>
  public function __construct() { $this->foo() }

  private function foo(): void { echo "A";}
}

class B extends A {
  <<__Override>>
  private function foo(): void { echo "B";}
}

$b = new B() // B

final class C extends A {
  <<__UNSAFE_Construct>>
  public function __construct() {echo 'C';}

  <<__Memoize>>
  private function foo(): void {sleep(1000); echo 'test';}
}

<<__MockClass>>
class mockC extends C {};

Operators

  • ==> Lambda operator
  • ?-> null-safe operator
    • $obj?->foo();
    • // isset($obj)? null : $obj->foo();
  •  |> pipe operator (fluid operator)
    • $obj

                    |>func1() (return bool)

                    |>func2(); (return string)

Why not Hack ?

  • PHP is good enough (7.2 is faster than hack)
  • Incompatibility with PHP codebase
  • Lack IDE support (only Facebook's nuclide)
  • Too young language to be popular
  • Facebook doesn't promoting the language

Q&A

HackLang

By Paweł Radzikowski

HackLang

  • 467