gleamを試す
この記事を読んでgleamに興味が出てきた(特にTSユーザーってわけじゃないけど)
Elangは知ってるけど使ったことない・Rustは多少わかる勢
公式
チュートリアル
基本的なところを触って試すことができる
もうちょっと触りたいのでローカルで環境構築
環境構築
ubuntu 22.04使っているので、それに合わせて入れる
asdf使っているので、asdfでgleam入れてみる
asdf plugin-add gleam
asdf install gleam latest
asdf global gleam latest
gleam --version
gleam 1.2.1
erlang
ベースはerlangで動くので、上記ドキュメントに従って入れる
ドキュメントだと、 esl-erlang
を入れるよう書いてあるが、apt packageで検索しても無かったので、erlang
で入れてみる
wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb
sudo dpkg -i erlang-solutions_2.0_all.deb
sudo apt update
sudo apt install erlang
erl -version
Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version 12.2.1
Reber3
Erlangの標準のビルドツールらしいので、入れる
VSCodeでの設定
入れる拡張
チュートリアルプロジェクト
$ gleam new vars
Your Gleam project vars has been successfully created.
The project can be compiled and tested by running these commands:
cd vars
gleam test
せっかくなのでテスト動かす
gleam test
Resolving versions
Downloading packages
Downloaded 2 packages in 0.06s
Compiling gleam_stdlib
Compiling gleeunit
Compiling vars
Compiled in 1.13s
Running vars_test.main
.
Finished in 0.006 seconds
1 tests, 0 failures
生成されているテストコードは以下
import gleeunit
import gleeunit/should
pub fn main() {
gleeunit.main()
}
// gleeunit test functions end in `_test`
pub fn hello_world_test() {
1
|> should.equal(1)
}
コメントにあるとおり、最後に_test
を入れないと判定されないそう
pub fn hello_world_test2() {
$ gleam test
Compiling vars
Compiled in 0.20s
Running vars_test.main
Finished in 0.002 seconds
0 tests
わざと壊してみる
1
|> should.equal(2)
$ gleam test
Compiled in 0.02s
Running vars_test.main
F
Failures:
1) vars_test.hello_world_test: module 'vars_test'
Values were not equal
expected: 2
got: 1
output:
Finished in 0.005 seconds
1 tests, 1 failures
TourのPipelinesの説明を見る限り、以下のように他の言語でもよくあるような感じでassertできる。
(基本はパイプラインで渡す感じなんだとは思うけど)
// 1
// |> should.equal(2)
should.equal(1, 2)
gleeunitのassertionは actual, expectedの順番なのか。
依存関係の追加
gleam add envoy argv
[dependencies]
gleam_stdlib = ">= 0.34.0 and < 2.0.0"
+envoy = ">= 1.0.1 and < 2.0.0"
+argv = ">= 1.0.2 and < 2.0.0"
[dev-dependencies]
gleeunit = ">= 1.0.0 and < 2.0.0"
lockファイルも変更がかかる
packages = [
+ { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
+ { name = "envoy", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "CFAACCCFC47654F7E8B75E614746ED924C65BD08B1DE21101548AC314A8B6A41" },
{ name = "gleam_stdlib", version = "0.38.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "663CF11861179AF415A625307447775C09404E752FF99A24E2057C835319F1BE" },
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" },
]
[requirements]
+argv = { version = ">= 1.0.2 and < 2.0.0"}
+envoy = { version = ">= 1.0.1 and < 2.0.0"}
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
argv
argv使ったコード
pub fn main() {
case argv.load().arguments {
["get", name] -> get(name)
_ -> io.println("Hello from vars!")
}
}
fn get(name: String) -> Nil {
io.println("args")
}
gleam run get T
args
gleam run set T
Hello from vars!
pub fn main() {
+ io.debug(argv.load().arguments)
case argv.load().arguments {
["get", name] -> get(name)
_ -> io.println("Hello from vars!")
gleam run get T
Compiled in 0.02s
Running vars.main
args
["get", "T"]
["get", "T"]
と取ることができるので、Listのパターンマッチができるということぽい。
case argv.load().arguments {
// 1つ目が"get"で2つ目がなにかあれば、nameにバインドできるぽい
["get", name] -> get(name)
_ -> io.println("Hello from vars!")
パッケージ分け
To call the format_pair function from a module in the test/ directory we will need to make it public. We don’t want it to be part of the public API of the package, so we’ll move it to an internal module, which by default are modules named packagename/internal and packagename/internal/*.
internal
という名前にすれば内部モジュールという扱いになるらしい。
import envoy
import gleam/io
import gleam/result
+import vars/internal
pub fn main() {
case argv.load().arguments {
fn get(name: String) -> Nil {
let value = envoy.get(name) |> result.unwrap("")
- io.println(format_pair(name, value))
+ io.println(internal.format_pair(name, value))
}
-
-fn format_pair(name: String, value: String) -> String {
- name <> "=" <> value
-}
+pub fn format_pair(name: String, value: String) -> String {
+ name <> "=" <> value
+}
vars/internal.gleam
とつくれば、 import vars/internal
という形でimportができるらしい
どんなパッケージを入れればいいか
パッケージの検索
ユースケース別にまとまっているrepositry
csv -> listへのパース
gsvというのがある。
ただし、先頭列に"
があると、うまくパースができない(1つのリストにまとまってしまうなど)ことがある
todoキーワードが使えるらしい。
ただ、todoの部分のコードを実行しないと落ちないので、普通にコンパイルはできてしまいそう
あと、todoがなくても同じ not yet implementは出る
case文で _
のあとに書くと、 cannot be reached
と怒られる
case request.path_segments(req) {
["ws"] ->
mist.websocket(
request: req,
on_init: fn(_con) { #(state, Some(selector)) },
on_close: fn(_state) { io.println("goodbye!") },
handler: handle_ws_message,
)
["echo"] -> echo_body(req)
_ -> echo_req(req)
["chunk"] -> serve_chunk(req)
}
}
warning: Unreachable case clause
┌─ mist_handler.gleam:36:5
│
36 │ ["chunk"] -> serve_chunk(req)
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This case clause cannot be reached as a previous clause matches
the same values.
Hint: It can be safely removed.