変数

変数は基本イミュータブル

let num = 100
let name = "gleam"
 
// 定数はconstで宣言 
const const_string = "This is constant string."

一般的な型名Gleamでの型名Gleamでの表現ライブラリ
整数Int1234gleam/int
文字列String”Gleam”gleam/string
リストList[]gleam/list
タプルTuple#(“Langage”, “Gleam”)gleam/map
浮動小数点型float-12.5 gleam/float
真偽値Booltruegleam/bool
動的型Dynamic————————gleam/dynamic

型変換(キャスト)

Int String

import gleam/int
 
let str = 100
int.to_string(100)

ファイルIO

gleam_erlangをインストール gleam add gleam_erlang

ファイル書き込み

read pub fn read(from path: String) -> Result(String, Reason)

ファイル読み込み

write pub fn write(contents contents: String, to path: String) -> Result( Nil, Reason, )

デバッグ出力

stdlibをimportすると使える pub fn debug(term: a) -> Nil

Result型から値を取得したい

GleamにはRustのようなResult型がある。

pub type Result(success, error) =
  Result(success, error)

以下のようにすればResult型から値を取得出来る。

let Ok(text) = // Resultを返す処理

例えばこんな感じ(gleam_stdlibgleam_erlangパッケージをインストールする必要がある。)

import gleam/io
import gleam/erlang/file
 
let Ok(text) = file.read(path)
io.println(text)

しかし、この方法だとError()が返された場合に例外が発生する。これを避けるにはresult.unwrapを使う。

gleam/resultを使う

Gleamには、Result型を扱う際に便利なメソッドが用意されている。 これらを使うことでよりシンプルにResult型を操作することができる。 ドキュメントはここから見ることができる。

このライブラリに含まれている、result.unwrap()を使うことでResult()から簡単に値を取り出すことが出来る。

Gleam Playground

import gleam/io
import gleam/result
 
pub fn main() {
  let str = sub()
  io.println(result.unwrap(str, ""))
}
 
pub fn sub() -> Result(String, Nil) {
// Ok("ok!")
Error(Nil)
}

unwrap()には2つの引数を指定する必要があり、それぞれ

  • Result型の値
  • Error()だった場合の値 を指定する。Rustのunwrap()と動作が違うので注意。(どちらかというとunwrap_or_default()に近い挙動をする。)

Elixirと連携したい

ここではElixirのIO.puts()をGleamから呼び出してみる。

pub external fn puts(text) -> atom.Atom() =
"Elixir.IO" "puts"

externalというキーワードで、バックエンドの関数を呼び出すことができる。IO.putsはElixirのIOモジュールで宣言されているため、

  • まず1つめの引数でElixir.IOと指定する。
  • その次にputsという関数を呼び出すため、2つめの引数でputsを指定する。

この最初の引数のElixirの部分を指定せず関数のみを指定すると、Erlangの関数を呼び出すことができる。(GleamはErlangにコンパイルされるため、デフォルトでErlangの関数を呼び出す仕様にしたと考えられる)

ちなみにGleamはJavaScriptにもコンパイル出来る。その場合は以下のように、

pub external fn run() -> Int =
  "./my-module.js" "run"

Elixirでモジュールを指定したようにJavaScriptのファイル名を指定する。その次の関数名の指定は同じ。

他のBEAM言語との連携

2024/01/22追記

Gleamで他のBEAM言語の関数を呼び出す方法が変更されている。 Pythonのデコレータのように、関数の上に@externalキーワードを書いて宣言する。

公式ドキュメント

// Erlangのrand:uniform()を呼び出す場合
@external(erlang, "rand", "uniform")
pub fn random() -> Float

他のBEAM系言語(Ex. Erlang/Elixir)の関数を呼び出すには、externalキーワードを使って関数を宣言する。

Erlangの場合

pub external fn random_float() -> Float =
	"rand" "uniform"

Elixirの場合

external fn puts(text: String) -> =
"Elxir.IO" "puts"
 
fn main() {
	puts("Hello Elixir!")
}

JavaScriptの場合

pub external fn run() -> Int =
	"./my-module.js" "run"

関数を定義する際には以下のように引数に型を付けることも出来る。これを行うことでより堅牢なプログラムを書くことができる。ただしGleamはこの型付けを完全に信用する。 もし型付けが間違っている場合は実行時エラーが発生するので気をつける。

pub external fn any(in: List(a), satisfying: fn(a) -> Bool) =
  "my_external_module" "any"

GleamとElixirの相互運用についてはこのサンプルプロジェクトが参考になる。

Elixirのライブラリを使いたい

Gleamのバージョンアップに伴いこの方法は使えなくなりました。
こちらで新しい方法について解説しています。

https://zenn.dev/comamoca/articles/interop-of-gleam-and-elixir

ElixirのライブラリをGleamから使うには、

  • gleam add パッケージ名でパッケージを追加
  • externalで関数を宣言 この順番で行う。 GleamはHexに対応しているのでgleam addでGleamパッケージと同じようにパッケージをインストールすることができる。 また、Gleamには配下のElixirプログラムを自動でコンパイルするというとても便利な機能があるので、プロジェクトの一部をElixirで書きそれをGleamから利用する事も可能。Elixirライブラリのグルーコードを書く場面で便利だと感じた。

パッケージをインストールした後はexternalで宣言することで呼び出す事ができる。 この際、iex -S mixなどでパッケージの関数を呼び出したりして調べながら書いていくと分かりやすい。 以下はElixirのPandexパッケージのgfm_to_html関数を呼び出す例。

pub external fn gfm_to_html(text) -> Result(String, String) =
"Elixir.Pandex" "gfm_to_html"

Javascriptターゲット

GleamはJavascriptをターゲットにコンパイルすることが出来る。 GleamをJavascriptにコンパイルするのは以下の2通りの方法で行うことが出来る。

ビルドオプションにJavascriptを指定

gleam run