プリキュア Advent Calendar 2014 - Adventar の 23 日目の記事です.
Clojure + Precureという意味で命名された,PycureおよびRubicureリスペクトです.
つまり世界初のLispによるプリキュア実装です.更にJVMのためのプリキュア実装でもあります.
ソースコードは kaosf/clocure にあります.ここから Clojars (Clojureのライブラリ登録サービス) へのリンクなども確認出来ます.
実は最初は Clocure ではなくて Prejure という名前にしようと考えていました.「プリ」の方を残したかったですし,何よりたったの1文字しか違わないというのが面白い.
するとなんとLeiningenから警告を受けました."xxxjure" って名前のライブラリは作れないそうなのです.
lein new default prejure
#=>
# Sorry, names such as clojure or *jure are not allowed.
# If you intend to use this name ironically, please set the
# LEIN_IRONIC_JURE environment variable and try again.
そんなわけで名前は Clocure になったのです.
まずLeiningenを用意します.
Clojureが初めての方も,この機会に入門してしまいましょう.
Leiningenのインストールは公式サイトの Install を参考にするのが一番確実です.Windowsユーザはどうすればいいのかも教えてくれます.
Linuxの方は以下を実行すればOKです.
# Debian/Ubuntu
sudo apt-get install openjdk-7-jdk
# Fedora/CentOS
sudo yum install -y java-1.7.0-openjdk java-1.7.0-openjdk-devel
if [ ! -d $HOME/local/bin ]; then mkdir -p $HOME/local/bin; fi
cd $HOME/local/bin
wget https://raw.github.com/technomancy/leiningen/stable/bin/lein
chmod +x lein
./lein
export PATH=$HOME/local/bin:$PATH
echo 'export PATH=$HOME/local/bin:$PATH' >> .bashrc # 必要に応じて .zshrc など
これで ~/local/bin/lein
が用意されてパスも通るので lein
コマンドが使えるようになります.
そうしたらClocureを利用するサンプルアプリ環境を作りましょう.
lein new app myappname # 好きな名前でいい
cd myappname
プロジェクト直下に project.clj
というファイルがあります.これが設定ファイルになります.ここの :dependencies []
の中に [clocure "1.0.0"]
を追加します.多分以下のような形になるはずです.
(defproject myappname "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.6.0"],
[clocure "1.0.0"]]
:main ^:skip-aot myappname.core
:target-path "target/%s"
:profiles {:uberjar {:aot :all}})
そうしたら lein repl
でREPLを起動して,以下を試します.
(require '[clocure.core :refer :all])
(transform nagisa)
;=>
;デュアル・オーロラ・ウェイブ!!
;光の使者、キュアブラック!
;ふたりはプリキュア!
;闇の力のしもべ達よ!
;とっととお家に帰りなさい!
;#clocure.core.Precure{:id black, :name "キュアブラック", :short-name "ブラック", :name-en "Cure Black", :short-name-en "Black", :before nagisa}
ちゃんとなぎさがキュアブラックに変身しましたね?そして transform
関数を経て別の値が帰ってきました.これが black
と同じになります.
(def x (transform nagisa))
(= x black) ;=> true
(= x nagisa) ;=> false
コーディングする上で毎度毎度 cureblack
や shinyluminous
とタイプするのは,プリキュアの名前を打ち込めて幸せハピネスかもしれませんが疲れも溜まってしまいます.
なので全て nagisa
black
luminous
などの短い名前で登録してあります.
あと上記サンプルだとグローバル名前空間に nagisa
だの black
だのが登録されてるように見えますが,実際すべて clocure.core/
配下に定義されています.それを打たなくても使えているのは require
の部分の :refer
のおかげです.
グローバル名前空間に見えないですか?最初からちゃんと clocure.core/
が見えてました?JVM界隈の感覚がよく分からないので不安です…
なぎさとほのかはふたり一緒じゃないと変身出来ないのが設定上正確です.しかしClocureではあえて自由度を持たせるために単体での変身を制限していません.
しかし,ふたりで変身することももちろん可能です.そのためには transform
関数に :with
を使ってもう一人を渡します.
(transform nagisa :with honoka)
;=>
;なぎさ・ほのか「デュアル・オーロラ・ウェイブ!!」
;ブラック「光の使者、キュアブラック!」
;ホワイト「光の使者、キュアホワイト!」
;ブラック・ホワイト「ふたりはプリキュア!」
;ホワイト「闇の力のしもべ達よ!」
;ブラック「とっととお家に帰りなさい!」
;[#clocure.core.Precure{:id black, :name "キュアブラック", :short-name "ブラック", :name-en "Cure Black", :short-name-en "Black", :before nagisa} #clocure.core.Precure{:id white, :name "キュアホワイト", :short-name "ホワイト", :name-en "Cure White", :short-name-en "White", :before honoka}]
こうすると,今まで (transform nagisa)
の評価結果は black
と等価だったのが,二人で変身したことにより二人のプリキュアが返ってきます.
(def futari (transform nagisa :with honoka))
(= futari [black white]) ;=> true
複数同時変身はこの他に咲と舞,スイートチームと,あともう一組で実装されています.
ふたりはプリキュアSplash☆Starにおいて,キュアブルームとキュアイーグレット,キュアブライトとキュアウィンディは必ずどちらか片方の組み合わせでしか出現しません.(※ブルームとウィンディ,ブライトとイーグレットはありえないということ)
単体で変身した場合にはその限りではありませんが,複数同時変身の場合には必ず揃いのペアで登場します.
(def futari (transform saki :with mai))
(or
(= futari [bloom egret])
(= futari [bright windy])) ;=> true
他のプリキュア実装には居ないキャラを追加するブランチが実はあります.満と薫,キュアフラワー,キュアエンプレスなど,まだおひろめが出来ていません.しかし,ハピネスチャージプリキュアに登場した,間違いなくプリキュアである,とあるふたりが居ます.
オハナとオリナです.
(transform ohana :with orina)
;=>
;(かわルンルン♪)
;オハナ・オリナ「プリキュア!くるりんミラーチェンジ!」
;サンセット「紅い夕日は明日への誓い!キュアサンセット!」
;ウェーブ「寄せては返す悠久の調べ!キュアウェーブ!」
;サンセット・ウェーブ「南国に輝く二つの光!アローハプリキュア!」
;[#clocure.core.Precure{:id sunset, :name "キュアサンセット", :short-name "サンセット", :name-en "Cure Sunset", :short-name-en "Sunset", :before ohana} #clocure.core.Precure{:id wave, :name "キュアウェーブ", :short-name "ウェーブ", :name-en "Cure Wave", :short-name-en "Wave", :before orina}]
さっき複数変身のところで言った「もう一組」とは彼女たちのことです.
そして,イースも居ます.実は setsuna
に限り transform
関数ではなく switch-over
関数に適用することが出来ます.すると評価結果が eas
になります.
(def x (switch-over setsuna))
(= x eas) ;=> true
あ!あと当然なんですが,キュアエコーちゃんと居ます!キュアエコーはプリキュアです!
単なるお遊び(というのが半分以上ですが)で作ったわけではなく,「プリキュア全員の名前を特定の形式で取得したい」などの要望を満たすために作りました.
なので以下のようなものがあります.
(:name nagisa) ;=> "美墨なぎさ"
(:first-name nagisa) ;=> "なぎさ"
(:family-name nagisa) ;=> "美墨"
(:name black) ;=> "キュアブラック"
(:short-name black) ;=> "ブラック"
(:name-en black) ;=> "Cure Black"
(:short-name-en black) ;=> "Black"
苗字が無い人なんかはその辺りが nil
になります.
(:family-name eas) ;=> nil
(:family-name orina) ;=> nil
この辺りの七面倒臭い設定を一括で行ってくれるのが,これこそがClocureの特徴(であってくれたらいいなぁ…)である defhuman
マクロと defprecure
マクロです.
以下のような設定をS式として並べていけば,変身前と変身後の対応も取って Human
と Precure
が定義出来ます.
(defhuman nagisa misumi なぎさ 美墨 なぎさ みすみ black)
(defhuman honoka yukishiro ほのか 雪城 ほのか ゆきしろ white)
(defprecure black ブラック nagisa)
(defprecure white ホワイト honoka)
いちいち "black"
や "ブラック"
と文字列指定しなくても大丈夫です.
変身メッセージは設定にするには長いのとまだ実装の仕様が出来ていないのとで transform-messages
に辞書形式で追加していく形になります.
このような感じでキャラの追加が行い易く,記述の見通しも高まります.
YAMLにするのも考えたのですが(JSONは考えなかった),いちいち name: black
のように書くのが面倒だったので,見た目スプレッドシートのように書ける,ただしS式である,という現状に落ち着かせています.
まずは満と薫,そしてキュアフラワー,キュアエンプレスを実装する.
まずは可能であれば,揚げたてフレッシュなキュアカオルちゃん,キュアファイヤー,キュアゴリラ,キュアセバスチャンも実装したいです.異質な変身するを人たちを集めたいです.
それと妖精.妖精が居ないと変身出来ないプリキュアがシリーズによっては居ます.それを再現したいです.
後は strict モードを導入したいです.これを設定しておけば (transform nagisa)
が何らかの例外(ほのか無しの一人では変身出来ません or メップルが居ないと変身出来ません)を吐くようになる感じ.
後何よりもGo!プリンセスプリキュアの三人の名前が判明しましたので,ブランチ用意して待っておくべきですね.
他には,せっかくのClojureなので並列処理に対応するとか無意味にしたいですね.あっちでキュアブルームに変身したなら,こっちは絶対にキュアイーグレットにしか変身しない,とか.現状単なるランダムなので.
更に他には,変身時のセリフも何らかのマクロ,あるいは独自の仕様とそのパーサを作って,今全パターン書いているのを統一出来るようにしたいです.これもまだ実験状態のブランチが眠ってます…
- Lispはプリキュアになれる!
- マクロ難しいけど出来たら楽しい
- もっとやりたいこといっぱいあるねん