いつの間にか Ja 婆婆が妙に流行っていたのでどれいっちょ Rust で実装してみっかと思って念の為検索をかけたらもういたので, 人気がなさそうなまず間違いなくかぶらない PureScript で実装することにしました。
なお, PureScript で標準入力を実現するのは少し面倒なので, コードに直書きすることにしてます。 すまねえ。 やり方はこちら。
でも代わりに Try PureScript! に貼り付けて実行できるので環境構築とかしなくても遊べるよ。
コード
module Main where
import Prelude
import Data.String.CodePoints (length)
import Data.String.CodeUnits (singleton)
import Data.String.Unsafe (charAt)
import Effect (Effect)
import Effect.Console (log)
import Effect.Random (randomInt)
yubaba :: String -> Effect String
yubaba name = do
let nameLen = length name
index <- randomInt 0 (nameLen - 1)
pure $ singleton $ charAt index name
main :: Effect Unit
main = do
log "契約書だよ。そこに名前を書きな。"
-- 契約書
let name = "千尋"
log $ "フン。" <> name <> "というのかい。贅沢な名だねぇ。"
newName <- yubaba name
log $ "今からお前の名前は" <> newName <> "だ。いいかい、" <> newName <> "だよ。分かったら返事をするんだ、" <> newName <> "!!"
実行結果
解説
main
mainに関しては見たままです。 PureScript の知識がなくてもなんとなく分かると思います。 PureScript では関数は引数をカッコで囲んで与える必要はなく, 隣に書くだけで OK です。 間に挟まっている$は関数適用演算子で, a $ b $ c $ dはa(b(c(d)))に等価です。 全体をカッコで囲う必要がないので便利です。
非 Haskeller に説明が必要そうな部分として, let hoge = ...とhoge <- ...の違いは, 右辺がEffectつまり作用を持っているかどうかです。
作用のない, 直の値なら=でそのまま束縛します。
作用を持つなら値そのものではなく, 「それによって得られる値をこのように操作する」という手順(アクション)として記憶します。 そのために使うのが<-です。
logは標準出力にStringを流します。 <>は文字列の結合に使う演算子です。 関数適用は演算子よりも優先度が高いので, 全体をカッコで囲む……かわりに$演算子を使っています。
yubaba
yubabaは気持ち的にはStringをとってStringを返す関数です。 湯婆婆関数とかいうパワーワード。 しかし, 乱数によって結果が変わる……すなわち作用を持つので, 文字列そのものではなく「Stringを得る手段(アクション)」Effect Stringを返します。
lengthはStringの文字数Intを返します。
randomIntは第一引数Int以上第二引数Int以下の整数を得ます……が, 乱数なので作用を持ちます。 つまりこの関数はIntそのものではなく「Intを得る手段(アクション)」Effect Intを返しています。 よって<-です。
charAtは第二引数のStringの第一引数Int文字目のCharを返します。
singletonはCharをStringに変換しています。
pureは少し説明が難しいのですが, 「この値を手順(アクション)Effect Tとして扱う」というような意味を持ちます。 この関数は手順(アクション)を返すからです。 indexは具体的な値そのものではなく, 便宜上つけられた識別名でしかありませんので, 最後に手順(アクション)を返さなければいけないのはそれは当然だよね。
クラッシュする湯婆婆
もちろん元ネタ様にしたがい, 空文字列を与えるとクラッシュします。 やったぜ。
これはわざと「安全でない」charAtを使用しているためです。 よく見るとUnsafeって書いてあるよね。 PureScript は超・安全志向言語なのでちゃんとしたプログラムではこんなことは起こりませんが, それについて長々と語ってもただの宣伝になってしまいますし, なにより Ja 婆婆らしさ(?)がなくなってしまいますので割愛。

