Back-End

5 mai, 2014

Hack Lang: a evolução do PHP?

Publicidade

Hack é uma linguagem para HHVM que interage perfeitamente com o PHP. O propósito é permitir o desenvolvimento ágil com a disciplina da tipagem estática.

Hack também fornece alguns recursos específicos:

  • generics
  • collections
  • nullable

Daqui a pouco vou falar mais sobre esses recursos!

<?hh
echo "Hi, I'm a Hack script!";

Type Annotations

Tradicionalmente, uma linguagen com tipagem dinâmica permite o desenvolvimento ágil, mas sacrifica a capacidade de detectar erros rapidamente. O Hack reconcilia o ciclo de desenvolvimento rápido do PHP com a disciplina fornecida pelo tipagem estática.

<?hh
function hello(): void {
    echo "Type Annotations :)";
}

Hack também especifica o tipo de retorno no final da declaração de uma função/método, não no início, como acontece no C#.

<?hh
function add_numbers(int $number1): int {
    return $number1;
}

Outro detalhe importante: o PHP permite o uso de sinônimos para manipulação de tipos, mas o Hack eliminou isso. Na prática isso significa que:

  • double, real não sâo permitidos para float.
  • boolean não é permitido para bool.
  • integer também não é permitido para int.

Generics

Um método genérico tem a mesma funcionalidade dos tipos genéricos: suportar tipos fortes, definidos e genéricos (d’oh).

Assim como nos tipos genéricos, os métodos genéricos existem para permitir a passagem de valores genéricos para um determinado método.

<?hh
class Box<T> {

  protected T $data;

  public function __construct(T $data) {
      $this->data = $data;
  }

  public function getData(): T {
      return $this->data;
  }
}

A classe Box tem um parâmetro de tipo genérico. Para qualquer instância de Box, T assume qualquer tipo disponível, e ainda podemos utilizar o mesmo tipo para o parâmetro de um método da mesma classe, no nosso caso, o método getData().

<?hh
$main = new Box(9);
echo $main->getData(); //Output '9'

Collections

Collections é uma das coisas mais úteis na maioria das linguagens, mas por alguma razão o PHP ainda não tem essa funcionalidade como algo padrão. Elas são grupos de objetos similarmente iguais que são agrupados. Elas são especializadas para armazenamento e recuperação de dados. Atualmente, Hack implementa os seguintes tipos de Collections:

  • Vector: ordenada, baseada no índice;
  • Map: dictionary-style ordenada;
  • Set: armazena valores exclusivos;
  • Pair: baseada em índice que pode conter exatamente dois elementos.

Exemplo usando Vector:

<?hh
$vector = Vector {5, 10};

$vector->add(15);
$vector->add(20);

$vector[] = 25;

$vector->removeKey(2);

foreach ($vector as $item) {
    echo $item . "\n";
}

O exemplo acima retorna:

5
10
20
25

Agora um exemplo usando Map:

 <?hh
$map = Map {"A" => 1, "B" => 2, "C" => 3};

$map["D"] = 4;
$map["E"] = 5;

foreach ($map as $k => $v) {
    echo $k . ": " . $v . "\n";
}

O exemplo acima retorna:

A: 1
B: 2
C: 3
D: 4
E: 5

Outro exemplo, usando Pair:

<?hh
$p = Pair {9, 'l'};
echo $p[0] . "\n";
echo $p[1] . "\n";

O exemplo acima retorna:

9
l

Nullable

Nullable introduz uma maneira mais segura de lidar com valores nulos. Isso nada mais é do que permitir qualquer tipo aceitar nulo, além dos valores normais para este tipo. É muito útil para os tipos primitivos que geralmente não permitem nulo como um de seus valores, como bool e int.

<?hh
function check_not_null(?int $x): int {
  if ($x === null) {
      return -1;
  } else {
      return $x;
  }
}

Chega de blá, blá, blá! O HipHop Virtual Machine, a.k.a HHVM, substitui servidores web como Apache e IIS com um serviço específico para PHP, buscando a performance perdida pela linguagem, mas, sem perder a praticidade.

Instalando o HHVM no Debian 7

$ wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | sudo apt-key add -
$ echo deb http://dl.hhvm.com/debian wheezy main | sudo tee /etc/apt/sources.list.d/hhvm.list
$ sudo apt-get update
$ sudo apt-get install hhvm

Conferindo a versão do HHVM:

$ hhvm --version
HipHop VM 2.4.2 (rel)
Compiler: tags/HHVM-2.4.2-0-g432ecffa04b21c60953bb236a9db8278f4650537
Repo schema: 1be260b29a71097b5d1f78c6e4dcbb981ba03bde

Vamos dar uma olhada no server.hdf?

$ sudo nano /etc/hhvm/server.hdf
PidFile = /var/run/hhvm/pid

  Server {
    Port = 80
    SourceRoot = /var/www/
    DefaultDocument = index.php
  }

  Log {
    Level = Warning
    AlwaysLogUnhandledExceptions = true
    RuntimeErrorReportingLevel = 8191
    UseLogFile = true
    UseSyslog = false
    File = /var/log/hhvm/error.log
    Access {
      * {
        File = /var/log/hhvm/access.log
        Format = %h %l %u % t \"%r\" %>s %b
      }
    }
  }

  Repo {
    Central {
      Path = /var/log/hhvm/.hhvm.hhbc
    }
  }

  #include "/usr/share/hhvm/hdf/static.mime-types.hdf"
  StaticFile {
    FilesMatch {
      * {
        pattern = .*\.(dll|exe)
        headers { 
          * = Content-Disposition: attachment 
        }
      }
    }
    Extensions : StaticMimeTypes
  }

  MySQL {
    TypedResults = false
  }

Não vou mudar nada por enquanto.

$ sudo touch /var/www/info.php
$ sudo nano /var/www/info.php

Vamos dar uma olhada no phpinfo()? Insira <?hh phpinfo(); no seu info.php. Rodando:

$ sudo /etc/init.d/hhvm start
$ hhvm /var/www/info.php 
HipHop

Você pode conferir no browser também

Bacana, né? Vamos ver um outro exemplo usando Vector:

<?hh
class MyClass {

  private Vector<int> $vector = Vector{};

  public function increment():Vector<int> {
    for($x=0;$x<10;$x++) {
        $vector[] = $x;
    }

    return $vector;
  }
}

$init = new MyClass();
var_dump($init->increment());

Temos o seguinte retorno:

array(10) {
  [0] => int(0)
  [1] => int(1)
  [2] => int(2)
  [3] => int(3)
  [4] => int(4)
  [5] => int(5)
  [6] => int(6)
  [7] => int(7)
  [8] => int(8)
  [9] => int(9)
}

Bacana demais! Em outros artigos vou aprofundar mais no Hack, vamos falar de Hack Modes, Array, Shapes, Async, HHVM com Vagrant. Ufa, diversão garantida!