いまさらHackに入門(Dockerfile付き)

HackがあればPHPでも型がつけられる!とか色々言っている割にインストールすらしてないありさまな状態から脱出すべく入門しました(´・_・`)

ちなみにHackというのはジェネリクスや返り値の型指定など、PHPのタイプヒンティングを強化したような機能をもっているFacebookが作った言語です。

詳しくは以下を参照すると良いと思います( ⁰⊖⁰)

Dockerで構築

いつものようにVagrantでやろうかなーと思ったのですが、 そろそろカジュアルにDockerを使えるようにならねばという気持ちもあったのでDockerで環境構築しました。(ちなみにhhvmはmacに対応していません。南無三)

ちょうど同じようなことを公開してくださっている方がいたので、 Docker で Hack - Qiitaの記事をベースに始めました。 が、月日が流れたせいかちょっとできなかったのでPrebuilt packages on Ubuntu 14.04 · facebook/hhvm Wiki · GitHubを参考に書きました。₍₍ (ง ˘ω˘ )ว ⁾⁾

もろもろは、https://github.com/matsu-chara/docker-hhvmに上げてあります。

ちなみに

docker -v
Docker version 1.5.0, build a8a31ef

です。

FROM ubuntu

RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get install -y software-properties-common
RUN apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x5a16e7281be7a449
RUN add-apt-repository 'deb http://dl.hhvm.com/ubuntu trusty main'
RUN apt-get update
RUN apt-get install -y hhvm

具体的な手順は、 さきほどのDockerfileがあるディレクトリにsrcというコンテナと共有するためのディレクトリを作成しておいた状態で、

docker build -t chara/hhvm .
docker run -i -t -d -v pwd/src:/home --name hhvm chara/hhvm /bin/bash
docker attach hhvm

とすれば出来ます。attach後は何も表示されないのですが、エンターとか押せばプロンプトが表示されると思います。

これで

hhvm -v
HipHop VM 3.7.1 (rel)
Compiler: tags/HHVM-3.7.1-0-g111c76378ac29aa8f25e6bb3c5f15b628e6bbea1
Repo schema: be14a89778f35ca7f7dd4aca7fff0793e8ae3334

のようにできます。やったー₍₍ (ง ˘ω˘ )ว ⁾⁾

Hack

さて、type checkerを作動させるために.hhconfigという空ファイルがプロジェクトルートに存在する必要がありますので

cd /home
touch .hhconfig

しましょう。 これで準備完了です。

<?hh

function f(): int {
  return 'not an int';
}

echo f() . "\n";

のようなintを返すと言っているのにstringを返している関数を持ったhello.hhを書いて実行します。

> hhvm hello.hh
Fatal error: exception End_of_file

型エラーです!カタアンゼン!ヤッタ―!*1

ということで

<?hh

function h(): string {
  return 'not an int';
}

echo h() . "\n";

に変更したhello2.hhを用意してhhvm hello2.hhとすると実行できるようになりました。

ちなみに、hello.hhでも、fの呼び出しを行わなければ実行することが出来ます。関数の引数を受け取ったときと返り値を返すときに型チェックを実行時に見る仕組みのようです。

実行時の挙動に基づく検査ではなく実行前に型付けに矛盾がないかチェックしたい!という場合は、 hh_clientを実行すると裏でhh_serverを起動して、.hhconfig以下に対して型チェックを行ってくれます。

hh_client
/home/hello2.hh:3:10,10: Name already bound: f (Naming[2012])
  /home/hello.hh:3:10,10: Previous definition is here

おっと、たしかに同じプロジェクトに同名の関数がありますね。 適当にhello2をg()とかに修正します。

hh_client
/home/hello.hh:4:10,21: Invalid return type (Typing[4110])
  /home/hello.hh:3:15,17: This is an int
  /home/hello.hh:4:10,21: It is incompatible with a string

おお!できました。この状態でも

hhvm hello.hh

は実行可能です。基本はhh_clientでチェックをするけど、だるいときはhhvmで実行しながらもデバッグできそうです。

実はなんか上手く行かなくて、

> hh_client
logname: no login name
Fatal error: exception End_of_file

とか言われてしまっていたのですが、suしたら治りました。たぶんuserを普通に作れば問題ないんだと思いますが開発用だしこれでいいかな・・・(´・_・`)

開始したサーバープロセスは

> hh_client stop

で停止します。

とりあえず入門なのでこの辺で終わります( ⁰⊖⁰)

参考文献

*1:実行時のチェックだけど・・・