Gleamで湯婆婆を実装してみる


1.はじめに

令和時代の"Hello world"と呼ばれる(?)湯婆婆実装シリーズに便乗してみました。

この記事では、Gleamという言語での実装にチャレンジしました。

Gleamについてご存じない方は、こちらを参照頂けると幸いです。
→ Gleam (Rust + Erlang) 事始め

2.実装例

(1)プロジェクトの作成

コマンドライン
$ gleam new yubaba
* creating yubaba/LICENSE
* creating yubaba/.gitignore
* creating yubaba/README.md
* creating yubaba/gleam.toml
* creating yubaba/test/yubaba_test.gleam
* creating yubaba/src/yubaba.gleam
* creating yubaba/.github/workflows/test.yml
* creating yubaba/rebar.config
* creating yubaba/src/yubaba.app.src

Your Gleam project "yubaba" has been successfully created.
The rebar3 program can be used to compile and test it.

    cd yubaba
    rebar3 eunit

(2)コード

標準入力の関数が無いようなので、名前の入力は、関数の引数に直接与えています。

また、”名前を奪う”ために、ランダムにN文字目を取り出す処理が、かなり回りくどい書き方になってます・・・

src/yubaba.gleam
import gleam/float
import gleam/int
import gleam/io
import gleam/result
import gleam/string

pub fn hello_world() -> String {
  "Hello, from yubaba!"
}

//0.0~1.0の間でFloat型の乱数を返す
//https://gleam.run/book/tour/external-functions.html
pub external fn random_float() -> Float = "rand" "uniform"

//湯婆婆関数
pub fn yubaba(name:String) {

  //文字の長さを取得
  let name_length = int.to_string(string.length(name))

  //何文字目を切り出すか乱数で決める:その1
  //※to_float関数がまだ実装されてないのでダメでした
  //  https://hexdocs.pm/gleam_stdlib/gleam/int/#to_float
  //let name_num = int.to_float(name_length) *. name_length

  //何文字目を切り出すか乱数で決める:その2
  //※回りくどいけど、なんとかできた・・・

  //”文字列の長さの値”を、一旦文字列に変換して、小数点を付ける
  let length_1 = string.concat([name_length, ".0"])
  //”小数点付きの文字列長”の文字列を、floatに変換。unrap関数で値と成功/失敗値を分割
  let length_2 = result.unwrap(float.parse(length_1), 0.0)
  //乱数の値と、文字列長を掛けて、何文字目を取り出すかを決める
  let name_num = float.round(float.floor(random_float() *. length_2))

  //名前を1文字切り出す
  let name_new = string.slice(from: name, at_index: name_num, length: 1)

  //湯婆婆のメッセージ
  io.println("\n■■■ Gleamで湯婆婆を実装してみる ■■■\n")
  io.println("契約書だよ。そこに名前を書きな。\n")
  io.println(string.concat([" > ", name, "\n"]))
  io.println(string.concat(["フン。", name, "というのかい。贅沢な名だねぇ。\n"]))
  io.println(string.concat(["今からお前の名前は", name_new, "だ。いいかい、",
      name_new, "だよ。分かったら返事をするんだ、" , name_new, "!!\n"]))

  //何文字目を切り取ったかの値を返す
  name_num
}

(3)実行例

  1. rebar3 shellでコンパイル、対話モードに入ります。
  2. プロンプトにyubaba:yubaba("yourname").を入力してEnterします。(今回の実装だと、全角はだめっぽい)
  3. 湯婆婆に名前を奪われます。
コマンドライン
$ rebar3 shell
===> Verifying dependencies...
Compiling gleam/otp/port
・・・(省略)・・・
Done!
===> Analyzing applications...
===> Compiling yubaba
Erlang/OTP 22 [erts-10.5.4] [source] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Eshell V10.5.4  (abort with ^G)

1> yubaba:yubaba("myasu").  
■■■ Gleamで湯婆婆を実装してみる ■■■
契約書だよ。そこに名前を書きな。
 > myasu
フン。myasuというのかい。贅沢な名だねぇ。
今からお前の名前はaだ。いいかい、aだよ。分かったら返事をするんだ、a!!
2

2> yubaba:yubaba("myasu").
■■■ Gleamで湯婆婆を実装してみる ■■■
契約書だよ。そこに名前を書きな。
 > myasu
フン。myasuというのかい。贅沢な名だねぇ。
今からお前の名前はyだ。いいかい、yだよ。分かったら返事をするんだ、y!!
1

3> yubaba:yubaba("pomu"). 
■■■ Gleamで湯婆婆を実装してみる ■■■
契約書だよ。そこに名前を書きな。
 > pomu
フン。pomuというのかい。贅沢な名だねぇ。
今からお前の名前はuだ。いいかい、uだよ。分かったら返事をするんだ、u!!
3

4.まとめ

Gleamの勉強がてら(?)試してみました。
悩ましいところが多々あるので、ぼちぼちと直していきます・・・

参考資料