変数
変数は基本イミュータブル
let num = 100
let name = "gleam"
// 定数はconstで宣言
const const_string = "This is constant string."型
| 一般的な型名 | Gleamでの型名 | Gleamでの表現 | ライブラリ |
|---|---|---|---|
| 整数 | Int | 1234 | gleam/int |
| 文字列 | String | ”Gleam” | gleam/string |
| リスト | List | [] | gleam/list |
| タプル | Tuple | #(“Langage”, “Gleam”) | gleam/map |
| 浮動小数点型 | float | -12.5 | gleam/float |
| 真偽値 | Bool | true | gleam/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_stdlibとgleam_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()から簡単に値を取り出すことが出来る。
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のライブラリを使いたい
こちらで新しい方法について解説しています。
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