Open7
Gleam やる
Gleamという言語があって、ある。Erlangランタイムで動くらしい。
インストール
lsp serverは gleam lsp
で起動するタイプだった。
flake.nix
{
description = "A very basic flake";
outputs = { self, nixpkgs }:
let pkgs = nixpkgs.legacyPackages.x86_64-linux; in
{
devShells.x86_64-linux.default = pkgs.mkShell {
buildInputs = [ pkgs.gleam pkgs.erlang pkgs.rebar3 ];
};
};
}
rebar3
はErlangのビルドシステム。
HTTPサーバー書くぞ〜 gleam new
して gleam add wisp
app/web.gleam
import wisp
pub fn middleware(
req: wisp.Request,
handle_request: fn(wisp.Request) -> wisp.Response,
) -> wisp.Response {
use <- wisp.log_request(req)
use <- wisp.rescue_crashes
handle_request(req)
}
use <- f()
ってのがかなりおもろそう
app/router.gleam
import wisp.{type Request, type Response}
import gleam/string_builder
import app/web
pub fn handle_request(req: Request) -> Response {
use _req <- web.middleware(req)
let body = string_builder.from_string("<h1>Hello, Wisp!</h1>")
wisp.html_response(body, 200)
}
ここでよくみてみよう、2引数をとるはずの web.middleware
の呼び出しが1引数で行われているようにみえるが……要するにKokaの with
みたいな感じで呼び出し側の以降の処理が最終引数の関数としてぶん投げられている気配を感じる。
Gleam lacks exceptions, macros, type classes, early returns, and a variety of other features, instead going all-in with just first-class-functions and pattern matching.
そうなんだ
This makes Gleam code easier to understand, but it can sometimes result in excessive indentation.
pub fn main() { logger.record_timing(fn() { database.connect(fn(db) { file.open("file.txt", fn(f) { // Do something with `f` here... }) }) }) }
あーこいつらは非同期的に実行されるんかな、昔のJSのコールバック hellですわね
が、use
を使うとこうなる。Kokaの with
〜〜〜〜
pub fn main() {
use <- logger.record_timing
use db <- database.connect
use f <- file.open("file.txt")
// Do something with `f` here...
}