第16話

 「ずいぶん昔に呪文をアレンジして新呪文を作ろうとした時は全然成功しなかったですな」

 「呪文を唱える時はその呪文の結果に疑問を持ったらダメなのさ。どうせ君のことだから成功するか失敗するか確かめようとか思ってたんじゃないのかい?」

 「それは科学的な態度ですな」

 「科学はともかく、魔法は信じてないと成功しないさ」


 ――これは盲点だったですな。確かに心理的要素が魔法の発動に影響を与えるというのはありえる話ですな。


 そしてダフニはさらにもう1つの可能性についても頭に浮かんだ。


 「呪文の意味は誰が理解できればいいのですかな? 精霊ですかな? それとも」

 「あのタケノコが言葉を理解できると思うかい?」

 「ということは、呪文は本人が意味を理解してその結果を信じていれば他の誰も理解できない言語でもいいですかな?」

 「変なことを聞くな。そんなことをする意味があるかどうかは知らないけど精霊にとっては意味しか興味ないからいいに決まってるさ」


 そう言うとリピカはもう話は終わりというようにダフニから勝手に魔力を引き出してどこかへ消えてしまいそうになったので、思わず手を伸ばして首根っこを捕まえた。最初の頃は精霊に触れることもできなかったが、最近はそんな芸当もできるようになっていた。


 「ぐえ」

 「もう一つ質問があるですな」

 「えー」

 「どうして魔法には精霊が必要なのですかな?」

 「精霊がいなきゃ因果律に干渉できないからだよ。はい、これで話はおしまいです。ばいばい」


 言い終わるや否やリピカは両手いっぱいに魔力を持ってすたこらとどこかへ行ってしまった。といってもいつものことでそんな遠くに行ったわけではなく、少しくらい離れていてもリピカの魔法は使えるので問題ない。


 それに、ダフニの方ももうリピカへの質問は十分と一人で何かを考え始めていた。


 ――これはプログラムできるかもですな。いや、かもではなくて、できると言い切らないといけないですかな。


 ダフニが考えていたのは魔法をプログラミング言語で記述することだった。別に自然言語でもいいのになぜという疑問はあるが、それは元プログラマとしての趣味と意地と言うべきところだった。金槌があれば叩きたくなるのがプログラマというものなのだ。


 それに少し前にエーテル知覚について調べているうちに面白い使い方を見つけたので、それを使ってみたいというのもあった。それはエーテル知覚のチャネルを変えるということに関して、空きチャネルを使って真っ黒なコンソールのような視界を作り出すとそこに自由に文字や絵を書けるというものだった。


 失明したすぐ後に黒い視界に光点を表示して明滅させたり動かしたりしていたのがグレードアップしたようなものだったが、そこに数式やプログラムを書くと答えを表示させることができることを確認していて、これを何かに応用できないかと思っていたのだ。


 ――まず手始めはリピカを呼んでみるですな。


> main = do

>  menu <- lipika "今日の朝ごはん"

>  print menu

納豆トースト、陸はまぐりのすまし汁


 ――お、動いたですな。


 使った言語はもちろんHaskellだった。副作用があるとプログラムが動かないというのは当然呪文においても同じと想定すれば関数型言語の方が書きやすいだろうし、精霊の魔法の発動の順序が何となくHaskellのIOモナドを思い出させたということもあった。


 モナドというのはHaskellに特徴的で重要な仕組みの1つだ。Haskellには副作用がなくプログラムの実行順序が実行時まで確定しない。しかしそれだと入出力などを扱うのに困るので、部分的に実行順序を明示的に確定させてやることができる仕組みがモナドなのだ。


 例えば


> main =

>  let

>   a = 1 + 2

>   b = 3 + 4

>  in a + b

10


というプログラムで普通のプログラミング言語なら上から順に 1 + 2 を計算した後に 3 + 4 を計算する。しかし、数学的には計算順序に意味はなくHaskellでも計算順序は保証していない。つまり、もしかしたら 3 + 4 を計算してから 1 + 2 を計算するかもしれないのだ。


 これが入出力があるとどういうことになるかというと、


> main =

>  let

>   x = put "こんにちは"

>   y = put "こんばんは"

>  in x && y


と書いたとき、結果が


こんにちは

こんばんは


になるのか


こんばんは

こんにちは


になるのか予測がつかないということだ。さらに場合によっては片方しか出力されないということも起こり得る。こんないい加減なことではまともにプログラムが書けない。


 そこでHaskellではどうしているかというと、簡単に言うとプログラムの中では何をどういう順序で実行するかということを決めたデータだけを作って、それを読みこんで実行する部分はプログラムを解釈する誰か(コンピューター)に任せてしまうということにしている。そしてこのデータを作る仕組みをIOモナドと呼ぶのだ。


 この考え方が魔法と似ていると思うのは、呪文は精霊に魔法の「回廊」(=銃)の定義しか書いておらず詠唱中には魔法は発動しない。精霊は呪文が終わった後で魔力を受け取って銃を作り引き金を引く。精霊の種類によって銃の形も異なるが引き起こされる結果は同じだ。この魔法の定義と実行が分離されている様子がダフニにIOモナドを連想させた。


 元のプログラムに戻ると


> main = do

>  menu <- lipika "今日の朝ごはん"

>  print menu


というのは、まずlipikaというところでリピカに「今日の朝ごはん」の内容を思い出させて、printで画面にその内容を表示するという意味だ。printはhaskellの標準関数だが、lipikaはどこにも定義していない。しかし、リピカによれば魔法使いがその意味を理解して結果に疑問を持たなければ動くというものらしい。


 ちなみに上のプログラムは下のように簡単な形に書き換えることができるので、普段使いには簡単な方を覚えておくことにした。


> main = print =<< lipika "今日の朝ごはん"


 さて、プログラムが魔法に使えることがわかったところで本題に戻って精霊の名前を調べるプログラムだ。元の呪文は「誓約にて共にする精霊に請い願い奉る。我、汝に一つの求めあり。我が左肩に汝の類を刻むる回廊を作りたまへ。コール」というものだった。これを契約していない精霊にも使えるようにするのだ。


 最初にダフニが書いてみたのは次のようなプログラムだった。


> main = do

>  spirit <- locate "そこの精霊"

>  target <- locate "この紙"

>  introduce spirit "類" target


 翻訳すると「そこの精霊spiritに対して、この紙targetに類を書くintroduce」ということになる。ほぼ呪文をプログラムの形に置き換えた内容だ。ただし、魔力を与えるところは書いていないので不完全だ。そこで考えたのちにダフニは次のように書き直した。


> main = do

>  spirit <- locate "そこの精霊"

>  target <- locate "この紙"

>  let corridor = do

>     introduce "類"

>     on target

>  give spirit 1

>  call spirit corridor


 変わったところは回廊corridorを定義してから魔法の発動callを呼び出しているところと、精霊に魔力を与えているgiveところだ。corridorの構築に別のモナドを使ったのは異なる種類の魔法のプログラムを書くときのことを考えたものだ。


 ここで例によってタケノコ君に登場してもらってこのプログラムを使うと、紙に「グノムス」という名前が表示された。どうやらタケノコ君の名前はグノムスというらしい。


 ――これは便利ですな。しかし、毎回プログラムを書くのは面倒ですな。


 と考えて、ダフニは天啓にうたれた。


 ――名前を付ければいいですな!


 名前を付けておけば、リピカの力でいつでも書いたプログラムを細大漏らさず思い出すことができる。これを使えば今後複雑なプログラムを書いた時にも一々紙にメモしたりしなくてもいつでも思い出してプログラムを使うことができる。


Ask-Spirit-Name

> main = do

>  spirit <- locate "そこの精霊"

>  target <- locate "この紙"

>  let corridor = do

>     introduce "類"

>     on target

>  give spirit 1

>  call spirit corridor


 というわけでこのプログラムには「Ask-Spirit-Name」という名前がつけられた。


 それから、このプログラムをデバッグしていて、同じ魔法の連続起動は精霊契約がなくてもできるということに気が付いた。呪文の方だと表現が難しくて見落としていたが、プログラムにしたことで簡単に書けるようになって判明した。単に最後の2行を繰り返すだけだ。つまり、こんな感じだ。


> main = do

>  spirit <- locate "そこの精霊"

>  target <- locate "この紙"

>  let corridor = do

>     introduce "類"

>     on target

>  give spirit 1

>  call spirit corridor

>  give spirit 1

>  call spirit corridor

>  give spirit 1

>  call spirit corridor

  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る