欲しいシーンはあるので、ちょっと欲しいです。文の強力版ただし、match式はパターンマッチのほんの1例にすぎない。この例だと、あまりありがたみはないが、F#にはさまざまな形式のパターンマッチが提供されているので、非常に便利。名無しの権兵衛さんレコード型をパターンマッチで分解しているの図。!だったりするが華麗にスルーで。Pattern,(アクティブパターン)なんてのもある。なんか見たことあるやつ。動物抽象クラスを継承して動物たちが鳴くやつ。ここもスルーで(機能的にはmatch式と同じでその引数省略できる版)いわゆる代数的なデータ型的なやつ。一部誤解を与えてしまう可能性もあるが、ある種のクラス階層を表現するのに使える。オブジェクト指向プログラミングの「継承」と明らかに違う点は、まったく性質の異なるものを同質のものとみなして定義することが出来る点、かなあと思う。これを難しいと言われると、もうどうしようもない。中括弧のことなわけですが。洞窟物語のキャラにカーリーブレイスって居たなと。スコープがインデントで区切られるという構造のオフサイドルール(軽量構文)。Pythonインスパイア。これに対して、インデントにしばられない冗語構文もあるが、(どうとでもなるので)そっちは別段覚えなくてもよいと思う(個人の感想)オフサイドルールは最初こそ少しとっつきにくいかもしれないが、ルールがシンプルなのですぐに慣れることができるだろうし、実際明確でわかりやすいように思う。人によっては「見た目キモすぎぃぃぃ」と言う反応をする方もいる。それも理解できないこともない。慣れないものを見ると拒絶反応を示すというのはごくごく当たり前の反応だし。無理なものは無理だし。you!)とかもまあ現実世界でも実際あるわけだし、世知辛いですね(なんの話)唐突には挿入した息抜き用の画像。さんが作ってくれたものです。かなりの謎コラだけど、非常によい表情です。変数は、値にわかりやすい名前を付けて定義しておくことで、続くコードで再利用するためのもの。変数を作り出すことを変数束縛と言います(くどい)例えば破壊的代入(再代入)を許すようなプログラムでは、変数が異なる状態を持ち得るのでその変数を参照する場合「この変数の今の値は何だろう?」と観測しなければならなくなり、複雑性を生み出す要因となる。よる変数束縛ではデフォルトで破壊的代入(再代入)ができません。mutable宣言をすることで、破壊的代入が可能な変数として宣言することもできます。関数プログラミングというスタイルでは極力「破壊的な状態の変化」というものを避ける傾向にあるので、破壊的代入をデフォルトで許さないようにしている。これはスタイルとしての「副作用をできるだけ使わない」ということを推奨/支援しているとも言える。変数が状態を持ってしまうと、その変数を参照する箇所で「この変数の今の値は何だろう?」と注意しなければならない。この例においては、2番目の出力は「5963」ではなく「4649」と表示される。F#は、変数を後から宣言した同名の変数でシャドウイング(隠ぺい)することができる。シャドウィングが使えることで、破壊的代入をしなくても不便さはそれほどなくなる。プログラムのスコープが明確になり、書きやすいだけではなく非常に読みやすいプログラムとなる。スコープの中の直前のものにのみ着目すればよいので、余計な複雑さを排除できてコードの見通しがくなり、プログラミングそのものに集中できる。宣言をシャドウィングすることはできないという制限ありプログラマーのかわりに関数を利用しているコードの型などから、コンパイラがよしなに型をつけてくれる型推論。関数の引数や戻り値にも型を書かなくてよいし、可能であればジェネリックな関数として自動的に推論してくれたりする。変数の定義も関数の定義も、letというキーワードで統一的に定義できるようになっていてうれしい。キーワードを覚えるだけで、かなりのプログラミングが書ける。式を覚えれば条件分岐もできる。覚えれば、ループ処理が書けるので、いとも簡単に三種の神器を手に入れることができる(アッハイ)JavaScriptのコードでカリー化関数と部分適用の説明。JavaScript!なのだが、社内勉強会用に作った資料の流用だったりするので。高階関数のうれしいところ高階関数を扱いやすくするのに必要な機能とかの話。F#では関数内関数が簡単にかけてうれしい。高階関数を書きやすくする要因のひとつとして、関数内関数が無理なくかけるかというのがある。書けないこともないが、どうしても書きにくいので書くモチベーションにならない。素直に名前を付けてメソッドとして切り出して書くべきだ。F#では、無理なく関数内関数を書くことができるのでなんの抵抗も生まれないし、その場限りの関数であれば、関数内関数として定義することはごくごく当たり前に行われる。これは、インデントによるオフサイドルールとも相性が良く、書き方/スタイルとして非常になじむ。プログラミングスタイルそのものが変わります。関数の合成のしやすさも、関数プログラミングのしやすさの指標と考えられます。C#で合成関数を書こうとするとかなり骨が折れます。これは、特定の型に関する合成しかできません。F#で定義した関数は、コンパイラの型推論と自動ジェネリック化のメカニズムによって、可能であれば暗黙的にジェネリックな関数となります。これにより非常にシンプルな記述で、あらゆる型の関数を合成するような関数(演算子)が表現できてしまうというわけです。いった特徴を兼ね備えているので、小さな関数を巧みに組み合わせて、より大きな関数を構築していくという関数プログラミングというプログラミングスタイルが違和感なく行えます。レキシカルスコープのほうが、コードを追いやすい話。ダイナミックスコープで解決されてうれしい場面ってどの程度あるのだろうか。F#はレキシカルスコープを採用しているので、オフサイドルールやシャドウィングの仕様ともよくマッチしていて人道的でわかりやすいスコープとなっている。コードは非常に読みやすい(追いやすい)。これが仮にダイナミックなスコープだとすると、関数を適用したときに、どのような結果をもたらすかコードリーディングだけで判別しにくくなってしまう。高階関数とかこわくて使えない。言い換えると、関数プログラミングしやすい条件ともいえる。ここから、「続きはWebで」のぶぶん有名なアレ。null非許容型が欲しいなんて話はたびたび聞きます。いう話ではないんです。値を値にも変数にも使用しません。デフォルトで危険性を回避するように設計されています。例外的な場合を除いて、nullの使用はできる限り避けるよう言語設計されています。してもコンパイルエラーとなります。値を扱うことはあります。メソッド呼び出しからの戻り値または出力パラメーターを解釈する場合のいずれかしかありません。属性を使用して対応します。許容する型を明示的に定義することができます。使用すべきではありません。NullReferenceExceptionとなります。いずれかの関数を使用した場合に限られます。いえ、値がない状態というのをプログラミングで表現したいシーンはたくさんあります。そんなときに役立つのがオプション型で、これにより「値がないかもしれない」ということを型として明示することができます。計算不能や計算失敗などにより、実際の値が存在しない場合などに使えます。あることが型の情報として現れないことで。null参照によるエラーというのは実行してみるまで誰にも分からないからです。nullが来るかどうかの判定をプログラマーが正確に管理しなければならないこと意味します。これは実際難しいことです。null値を使用することなく安全に「値がない状態」を表すことができます。面白い(エキサイティングな)機能なのでご紹介します。」「わけがわからないよ。コード上であらゆる情報を安全に扱えるようにする仕組み。型プロバイダーの主目的はコンパイル時プログラミングではないものの、型のないものを扱う際に生じやすいしょーもないバグを未然に防ぐことができるソリューションと解釈することもできます。型のないものを安全に扱える世界があなたの手中にといったところです。ごむごむいろいろできそうです(オラワクワクしてきたぞ)でも、TypeProviderはDSLなどをメタプログラミングするためのものではないと、TypeProviderのドキュメントに書かれています。学習目的であればメタプログラミング目的の方がとっつきやすいかもしれませんので。導入するのがもっとも近道。TypeProviderを作る際に必要な便利部品がひととおり用意されている。スキーマが動的に変化することは想定されていないので、スキーマがコーディング中やプログラムの実行中に安定しているかということは、もちろん前提として必要。構造体だったりに対するマッピング。型システムと言っているのは、主に判別共用体やレコード型に対するマッピングを意味している。型システムの型を生成するのか、あるいはオブジェクト指向プログラミングになじみやすいような型を生成するのか、そのあたりはよく検討してデザインする必要がある。FsBulletMlでは実際に、XML(外部DSL)から判別共用体(型付き内部DSL)への安全なマッピングのためのTypeProvider提供しています。セッションでは、いちおう簡単なDemoだけ紹介しました。コンパイル時にメタデータからリアルタイムで型がつくられる。Studioとも連携しているので、インテリセンスも効くという感じ。こんな簡単なDemoからでも、「TypeProviderでなんか面白いことができそうだな!」ということが容易に想像できると思う。今回のDemoのような単純なものであれば少し勉強すれば、すぐに作れるようになりますが、ある程度複雑なものになると、ぐんと難しくなります。それは関数プログラミング的な側面で難しいという意味ではなく、メタプログラミングの側面として難しいという意味です。FSharp.Data等のライブラリのソースを読んで勉強する感じになるかと思います。github.comF#に限らずさまざまな言語の話も飛び交う感じの割とフリーダムなゆるい集まり。私も何度かお邪魔して楽しくすごさせていただいています。ほとんどF#を書いたことがないというような人でも気軽に参加していただける勉強会です。言語の発展に物申したい場合は有料会員になる感じだと思います。さんは、こちらのボードメンバーでもあります。他のプログラミング言語に比べてF#が特別難しいというようなことはありません(もちろん難しい部分も当然あります)。F#は高階関数が扱いやすく関数プログラミングがしやすい言語です。プログラミングのスタイルは自然と関数プログラミングに軸をおいたものとなります。F#って何に使えるんですか?等の質問をいただきますが、VBがC#とほとんど同じ場面で使えると同じように、ほとんどの場面で同じようにF#も使えます。F#を選択する理由があるとするならば、関数プログラミングのスタイルおよびそれによって享受できるメリットを重視するかしないかくらいのものです。それ以上でもそれ以下でもありません。関数プログラミングのスタイルを重視しないのであれば、選ぶ理由はないでしょう。現状、世間一般ではそれを重視しないのが多数派であり、人材の確保が難しかったりある程度学習コストが高いという側面があるので、選択肢としてあがることも少なく(んなもんで人材が増えないという悪循環)、結果「流行っていない」ということになります。実際間違いではないし、どちらかというと筋がよいことだと思うんだけど、それを必要としている人もいるししてない人もいるというのは理解できます。実際いまのところは(残念ながら)必要とされていない(らしい)ので、F#流行っていないということになります。良い言語(実際)ですが、今のところMSが推す気配なし!ということもあって、だいぶ闇は深いです。F#の人達は知ってるけど、MLな人は知らないとかあるかもしれないですし。10結局、25日に間に合いませんで。2014も合わせてどうぞ。この記事は非常に誰得でニッチな内容を扱います。ほとんどの場合役には立たないでしょう。らしい成分もあまりありませんので、まあ適当に流してください。簡単に導入することができます。Studio使いたい勢ということもあり、こちらWindows専用となっています。いうか、リポジトリ公開してますから、誰か適当にうまいことやっちゃってください。上の動画の内容は少し古いですが、概要は伝わるかと。Scriptを作成できます。ScriptをDLLにビルドすることができます(MSBuild利用)。F#(関数型プログラミング言語)でUnityのゲーム開発がしやすくなります。いわゆる、"作ろうと思えば作れるの知ってるけど、面倒くさくて誰もやらなかったことをやってみた系のツール"です。実際やるといろいろ大変。オープンソースヒロインのユニティちゃん(ユニティ・テクノロジーズ・ジャパン提供)をマスコットキャラクターに採用しました。ユニティちゃんの音声で時報やイベント、ビルド結果の通知を受けられるという、本来の目的とはまったく関係のない機能も提供しています。UniFSharpはUnityのEditor拡張です。Scriptを作成できます。ユニティちゃんの音声でビルド結果の通知する機能を提供しています。趣味で使う分にはフリーダム。Scriptが混ざってます)。ほとんどの部分(エディタだろうがゲームだろうが)を書くことができます。この記事では、UniFSharpが提供する機能および、それがどのように実装されているのかについて書きます。ここで紹介でもしないと、GitHubのリポジトリを誰も覗いてくれることもないでしょうし。ご利用の際は、まぁいろいろあると思います(お察し)。12この記事を読むその前に...むろほしりょうたさんの初心者がF#をUnityで使ってみた!という記事をオススメします。Scriptの作成Unityのエディタ拡張では、カスタムメニューを簡単に作ることができます。F#で実装する場合、Moduleに定義した関数にMenuItem属性を付けるとよいでしょう。UnityのEditorWindowは、ScriptableObjectがインスタンス化されたものです。ShowUtilityメソッドを実行すると、必ず手前に表示し続け、タブとして扱えないウィンドウを作れます。作る場合と基本的に同じです。Scriptを生成するという機能を提供しています。して認識させる必要があります。Projectウィンドウ上に表示されません。Scriptファイルの名前の編集が確定したタイミングで行うようにします。EndNameEditActionクラスを継承し、Actionメソッドをオーバーライドして実装します。ScriptをUnityEngine.Objectとして読み込み、ProjectWindowUtil.ShowCreatedAssetで、Projetウィンドウ上に表示させることができます。チェックしていたりという感じです。変な階層を作られると、.fsprojファイルがぶっ壊れて開けなくなっちゃいますからね。Folder機能を作った本人も何故駄目なのかわからないって言ってますね。F#コードのプレビューを表示するためには、カスタムエディタを作成します。Scriptを読み込んで表示するよう実装します。MSBuildでビルドするだけの簡単なお仕事です。これといって特筆すべきことはありません。誰かソースきれいにして。UniFSharpでは、ビルドの結果をユニティちゃんが通知してくれます。Scriptファイルを、Inspectorウィンドウにドラック&ドロップしGameObjectにComponentとして追加することはできません。Scriptファイルをドラッグ&ドロップしているかのような操作感覚を実現しています。Scriptファイルを読み取って、シンプルな正規表現でクラス名を抽出し、アセンブリからMonoBehaviourの派生クラスを検索する方法。コンパイラサービスを利用して、解析して厳密にクラス名を抽出する方法。前者は精度は低いが早い。後者は精度は高いが遅い。それぞれ一長一短がある。コンパイラサービスを利用する部分を除いては、またC#。Scriptファイルから名前空間を含むクラス名の探索はこんな感じ。Framework4以上です。Unityでこのアセンブリを読み込むことはできません。残念!!なのですが、ここで、Microsoftが提供しているILMergeという神ツールを使う(苦肉の策)ことにより、それを回避し実現してる(アッハイ)。作成することをサポートしたということは、つまり、IDEとの連携もサポートするってことだよね。内容が書き換わってくれないと、それぜーんぜん役に立たない。この実装がけっこー面倒くさかった...。こんな感じAssetを追加・削除・移動した際に独自の処理をしたい場合は、AssetPostprocessorを継承して適宜処理を実装する。Scriptがこの場合)には、OnPostprocessAllAssetsメソッドを実装する。.fsprojファイルをごにょごにょすることで、これを実現できる。Studio上でそのファイルをアクティブにする動作を実現するために、EnvDTEを利用した。25これはきな臭い...。UniFSharpがWindows専用であることが滲み出ているコードですね。はい(真顔)他のDLLに依存する型プロバイダーを作るFsBulletMLで型プロバイダーを提供するにあたって、実装はFsBulletML.CoreおよびFsBulletML.Parserに依存するようにしたい。FsBulletML.Coreは、XML形式のBulletMLをパースする機能を持っている。FsBulletML.Parserは、SXML形式とFSB形式をパースする機能を持っている。それぞれのDLLを参照してしまえば、ちょっと草植えておきますね型言語Grass型プロバイダーと同じようなノリで簡単に実装できるはずだ。実際、実装そのものは容易にできた。実行するとうまくいかない。依存対象のDLLを参照しただけではだめなのだ。型プロバイダーのコンパイルは通るが、利用時にエラーとなる。実行時には参照できないことが原因だ。参照した型プロバイダーを作る。型プロバイダーコンパイルが通るし一見良さそうに見えるが、この型プロバイダーを利用しようとすると以下のようになる。型プロバイダーの実行時に参照できていないためにこのようなエラーとなる。存在するパスを、型プロバイダーの探索対象にあらかじめ登録しておく必要がある。クラスのRegisterProbingFolderメソッドでこれを解決できる。このように実装することで、型プロバイダーと同じパスに存在するDLLが実行時に参照可能となる。他のNuGetパッケージに依存した型プロバイダーを作ってNuGetで配布するときのやり方FsBulletML.TypeProvidersは、FsBulletML.CoreおよびFsBulletML.ParserのNuGetパッケージに依存するかたちで配布したい。この場合、他のNuGetパッケージが展開されるフォルダのパスを考慮した実装が必要となる。良さそうな方法は、package.configのXMLを読み込んで参照するパスを解決する方法が考えられる。FsBulletML.TypeProvidersでは、下記のような感じで、型プロバイダーが依存するNuGetパッケージのパスを探索するよう実装することでこれを解決した。いうことで、FsBulletML.TypeProvidersリリースしました。言語サービスがそのプロバイダーを無効化するようにシグナルを通知することができる。Studio上でホストされている場合に限り、再度型チェックが行われる。これを利用して型プロバイダーが参照するファイルの更新チェックを実装することができる。(F#)のInvalidateメソッドを呼び出すように実装すればよい。FsBulletML.TypeProvidersでも実装しています。ソースはここにあります。最後に、@bleisさんのTypeProviderについて、勝手に補足で紹介されていた生成型の型プロバイダーのひじょーにシンプルな例についてご紹介。消去型のサンプル型が消えてますね。ILDASMで逆コンパイルした結果も見てみましょう。型が消去されています。これを生成型の型プロバイダーに書き直してみます。falseとすること。ProvidedAssemblyで一時アセンブリを作り、そのアセンブリにAddTypesで生成する型を登録することです。この例では、アセンブリ内に定義したPiyoクラスを継承する型を生成しています。ILDASMで逆コンパイルした結果を見てみましょう。Studio上でも確認ができたように、型が消去されずに、Piyoクラスを継承したHogeAクラスが型プロバイダーによって生成されていることが確認できます。30うほ!とても面白いアイデア。生成型の型プロバイダーだと確かにそういった構想の面白いブツが作れそうですね(wktk)。Provider)のちょっとしたアレコレを書いてみました。Toolsなのか他の拡張機能なのかわからないけど、型プロバイダーを書いたりデバッグしていると、割と頻繁になにかしらの拡張機能のエラーのダイアログがでてきてウザいですよ(激おこ)。Provider)のとりとめもない話。ほとんど内容はないよう。利用できる目玉機能のひとつ。Programming」なんて言われていました。」「わけがわからないよ。任意のメタデータを与えると、コンパイラがコンパイル時に"型のないもの"に"型を与えて"提供してくれる。それが型プロバイダー。等のIDEとも連携するということでメシウマ状態必至なわけ。型プロバイダーに与えられた場合、コンパイルエラーとなる(そのように実装している場合に限る)。型プロバイダーの主目的はコンパイル時プログラミングではないものの、型のないものを扱う際に生じやすいSHOUMONAIバグを未然に防ぐことができるソリューションと言うこともできる。型のないものを安全に扱える世界があなたの手中に的な。この世のあらゆるものに型を付けた男、型王タイプロジャー。彼の死に際に放った一言は人々を型へと駆り立てた。欲しけりゃくれてやる。この世の全ての型はここに集まる!」男達は型プロバイダーを作り夢を追い続ける。TypeProvider」くらいはチョロっとかじりました。作りたいオリジナルのネタもなくって(あるいは既に先駆者がいたりで)、なかなか触れる機会に恵まれまれずにコンニチに至ります(言い訳)。実装したいネタがどうこうというより、そもそも難しかったり取っつきにくかったりで手が出しずらいという説もある。FSharp.Data等のライブラリのソース嫁がデフォというなかなかに漢らしい感じだし。何か作りながら覚えようにも、予期せぬエラーとそのメッセージに悩まされることも多いし、デバッグ実行で地道に追っても原因がよくわからず途方に暮れるなんてこともあり...結構ハードルは高い。実際上級者向けではある(個人の感想)。ユーザーは利用者としてその恩恵を受けることができればいいよね。」くらいに割り切って押さえておくだけでもよいという代物かもしれない。14ごもっともすぎるご意見。汎用的で有用な型プロバイダーを自分で実装するような機会は、あまりないような気がする(便利そうなやつはもう既に誰かが作ってくれていることが多いし)。概要だけ把握しておいて、もし実装する機会があったらそのときじっくり調べながら頑張ればいいんじゃないだろうか。逆に言うと、型プロバイダーがわかったからって上級者にはなれません。がやまだかつてない程の盛り上がりがあったようです。そのイベントで@kos59125さんによるTypeProviderに関する発表があり、更に後日@bleisさんによる、TypeProviderについて、勝手に補足がありました。Togetterまとめで雰囲気だけ味わいました。触発されて何かしら型プロバイダーを作りたくなった。軽い気持ちで...、とりあえず役に立たない系型プロバイダーを作ってみた。6@moonmileさんにフィードバックを頂きました。ありがとうございます。TypeProviderはProvidedType.fs(か、StartarPack)を使えばいいということだけ覚えておけばあとはなんとか。13ゼロから自分で実装することも不可能ではありませんが...基本的にはこの方法しかないといっても過言ではないので、なにかしらのProvidedType.fs(の類)を使いましょう。役に立つ立たないは置いておいて勉強したい場合はとりあえずなんか作ってみる。ない場合は概要だけ抑えて華麗にスルーする。F#Tweet判別共用体を文字列として出力する際に、ケース識別子を宣言する型(判別共用体)の名前を含めたフルネームで文字列化したくなったときのお話。以下を実行すると次の出力結果を得られる。それを、以下のような感じに出力するようにしたい。次元のテキストベースの表示レイアウトを使用する場合に、型を表示する既定の方法を指定するために使用されます。プロパティ名は、オブジェクトそのものの代わりに評価および表示するプロパティを表します。これを使えば、型を表示する際のレイアウトを自由にカスタマイズすることができる。有効な値は"とあるが、F#2.0からF#3.1までは変更はない(F#2.0より前は仕様が異なる)。StructuredFormatDisplayAttribute。ライブラリのソースコード等を読んでたり、コンパイラのソースを見ていたりする人なら見覚えがあるかもしれないが、"%A"書式指定子の表示レイアウトをカスタマイズしたい場面はそんなに多くはないだろうし、そこそこマニアックな(割とどーでもいい)話題かもしれない。把握できていない可能性がある。「プログラミングF#」にはサラりと載っていたりする(!)。単純な例StructuredFormatDisplay属性を使った単純な例は以下のようになる(ここでは例として判別共用体を対象としているが、その限りではない)。出力結果は以下のようになる。FizzBuzzしてみる意味もなくFizzBuzzしてみます。出力結果この結果から、StructuredFormatDisplay属性を使って型の表示方法をカスタマイズしても、"%s"および"%O"書式指定子に影響を及ぼしていないことが確認できる。Object.ToString仮想メソッドが呼び出されるかたちになるので、判別共用体の場合は既定では上記のように型名が出力される。"%A"書式指定子を指定した場合と同じ結果が得られるようになる。ToStringを経由して表示する際にStructuredFormatDisplay属性を参照していたようだが、F#2.0以降はToStringメソッドを経由する場合にはこれを参照しないよう仕様が変更された。StructuredFormatDisplay属性で指定した{PropertyName}を実装していない場合ちょっと例を変えて、レコード型にしてみる。コンパイルエラーとなるわけでなく例外となるわけでなく、割と残念な感じの出力結果を得ることになる。コンパイルエラーにしてくれてもいいのにー。unions)について、型名も含めて文字列化するさて、本題。愚直に書いてみようStructuredFormatDisplay属性でマークし、表示をカスタマイズする実装を愚直に書き加える。以下の出力結果が得られる。PreText使おうぜあっ。ケース識別子を宣言する型(判別共用体)の名前は固定なので、この場合StructuredFormatDisplay属性のPreTextに集約できるんだったね。このTree<'T>判別共用体の場合だけに関して言えば、とりあえずこれで良さそうに見えるし、この方法を取れば他の判別共用体についても都度対応できそうだ。毎回個別に対応するなんてダルすぎる。汎用的にしたいよねー。リフレクションで汎用的に実装しようMicrosoft.FSharp.Reflectionを利用する。ワーイ、できたよーと、思ったけど、待って。本当は以下のようなレイアウトで表示したかったんだった(だった!)。んー、内容的には同じなのでそんなに大きな問題ではないんだけど、若干モヤッとする。既存の型(例えばOption<'T>型など)の、表示をカスタマイズしたい場合はどうすればよいのだろう?F#er諸兄、何かご存じであればアドバイス頂きたい。書式指定子における型の表示レイアウトのカスタマイズTweet広告を非表示にするもっと読むコメントを書く2013-12-20判別共用体で型付きDSL。弾幕記述言語BulletMLのF#実装、FsBulletML作りました。2013の20日目です。Usをちびちびとプレイ中。FF14のパッチ2.1が先日リリースされ、メインジョブ弱体化にもめげず引き続き光の戦士としてエオルゼアの平和を守り続けている今日この頃。はてなブログに引っ越してきて一発目(ブログデザイン模索中)です。気付けば半年もブログを書いていませんでした(テイタラク)。今年はあまり.NET関係の仕事に携わることができずに悶々としておりましたが、急遽C#の仕事が舞い込んできました。年末はいろいろとバタバタするものです。間ホテル暮らしなのでゲーム(据置機)できなくてつらいです。...多くのものを失ったように思います。アラフォーいい響きです(白目)。上の動画の弾幕は次のBulletml判別共用体で記述されています(MonoGameで動いています)。ActionFsBulletMLリリースしました弾幕記述言語BulletMLのF#実装、FsBulletMLを作りました。4.3では新たに2Dがサポートされたりで、少なからず需要がないこともないのかもしれず。NuGetに放流してみました(Beta版)。実際に使える(使われる)ライブラリに成長するかどうかはわかりません。詳しくはこちらをご覧ください。長健太氏が作りました。10年以上前ということになります。シンプルな記述で多彩な弾幕を表現することができ、有限オートマトン的に弾を管理しなくてもよいので楽チン。いうことで多くの人から注目を集めました。わたしが存在を知ったのはもう少し後のことですが、当時かなりインパクトを受けて感動したのを覚えています。本家BulletMLのパーサおよび処理系はJavaで実装されています。RELAX定義、DTD定義など弾幕定義自体の簡易的な仕様については公式に公開されているものの、弾幕の処理系の詳細については「ソース嫁」状態という非常に漢気溢れる感じになっています*1。かかわらず、多くの人によって様々な言語で移植/実装/改良されています。BulletMLのS式版(内部DSL)で、ひとつひとつの弾が継続になっているらしいです(あたまおかしい)。内部DSLも提供していて、enchant.js用、tmlib.js用のプラグインもあって、ブラウザで動く弾幕ゲーが簡単に作れるようになっているようです。特定の「何か」を達成するために、最適化された言語を作ることは簡単なことではありません。シンプルで且つ表現力が高くて実用的なドメイン固有言語を作る(デザインする)のはとても難しいことです。BulletMLはとてもよくデザインされていて面白くて魅力的なDSLだと思いました。DSLについて以前以下のような記事を書きました。F#3.0で加速する言語指向プログラミング(LOP)。コンピューテーション式はもはやモナドだけのための構文ではない!!!きっかけ今年は例年に比べてIT系勉強会に参加できませんでしたが、夏に「コード書こうぜ!」をスローガンとしたCode2013という合宿イベントに参加しました。その中で、座談会orセミナー形式で複数グループが集まってそれぞれが異なるテーマについて話をする形の「きんぎょばち」というコーナーがありまして、「パーサコンビネータを使った構文解析およびDSLの作成などについて勉強したいです。」というテーマがありました。関数型言語の話題なら少し話せます。ついてお話してきました。本当は教えてもらいたい側だったのですが...。イベントから帰ってきてから、「何かDSL書きたいなー」と漠然とした思いを持っていました。型付きの内部DSLとして表現できるようにしたらちょっと面白いんじゃあ?」という発想。アイディアとしては3年くらい前から持っていましたが、実装が面倒くさいことになりそうだったので行動に至らずでした。ゲーム開発の世界ではDSLや各ドメインエキスパートのための独自スクリプト言語などを開発/運用することは日常茶飯事で、そう珍しいことではないと風のうわさで聞いたことがあります。わたし自身は、仕事であれ趣味であれ、日頃のソフトウェア開発において本格的なDSLを設計したり実装したりする機会はほとんどありません。非常に興味のある分野/開発手法なので実際に何かを作って勉強してみたい。兼ねてから思っていました。良い練習になりそうだし、"評論家先生"というYAIBAに影響を受けたりで、重い腰を上げました(よっこらせ)。弾幕を判別共用体で書きたい(型付き内部DSL)・従来のXML形式での弾幕を再利用したい(外部DSL)・XML形式は書きにくいしちょっと古臭い。XMLとは異なる形式の外部DSLも利用できるようにしたい。要は、「内部DSLと複数の外部DSLを両立する。」ということをやってみたい。その辺りを最終的な目標にしました。Games)があるし、何を今さら感があるのも事実ですが、判別共用体による型付き内部DSLを提供するという点で若干のアドバンテージがあります。型付きの内部DSLが使えると何がうれしいって、弾幕を構築する際にF#の式がそのまま使えるということです。関数を組み合わせて自由に弾幕を組み立てることができるようになります。それってつまり、Bulletsmorphのようなアイディアも実装しやすくなる、と。「ちょ、構成ファイルの書式に今どきXMLなんてありえないでしょww」「yamlかjsonだろ」「つーか.rbで構成書くよねふつー」とかXMLのdisり大会やってみたい。6XMLのdisり大会。こちら結局どうなったんでしょう。́・_・`)DTD定義を判別共用体で表現するいにしえからの言い伝えによると、「判別共用体は、ドメイン知識をモデル化するための簡潔かつタイプセーフな方法である。DTD定義を内部DSLとして判別共用体で表現する。いうことについて考えてみたい。以前、こんなやり取りがありました。みたいに書けないわけで。泥臭くならざるを得ない。先の例は単純化したものでして。twitterではうまく状況を説明しにくいのですが、やりたいのはそういうことではないのです。確かにそんなに多くはないんですが、型に厳格目というか、ちょっとコッたことをやろうと思うと...。