Gleamことはじめ
概要
Gleamは、BEAM(Erlang VMとも言う)と呼ばれる仮想マシン上で動作するプログラミング言語です。
BEAM(ビーム)の韻を踏んで、読み方は「グリーム」です。
Gleamは、Rustで書かれています。
特徴として、型安全でスケーラブルなシステムを構築する用途を目指してます。
また、他のBEAM上で動作するプログラミング言語(たとえば、Erlang、Elixir、LFE(Lisp Flavored Erlang))との親和性を有しています。
Gleamは、BEAM上で動作するのでErlangのバイナリ(beamファイル)をコンパイルします。
加えて、JavaScriptのコードも出力できます。
最新バージョンについて
Gleamは、2022年5月22日時点での最新バージョンは、「v0.21.0」です。
まだ、正式バージョンがリリースされていません。
正式バージョンのリリースを気長に待ちましょう。
https://github.com/gleam-lang/gleam/releases/tag/v0.21.0
追記!
2024年3月4日、待望の「v1.0.0」がリリースされました。
https://github.com/gleam-lang/gleam/releases/tag/v1.0.0
https://gleam.run/news/gleam-version-1/
PlayGroundでGleamを体験してみる
まずは、Gleamを体験してみます。
Gleam用のPlayGroundがあるので、こちらにアクセスします。
https://johndoneth.github.io/gleam-playground/
画面左部のエディタ部分には、初期値として以下のコードが書かれています。
import gleam/io
pub fn main() {
io.print("hi")
42
}
画面上部の「Build&Run」をクリックしてみましょう。
画面右上部に実行結果が、画面右下部にコンパイル結果が出力されます。
なお、現時点では「JavaScript」にチェックが付いているので、JavaScriptのコードがコンパイルされています。
では、「Erlang」を選択した場合はどうなるでしょうか。
「Erlang」を選択した場合、「Build&Run」は「Build」に変わります。
実行結果はブラウザ上で確認できません。
以下のようなメッセージが「Result」欄に出力されています。
Note that the Erlang target is not executable in the browser.
ただし、画面右下部にはコンパイル結果は出力されます。
コードを修正してみる
PlayGroundでコードの動作確認ができたので、少し手を加えてみます。
なお、PlayGround上で動作確認もできるように、以降は「JavaScript」を選択して実行します。
コメントアウトする
コメントアウトには//
を使います。
既存のコードio.print("hi")
の先頭に//
をつけると、コメントアウトされます。
import gleam/io
pub fn main() {
//io.print("hi")
42
}
「Build&Run」をクリックすると、「Result」欄と「Compiled JavaScript」欄から、io.print("hi")
に関する内容が消えています。
変数へのバインディング
let 変数名 = 値
で、変数に値をバインディングできます。
以下、let all_answer = 42
でlet all_answer
に「42」をバインディングします。
import gleam/io
pub fn main() {
// io.print("hi")
let all_answer = 42
all_answer
}
同じ変数名に再度バインディングするには、let
が必要です。
また、Gleamでの値はすべてImmutableとなります。
そのため、別の変数へバイディング後に元の変数を再度バインディングして値を変更したとしても、値が変わるのは元の変数のみです。
以下の例では、all_answer
へ42をバインディング後に、new_answer
へall_answer
の値をバインディングしました。
その後、今度はall_answer
へ43をバインディングしました。
プログラミング言語によっては、「代入」はオブジェクトへの参照だったり、アドレスの共有だったりします。この場合、元の値(all_answer
)の値が変わると代入された側new_answer
の値がall_answer
の値と同じ(同じ場所を参照するため)になります。
しかし、Gleamにおける変数へのバインディングはImmutableであるので、設定時に不変の値として新しく生成されます。
そのため、let new_answer = all_answer
としても、new_answer
とall_answer
はそれぞれ独立した42という値をもちます。
したがって、all_answer
の値が変わっても、new_answer
は影響を受けないのです。
pub fn main() {
// io.print("hi")
let all_answer = 42
let new_answer = all_answer
let all_answer = 43
#(all_answer, new_answer)
}
Intだとプリミティブ型のようにも思えるので、List型でも確認してみます。
List型の説明はまた後ほど。
実行してみると、やはりnew_answer
は影響を受けていないことがわかります。
文字列を扱う
Gleamの文字列は、「"
」(ダブルクォーテーション)で括って表現します。
シングルクォーテーションは対応していません。
また、Gleamの文字列設定は、マルチラインに対応しています。「"
」で囲んでいる中で改行を入れれば、文字列にも改行が含まれます。
なお、文字列同士を連結する場合には、標準ライブラリで提供されているappned
を利用します。appned
を利用するには、gleam/string
をimportします。
そして、関数string.append
に対して、2つの文字列を格納した変数foo
とbar
を引数として渡します。
let baz = string.append(to: foo, suffix: bar)
これで、foo
とbar
の連結された文字列が、baz
にバインディングされます。
import gleam/io
import gleam/string
pub fn main() {
// io.print("hi")
let foo = "The answer to the ultimate question"
let bar = "about life,
the universe,
and all things"
let baz = string.append(to: foo, suffix: bar)
#(foo, bar, baz)
}
数値を計算をしてみる
Gleamの数値の型には、Int(整数)とFloat(実数)があります。
これらの四則演算を実施してみましょう。
Intの場合、+
で加算、-
で減算、*
で乗算、/
で除算となります。
一方でFloatの場合、+.
で加算、-.
で減算、*.
で乗算、/.
で除算となります。
なお、IntとFloatは、直接演算できません。
Floatをfloat.truncate
を利用してIntに変換するか、
Intをint.to_float
でFloatに変換するか
のどちらかをの対応が必要になります。
以下の例では、a
ではFloatからIntへの変換を、b
ではIntからFloatへの変換を実施しています。
import gleam/io
import gleam/float
import gleam/int
pub fn main() {
let a = 40 + float.truncate(2.0)
let b = 1_000.0 -. int.to_float(958)
#(a, b)
}
TapleとListを扱う
Gleamには、Taple型とListがあります。
Tapleは複数の型をまとめて、ひとつの型として設定したものになります。
たとえば、String
とInt
を組み合わせた場合、以下のように定義します。
#("Gleam導話", 1000)
Listは、あるひとつの型を複数個所持する配列のようなものになります。
たとえば、Int
を複数持つ場合は以下のようになります。
[100, 200, 300, 400, 500]
また、Tapleを複数持つ場合は、以下となります。
[#("Gleam導話", 1000), #("Elixirへのいざない", 1500)]
ただし、Listに格納できるのは同じ型のみです。
違う型を格納しようとすると例外が発生します。
関数を作成する
Gleamでは、独自の関数を作成できます。
関数であることを示すfn 関数名
で宣言し、引数には名前ど型、戻り値には型を指定します。
また、pub
があるとスコープが広がります。module
を作成した場合、モジュール外部から呼び出せるようになるためです。
たとえば、Intの引数a
とb
を加算してIntの値を返す関数を作ると、以下となります。
pub fn add(a: Int, b: Int) -> Int {
a + b
}
これをmain関数側から呼び出せば、この関数が実行されます。
import gleam/io
pub fn main() {
let all_answer = add(40, 2)
all_answer
}
pub fn add(a: Int, b: Int) -> Int {
a + b
}
今回のまとめ
GleamはBEAM上で動作するプログラミング言語です。
BEAMの特徴である並行性を持っているため、スケーラビリティに親和性を持っています。
さらに、型安全で作成されており、堅牢性にも配慮されております。
加えて、他のBEAM系の言語(ErlangやElixir)とも親和性を持っています。
一方で、残念ながらまだ正式バージョンのリリースが行われていません。
そのため、日の目をみることは当面先かと思われます。
2024年3月に正式版がリリースされました。
これによって、少しずつ実際のプロダクションなどでも事例が増えていくのではないかと予想されます。
※ただし、日本での事例は、もう少し後になるでしょうね。
また、v1になったことで、YouTubeでも動画を見かけるようになりました。再生回数もそれなりに多く感じます。
Elixirの作者であるJosé Valim氏もスポンサーになっているため、可能性を秘めた言語であるともいえます。
来る日のために、Gleamを触ってみるのはいかがでしょうか。
参考情報
- 公式WebSite
- GitHub
- 公式(?)Twitter
- Language Tour(The Gleam Book)
- Gleam Plarground
- Gleamの標準ライブラリ(gleam_stdlib)のHexDocs
- Why is it called Gleam?
- BAEM
- Gleamの技術同人誌
Discussion
興味深い記事の公開ありがとうございます。「PlayGroungでGleamを体験してみる」という見出しのtypoに気付いたのでお伝えしておきます。
tkzさん
typeのご指摘、ありがとうございました。
修正しておきました。