0%

Lisp Flavored Erlang (LFE) のインストール

ElixirのおかげでErlangに注目が集まっています。今までErlangを使ってみたくても、特殊に見える文法に戸惑っていたプログラマに、Ruby風なシンタックスのおかげで敷居が低くなったと思います。一方のLisp Flavored Erlang (LFE)は名前の通りLisp風に書けるErlangです。誰がうれしいのか一瞬よくわかりませんが、Lispには何か避けられない魅力があります。かつてもっと文明的だった時代のエレガントな武器です

ScalaやClojureとったJVM上で動作する新しい言語も関数型言語の特徴を持つことが多く、不変性や並行性、分散処理を重要視しています。時代とともに純粋なプログラミング言語としてJavaやErlangの魅力は薄れつつありますが、クリティカルなエンタープライズの分野で長年の信頼と実績を持つJVMやErlang VMの性能を享受できるのは魅力的です。

インストール

GitHubのリポジトリにあるUbutntu版のDockerfileを見てもソースからErlangをインストールするのはとても面倒です。セットアップが面倒な環境ではDockerが便利です。

Debian版

Dockerイメージのlfex/lfeはDebianがベースになっています。lfeコマンドを実行するとREPLが起動します。Erlang/OTP 17、LFE V6.2とちょっとバージョンが古いようです。

$ docker pull lfex/ubuntu
$ docker run -i -t lfex/ubuntu lfe
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [async-threads:10] [kernel-poll:false]

LFE Shell V6.2 (abort with ^G)

Ubuntu版

DockerイメージはDebianの他にもリポジトリにはいろいろなOSで作成されたものがあります。Raspbianのあります。UbuntuはErlang/OTP 18、LFE v0.9.1と新しいバージョンなのでこちらで開発環境を作ろうと思います。

$ docker pull lfex/ubuntu
$ docker run -i -t lfex/ubuntu lfe
Erlang/OTP 18 [erts-7.0] [source-4d83b58] [64-bit] [async-threads:10] [hipe] [kernel-poll:false]

(
( ) )
)_.(._(
.-( \\ )-. | A Lisp-2+ on the Erlang VM
( / \\ ) | Docs: http://docs.lfe.io/
|`-.._____..-';. |
| g (_ \ | Type (help) for usage info.
| n || | |
| a '/ ; | Source code:
( l / / | http://github.com/rvirding/lfe
\ r ( / |
\ E ,y' | LFE v0.9.1
`-.___.-' | LFE Shell V7.0 (abort with G^)

開発環境

適当なディレクトリを作成します。リポジトリはこちらです。

$ cd ~/lfe_apps
$ tree
.
├── Dockerfile
├── README.md
├── docker-compose.yml
└── sample-module.lfe

Dockerfileはlfex/ubuntuをベースイメージにします。WORKDIRを作成するだけです。

~/lfe_apps/Dockerfile
FROM lfex/ubuntu
MAINTAINER Masato Shimizu <ma6ato@gmail.com>

WORKDIR /app
COPY . /app

docker-compose.ymlではローカルにビルドしたイメージを使い、lfelfescriptコマンドを使うサービスを定義します。

~/lfe_apps/docker-compose.yml
lfe: &defaults
image: masato/lfe
volumes:
- .:/app
entrypoint: lfe
lfescript:
<<: *defaults
entrypoint: lfescript

ローカルにDockerイメージをビルドしておきます。

$ docker build -t masato/lfe .

簡単な使い方

REPL

さきほど実行したようにlfeコマンドを実行するとREPLが起動します。2 The LFE REPLからいくつか写経してみます。

$ docker-compose run --rm lfes
>

Hello Worldと簡単なかけ算です。

> (io:format "Hello, World!~n")
Hello, World!
ok
> (* 2 21)
42

my-list変数に連番をバインドします。listsはErlangの組み込み関数のモジュールです。seq関数で連番を作成します。

> (set my-list (lists:seq 1 6))
(1 2 3 4 5 6)

同じくlistsモジュールのsum関数で変数にバインドした連番の合計した結果の21に、2を乗算します。

> (* 2 (lists:sum my-list))
42

もっと関数型言語っぽくlists:foldl関数を使い、my-list変数に累計する無名関数を適用して畳み込み(reduce)した結果の21に、2を乗算します。

> (* 2 (lists:foldl (lambda (n acc) (+ n acc)) 0 my-list))
42

Ctrl-Cを2回押すとREPLが終了します。

lfescript

lfescriptはスクリプトとして書いてコンパイルせずに実行することができます。リポジトリにあるsample-lfescriptのサンプルを実行してみます。関数型言語のサンプルによくあるfactorial(階乗)の計算です。スクリプトの実行にはスクリプトの先頭にshebangでlfescriptが必要です。

sample-module.lfe
#! /usr/bin/env lfescript

(defun main
([(list string)]
(try
(let* ((n (list_to_integer string))
(f (fac n)))
(: lfe_io format '"factorial ~w = ~w\n" (list n f)))
(catch
((tuple _ _ _) (usage)))))
([_] (usage)))

(defun fac
([0] 1)
([n] (* n (fac (- n 1)))))

(defun usage ()
(let ((script-name (: escript script_name)))
(: lfe_io format '"usage: ~s <integer>\n" (list script-name))))
}}}

6の階乗を計算してみます。lfescriptに続いて実行するスクリプトファイル、引数を入力します。

$ docker-compose run --rm lfescript sample-module.lfe 6
factorial 6 = 720