<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>捨てられたブログ</title>
	<atom:link href="http://blog.recyclebin.jp/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.recyclebin.jp</link>
	<description>ウェブ空間に捨てられた一片のブログ</description>
	<lastBuildDate>Wed, 09 May 2012 11:31:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
<image>
  <link>http://blog.recyclebin.jp</link>
  <url>http://blog.recyclebin.jp/favicon.ico</url>
  <title>捨てられたブログ</title>
</image>
		<item>
		<title>Apache で音楽ストリーミングサーバー</title>
		<link>http://blog.recyclebin.jp/archives/2524</link>
		<comments>http://blog.recyclebin.jp/archives/2524#comments</comments>
		<pubDate>Sat, 14 Apr 2012 16:00:48 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[Tip]]></category>
		<category><![CDATA[サーバー]]></category>
		<category><![CDATA[Apache]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2524</guid>
		<description><![CDATA[mod_musicindex は音楽ファイルのストリーミングのための Apache モジュールです。 インストール Ubuntu の場合は標準リポジトリに入っているので apt でインストールできます。 必要に応じてコー [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.parisc-linux.org/~varenet/musicindex/"  class="liexternal aga aga_3">mod_musicindex</a> は音楽ファイルのストリーミングのための Apache モジュールです。</p>
<p><span id="more-2524"></span></p>
<h3>インストール</h3>
<p>Ubuntu の場合は標準リポジトリに入っているので <code>apt</code> でインストールできます。</p>
<pre class="brush: bash; title: ; notranslate">
sudo aptitude install libapache2-mod-musicindex
sudo a2enmod musicindex
</pre>
<p>必要に応じてコーデックをインストールします。対応コーデックは<a href="http://www.parisc-linux.org/~varenet/musicindex/doc/html/index.html"  class="liexternal aga aga_4">ドキュメント</a>を参照してください。</p>
<pre class="brush: bash; title: ; notranslate">
sudo aptitude install libmp4v2-0
</pre>
<h3>設定</h3>
<p>通常の Apache の設定通り，ディレクトリへのアクセスを許可します。</p>
<pre class="brush: plain; title: ; notranslate">
Alias /music /var/music
&lt;Directory /var/music&gt;
   Options Indexes MultiViews FollowSymLinks
   AllowOverride Indexes
   Order allow,deny
   allow from all
&lt;/Directory&gt;
</pre>
<p>上記設定ではすべての人がアクセスできるようになっているので，必要に応じてアクセス制限をしましょう。</p>
<p>音楽ディレクトリ (ここでは /var/music) 内の .htaccess ファイルか，上記の Directory ディレクティブ内に musicindex の設定を追記します。</p>
<pre class="brush: plain; title: ; notranslate">
MusicIndex      On +Stream +Download +Search -Rss -Tarball
MusicSortOrder  album disc track artist title length bitrate freq filetype filename uri
MusicFields     title artist album length bitrate
MusicPageTitle  Title
MusicDefaultCss musicindex.css
MusicDirPerLine 3
</pre>
<p>意味はだいたい見た感じのままです。最低限 <code>MusicIndex On</code> があれば， musicindex が動きます。</p>
<h3>Apache の再起動</h3>
<p>再起動したら完成です。 http://www.example.com/music にアクセスしてストリーミングを楽しみます。</p>
<pre class="brush: bash; title: ; notranslate">
sudo /etc/init.d/apache2 restart
</pre>
<h3>その他</h3>
<p>キャッシュシステムに MySQL が使えたり， URL パラメーターを与えると RSS や PODCAST を吐いたり， CD カバーの画像を指定できたりするようです。詳しくは <a href="http://www.parisc-linux.org/~varenet/musicindex/README"  class="liexternal aga aga_5">README</a> ファイルを読みましょう。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2524/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>.NET の動作しているプラットフォームを取得</title>
		<link>http://blog.recyclebin.jp/archives/2512</link>
		<comments>http://blog.recyclebin.jp/archives/2512#comments</comments>
		<pubDate>Tue, 10 Apr 2012 11:29:44 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[Tip]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2512</guid>
		<description><![CDATA[.NET Framework が動作するプラットフォームを取得するには System.Environment.OSVersion を取得すれば良いように思います。しかし以下のコードを Mac OS X で動かすと，期待す [...]]]></description>
			<content:encoded><![CDATA[<p>.NET Framework が動作するプラットフォームを取得するには <a href="http://msdn.microsoft.com/ja-jp/library/system.environment.osversion.aspx"  class="liexternal aga aga_9">System.Environment.OSVersion</a> を取得すれば良いように思います。しかし以下のコードを Mac OS X で動かすと，期待する結果を得られません。</p>
<pre class="brush: csharp; title: ; notranslate">
var platform = Environment.OSVersion.Platform;
Console.WriteLine(platform == PlatformID.MacOSX);  // false
</pre>
<p>実は Mac OS X では <code>platform</code> には <code>PlatformID.Unix</code> になります<sup>[<a href="http://blog.recyclebin.jp/archives/2512#footnote_0_2512"  id="identifier_0_2512" class="footnote-link footnote-identifier-link" title="Bug 515570 - System.Environment.OSVersion.Platform returns wrong result on Mac OS X">a</a>]</sup>。</p>
<p>苦肉の策ではありますが， UNIX 系 OS に標準で搭載されている <a href="https://bugzilla.novell.com/show_bug.cgi?id=515570#c5"  class="liexternal aga aga_10"><code>uname</code> を用いて OS を調べる</a>ことができます<sup>[<a href="http://blog.recyclebin.jp/archives/2512#footnote_1_2512"  id="identifier_1_2512" class="footnote-link footnote-identifier-link" title="リンク先では -a オプションと書いてありますが， -s オプション (オプションなしと同じ) で十分だとます。">b</a>]</sup>。</p>
<pre class="brush: csharp; title: ; notranslate">
var platform = Environment.OSVersion.Platform;
if (platform != PlatformID.Unix)
{
   return platform;
}
using (var uname = new Process())
{
   uname.StartInfo.FileName = &quot;uname&quot;;
   uname.StartInfo.Arguments = &quot;-s&quot;;
   uname.StartInfo.RedirectStandardOutput = true;
   uname.StartInfo.UseShellExecute = false;
   uname.Start();
   var kernelName = uname.StandardOutput.ReadLine();
   uname.WaitForExit();
   return kernelName == &quot;Darwin&quot; ? PlatformID.MacOSX : PlatformID.Unix;
}
</pre>
<p>カーネルの名前が Darwin ならば Mac OS X，そうでなければその他の UNIX であるとしています。 <code>PATH</code> が変更されていたら例外が投げられるなどいろいろ問題がありますが，とりあえずうまくいくと思います。<br />
<h3>脚注</h3>
<ol class="footnotes">
<li id="footnote_0_2512" class="footnote"><a href="https://bugzilla.novell.com/show_bug.cgi?id=515570"  class="liexternal aga aga_11">Bug 515570 - System.Environment.OSVersion.Platform returns wrong result on Mac OS X</a></li>
<li id="footnote_1_2512" class="footnote">リンク先では <code>-a</code> オプションと書いてありますが， <code>-s</code> オプション (オプションなしと同じ) で十分だとます。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2512/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C# のジェネリックで Enum/Delegate 制約を使う</title>
		<link>http://blog.recyclebin.jp/archives/2499</link>
		<comments>http://blog.recyclebin.jp/archives/2499#comments</comments>
		<pubDate>Sat, 31 Mar 2012 07:17:21 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[Tip]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[F#]]></category>
		<category><![CDATA[MSIL]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2499</guid>
		<description><![CDATA[C# のジェネリック型制約には大きな制限があります。それは制約する型に System.Delegate や System.Enum が使えないということです。 F# や Nemerle といった，ジェネリックの制約型に制 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://msdn.microsoft.com/ja-jp/library/bb384067.aspx"  class="liexternal aga aga_16">C# のジェネリック型制約</a>には大きな制限があります。それは制約する型に <code>System.Delegate</code> や <code>System.Enum</code> が使えないということです。 F# や Nemerle といった，ジェネリックの制約型に制限がない別の言語を用いるという選択肢も当然考えられますが，可能な限り C# だけで解決したいということもあるかもしれません。</p>
<p>とは言っても C# でできないから困ってるのであって，本当に C# だけで解決するのは難しいです。そこでもう少し低レベルな MSIL を使って解決しましょう。</p>
<p><span id="more-2499"></span></p>
<h3>準備</h3>
<p><a href="http://visualstudiogallery.msdn.microsoft.com/44034a7b-143d-4b51-b7bc-99aa656ba137"  class="liexternal aga aga_17">IL Support</a> という Visual Studio の拡張を利用します。この拡張は， C# や F# のプロジェクトで MSIL を利用するための補助機能が含まれます。</p>
<p>IL Support は，具体的には一部のコードを宣言のみで実装せずにコンパイルし，それを逆コンパイルした後に IL コードとマージして再度コンパイルをする，という手法をとっているようです。 Visual Studio の無償版ではおそらく拡張機能は使えないので IL Support は利用できませんが，同様の考え方で同じことが実現できるはずです<sup>[<a href="http://blog.recyclebin.jp/archives/2499#footnote_0_2499"  id="identifier_0_2499" class="footnote-link footnote-identifier-link" title="各言語のコンパイラに加え， IL アセンブラ (ilasm) と IL 逆アセンブラ (ildasm) を使います。">a</a>]</sup>。</p>
<h3>プロジェクトの作成</h3>
<p>IL Support をインストールして再起動すると，プロジェクトテンプレートに IL Support プロジェクトが追加されています。例えばクラスライブラリプロジェクトを作成すると，次のようなファイルが追加されます。</p>
<pre class="brush: csharp; title: ; notranslate">
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;

namespace Library1
{
   public class Class1
   {
      [MethodImpl(MethodImplOptions.ForwardRef)]
      public extern int Square(int number);
   }
}
</pre>
<pre class="brush: plain; title: ; notranslate">
.class public Library1.Class1
{
   .method public int32 Square(int32 number) cil managed
   {
      .maxstack 2
      ldarg.1
      dup
      mul
      ret
   }
}
</pre>
<p>見て想像できるように， <code>Square</code> というメソッドの中身を IL で記述することができます。 IL レベルではジェネリック型制約に <code>System.Delegate</code> や <code>System.Enum</code> が使えるので，このような制約が必要な部分を IL で書いてやれば良いわけです。ちなみに <code>extern</code> で宣言する部分は IL の宣言とマッチしている必要はありません。 IL の方が優先されるので， C# でジェネリック型制約が書けないので宣言ができない，という心配はありません。というか <code>extern</code> の宣言は無くても良いみたいです。</p>
<p>IL を直接書ける人は少数派だと思うので，いったん制約を甘くしたプロトタイプのコードを記述してコンパイルし， ildasm で逆アセンブルした IL コードを修正するか，あるいは最初に述べたような制限のない言語で記述してコンパイル，逆コンパイルした IL コードをコピペする，という方法が容易だと思います。</p>
<h3>他の使い方</h3>
<p>IL Support は F# プロジェクトサポートもあるので， F# で <code>family</code> のアクセシビリティ (C# の <code>protected</code>) を使うこともできます。これで C# と F# がもっと仲良しになれる気がします。<br />
<h3>脚注</h3>
<ol class="footnotes">
<li id="footnote_0_2499" class="footnote">各言語のコンパイラに加え， IL アセンブラ (<a href="http://msdn.microsoft.com/ja-jp/library/496e4ekx.aspx"  class="liexternal aga aga_18">ilasm</a>) と IL 逆アセンブラ (<a href="http://msdn.microsoft.com/ja-jp/library/f7dy01k1.aspx"  class="liexternal aga aga_19">ildasm</a>) を使います。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2499/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>NemerleUnit で単体テスト</title>
		<link>http://blog.recyclebin.jp/archives/2486</link>
		<comments>http://blog.recyclebin.jp/archives/2486#comments</comments>
		<pubDate>Sun, 04 Mar 2012 21:48:30 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[Nemerle]]></category>
		<category><![CDATA[NUnit]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2486</guid>
		<description><![CDATA[NemerleUnit は NUnit を用いた単体テスト用のマクロです。 NemerleUnit を使うと自然言語のように単体テストを記述することが可能になります。 NemerleUnit.dll のコンパイル Nem [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://nemerle.org/NemerleUnit"  class="liexternal aga aga_23">NemerleUnit</a> は <a href="http://nunit.org/"  class="liexternal aga aga_24">NUnit</a> を用いた単体テスト用のマクロです。 NemerleUnit を使うと自然言語のように単体テストを記述することが可能になります。</p>
<p><span id="more-2486"></span></p>
<h3>NemerleUnit.dll のコンパイル</h3>
<p>NemerleUnit は zip や msi 形式で配布されるアセンブリ群の中に含まれていないので，自前でコンパイルしてやる必要があります。 <a href="https://github.com/rsdn/nemerle/blob/master/tools/nemerle-unit/src/macros/macros.n"  class="liexternal aga aga_25">NemerleUnit のソースコード</a>はチェンジセット 430eb4a78f 時点で Nemerle 1.1.372.0-RC の Nemerle.Compiler API に対応していないので，以下の修正を加える必要があります。</p>
<pre class="brush: nemerle; title: ; notranslate">
// 修正前
def mods = AttributesAndModifiers(NemerleModifiers.Public, attrs);
// 修正後
def mods = Modifiers(NemerleAttributes.Public, attrs);
</pre>
<p>修正したら以下のようにコンパイルできます。</p>
<pre class="brush: plain; title: ; notranslate">
ncc /t:library /out:NemerleUnit.dll /r:nunit.framework.dll /r:Nemerle.Compiler.dll /i macros.n
</pre>
<h3>使う</h3>
<p>NemerleUnit 名前空間を <code>using</code> するだけで OK です。コンパイル時には NemerleUnit.dll と nunit.framework.dll を参照に指定します。</p>
<p>公式ページにある通り，以下のように記述できます。インデント構文を使った方が自然言語らしく表現できます。</p>
<pre class="brush: nemerle; title: ; notranslate">
#pragma indent

using NemerleUnit

setup
   def abc = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]

teardown
   ()

test &quot;length of an empty list&quot;
   assert [].Length equals 0

test &quot;length of a three element list&quot;
   assert abc.Length equals 3

test &quot;equals&quot;
   assert abc equals [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;]
   assert abc does not equal [&quot;c&quot;, &quot;b&quot;, &quot;a&quot;]

test &quot;contains&quot;
   assert abc.Contains(&quot;a&quot;)
   assert abc.Contains(&quot;b&quot;)
   assert abc.Contains(&quot;c&quot;)
</pre>
<p>通常の構文で書いた場合は以下のようになります。</p>
<pre class="brush: nemerle; title: ; notranslate">
using NemerleUnit;

setup
{
   def abc = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
}

teardown
{
   ();
}

test &quot;length of an empty list&quot;
{
   assert [].Length equals 0;
}

test &quot;length of a three element list&quot;
{
   assert abc.Length equals 3;
}

test &quot;equals&quot;
{
   assert abc equals [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;];
   assert abc does not equal [&quot;c&quot;, &quot;b&quot;, &quot;a&quot;];
}

test &quot;contains&quot;
{
   assert abc.Contains(&quot;a&quot;);
   assert abc.Contains(&quot;b&quot;);
   assert abc.Contains(&quot;c&quot;);
}
</pre>
<p>上記のソースコードをコンパイルしてできたアセンブリを NUnit ランナーで読み込んでやると，以下のようになります。</p>
<p><img src="http://blog.recyclebin.jp/wp-content/uploads/2012/03/NemerleUnit.png" alt="" title="NemerleUnit" width="512" height="330" class="aligncenter size-full wp-image-2489" /></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2486/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nemerle のブロック</title>
		<link>http://blog.recyclebin.jp/archives/2481</link>
		<comments>http://blog.recyclebin.jp/archives/2481#comments</comments>
		<pubDate>Mon, 27 Feb 2012 15:12:25 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[Nemerle]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2481</guid>
		<description><![CDATA[整数リストの中に平方数が含まれるか，というお題を Nemerle で 3 通りの方法で書いてみました。 squareAnyFunctional はパターンマッチングによる関数型的な書き方， squareAnyProced [...]]]></description>
			<content:encoded><![CDATA[<p>整数リストの中に平方数が含まれるか，というお題を Nemerle で 3 通りの方法で書いてみました。</p>
<p><span id="more-2481"></span></p>
<pre class="brush: nemerle; title: ; notranslate">
using System.Math;
using Nemerle.Imperative;

def isSquare(x : int)
{
   Sqrt(x) % 1 == 0;
}

def squareAnyFunctional(values)
{
   match (values)
   {
      | [] =&gt; false;
      | x :: xs =&gt; if (isSquare(x)) true
                   else squareAnyFunctional(xs);
   }
}

def squareAnyProcedural(values)
{
   foreach (x in values)
   {
      when (isSquare(x))
      {
         return true;
      }
   }
   false;
}

def squareAnyLabeledBlock(values)
{
   ret:
   {
      foreach (x in values)
      {
         when (isSquare(x))
         {
            ret(true);
         }
      }
      false;
   }
}
</pre>
<p><code>squareAnyFunctional</code> はパターンマッチングによる関数型的な書き方， <code>squareAnyProcedural</code> は普通の手続き型的な書き方です。 Nemerle 的に面白いのは 3 つ目の <code>squareAnyBlock</code> でしょう。ブロックにラベルを付けて，そのラベル付きブロックが返す値が何であるかを明示的に示すことが可能です。やっていることは手続き型的書き方と変わりませんが，ブロックが値を持つということを意識して書くことができるのが良いと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2481/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>R の関数の引数の数を得る</title>
		<link>http://blog.recyclebin.jp/archives/2471</link>
		<comments>http://blog.recyclebin.jp/archives/2471#comments</comments>
		<pubDate>Fri, 10 Feb 2012 16:47:02 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[Tip]]></category>
		<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[R]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2471</guid>
		<description><![CDATA[args 関数を使うことで，関数の引数リストを取得することができます。 ここで得られる結果はクロージャオブジェクトなので， formals 関数により，リストオブジェクトにすることができます。 リストなので， lengt [...]]]></description>
			<content:encoded><![CDATA[<p><code>args</code> 関数を使うことで，関数の引数リストを取得することができます。</p>
<pre class="brush: r; title: ; notranslate">
args(sqrt)
</pre>
<p>ここで得られる結果はクロージャオブジェクトなので， <code>formals</code> 関数により，リストオブジェクトにすることができます。</p>
<pre class="brush: r; title: ; notranslate">
formals(args(sqrt))
</pre>
<p>リストなので， <code>length</code> 関数により引数の数を得ることができます<sup>[<a href="http://blog.recyclebin.jp/archives/2471#footnote_0_2471"  id="identifier_0_2471" class="footnote-link footnote-identifier-link" title="ただし， ... は 1 つの引数として扱われます。">a</a>]</sup>。</p>
<pre class="brush: r; title: ; notranslate">
length(formals(args(sqrt)))
</pre>
<p>これを用いて，例えば，特定の名前空間に存在するすべての関数の引数の数を取得したい場合は次のようにできます。</p>
<pre class="brush: r; title: ; notranslate">
e &lt;- asNamespace(&quot;stats&quot;)
exports &lt;- sapply(ls(envir=e), get, envir=e)
functions &lt;- exports[sapply(exports, is.function)]
sapply(functions, function(f) length(formals(args(f))))
</pre>
<p>結果は stats 名前空間に公開された関数の引数の個数の名前付きベクトルです。ジェネリック関数のように重複もありますが，これで引数の個数の分布を調べても面白いと思います。<br />
<h3>脚注</h3>
<ol class="footnotes">
<li id="footnote_0_2471" class="footnote">ただし， <code>...</code> は 1 つの引数として扱われます。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2471/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nemerle で Brainfuck をインラインで実行</title>
		<link>http://blog.recyclebin.jp/archives/2463</link>
		<comments>http://blog.recyclebin.jp/archives/2463#comments</comments>
		<pubDate>Fri, 03 Feb 2012 14:45:42 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[Brainfuck]]></category>
		<category><![CDATA[Nemerle]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2463</guid>
		<description><![CDATA[前回は Nemerle で Brainfuck のパーサーを書いて普通に実行しました。今回は Nemerle の強力なマクロ機能を利用して，インラインで Brainfuck のソースコードを実行してみます。 前回のままで [...]]]></description>
			<content:encoded><![CDATA[<p><a href="/archives/2449" class="liinternal">前回</a>は Nemerle で Brainfuck のパーサーを書いて普通に実行しました。今回は Nemerle の強力なマクロ機能を利用して，インラインで Brainfuck のソースコードを実行してみます。</p>
<p><span id="more-2463"></span></p>
<p>前回のままでも良いのですが，最初に Brainfuck の実行環境である仮想マシンのクラスを作成します。</p>
<pre class="brush: nemerle; title: ; notranslate">
public class BrainfuckMachine
   invariant 0 &lt;= pointer &amp;&amp; pointer &lt; memory.Length
{
   private memory : array[char];
   private mutable pointer : int;

   public this(memorySize = 64 : int)
      requires memorySize &gt; 0
         otherwise throw ArgumentOutOfRangeException(&quot;memorySize&quot;)
   {
      memory = array (memorySize);
   }

   public Initialize() : void
   {
      Array.Clear(memory, 0, memory.Length);
      pointer = 0;
   }

   public Execute(source : string) : void
   {
      def parser = BrainfuckParser();
      match (parser.Parse(source))
      {
         | option.Some(commands) =&gt;
               foreach (c in commands)
               {
                  Proceed(c);
               }
         | option.None =&gt; throw FormatException();
      }
   }

   private Proceed(command : BrainfuckExpression) : void
   {
      match (command)
      {
         | BrainfuckExpression.MoveRight =&gt; ++pointer;
         | BrainfuckExpression.MoveLeft =&gt; --pointer;
         | BrainfuckExpression.Increment =&gt; ++memory[pointer];
         | BrainfuckExpression.Decrement =&gt; --memory[pointer];
         | BrainfuckExpression.Get =&gt; memory[pointer] = ReadKey(true).KeyChar;
         | BrainfuckExpression.Put =&gt; Write(memory[pointer]);
         | BrainfuckExpression.Loop as loop =&gt;
               while (memory[pointer] != 0)
               {
                  foreach (c in loop.Body)
                  {
                     Proceed(c);
                  }
               }
         | _ =&gt; throw InvalidEnumArgumentException();
      }
   }
}
</pre>
<p>このクラスを用いて，マクロを使わずに普通に Brainfuck のソースコードを実行すると次のようになります。</p>
<pre class="brush: nemerle; title: ; notranslate">
def machine = BrainfuckMachine();
machine.Execute(source);
</pre>
<p>さて，マクロの登場です。 Nemerle ではマクロを用いて自由に構文を拡張することができます。例えば次のように構文を拡張できます。。</p>
<pre class="brush: nemerle; title: ; notranslate">
bf(source);
bf[256](source);  // 仮想マシンのメモリーサイズを指定
</pre>
<p>マクロによる構文の拡張は単純で，次のように記述してやります。</p>
<pre class="brush: nemerle; title: ; notranslate">
macro BrainfuckInlineExecution(memorySize, source)
syntax (&quot;bf&quot;, Optional(&quot;[&quot;, memorySize, &quot;]&quot;), &quot;(&quot;, source, &quot;)&quot;)
{
   def memorySize = if (memorySize == null) &lt;[ 64 ]&gt; else memorySize;
   &lt;[
      def machine = BrainfuckMachine($memorySize);
      machine.Execute($source);
   ]&gt;
}
</pre>
<p><code>syntax</code> で構文のマクロを作成することができます。 <code>Optional</code> で指定した構文は省略可能になります。ここでは Brainfuck を実行する仮想マシンのメモリーサイズを省略できるようになっています。</p>
<p>Nemerle だと，本当に簡単に言語内言語が実装できてしまうのですね。</p>
<h3>ソースコード</h3>
<p><a href="https://bitbucket.org/kos59125/nemerle-brainfuck"  class="liexternal aga aga_27">ソースコードを Bitbucket にアップロードしています</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2463/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nemerle で Brainfuck の PEG parser を作る</title>
		<link>http://blog.recyclebin.jp/archives/2449</link>
		<comments>http://blog.recyclebin.jp/archives/2449#comments</comments>
		<pubDate>Thu, 02 Feb 2012 03:30:46 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[雑感]]></category>
		<category><![CDATA[Brainfuck]]></category>
		<category><![CDATA[Nemerle]]></category>
		<category><![CDATA[PEG]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2449</guid>
		<description><![CDATA[Nemerle には標準で PEG のパーサージェネレーターのライブラリが付属しています。それを使って Brainfuck の単純なパーサーを書いてみます。 まず Brainfuck の構文を表す variant[a]  [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://nemerle.org/"  class="liexternal aga aga_33">Nemerle</a> には標準で <a href="http://ja.wikipedia.org/wiki/%E8%A7%A3%E6%9E%90%E8%A1%A8%E7%8F%BE%E6%96%87%E6%B3%95"  rel="nofollow" class="liwikipedia aga aga_34">PEG</a> のパーサージェネレーターのライブラリが付属しています。それを使って <a href="http://ja.wikipedia.org/wiki/Brainfuck"  rel="nofollow" class="liwikipedia aga aga_35">Brainfuck</a> の単純なパーサーを書いてみます。</p>
<p><span id="more-2449"></span></p>
<p>まず Brainfuck の構文を表す variant<sup>[<a href="http://blog.recyclebin.jp/archives/2449#footnote_0_2449"  id="identifier_0_2449" class="footnote-link footnote-identifier-link" title="F# の判別共用体に相当するものだと思います。">a</a>]</sup> を定義します。</p>
<pre class="brush: nemerle; title: ; notranslate">
using System.Collections.Generic;

variant BrainfuckExpression
{
   | MoveRight
   | MoveLeft
   | Increment
   | Decrement
   | Put
   | Get
   | BeginLoop
   | EndLoop
   | Loop { Begin : BeginLoop;
            Body : List[BrainfuckExpression];
            End : EndLoop; }
}
</pre>
<p>次にパーサーです。 <code>PegGrammerAttribute</code> に直接 PEG の文法を放り込んでやり，それぞれの実装をクラス内で定義やるだけです。文法と実装がマッチしていなければコンパイルエラーになります。</p>
<p>簡単のために，改行を含む空白文字やコメントを一切許容しない，もっとも単純な文法を定義します。</p>
<pre class="brush: nemerle; title: ; notranslate">
using System;
using System.Collections.Generic;
using Nemerle.Peg;

[PegGrammar(Options = EmitDebugSources, Commands,
grammar
{
   SingleCommand : BrainfuckExpression = '&gt;' / '&lt;' / '+' / '-' / ',' / '.';
   BeginLoop : BrainfuckExpression = '[';
   EndLoop : BrainfuckExpression = ']';
   Loop : BrainfuckExpression = BeginLoop Commands* EndLoop;
   Commands : List[BrainfuckExpression] = (Loop / SingleCommand)*;
})]
class BrainfuckParser
{
   SingleCommand(token : NToken) : BrainfuckExpression
   {
      match (this._parsingSource.OriginalText[token.StartPos])
      {
         | '&gt;' =&gt; BrainfuckExpression.MoveRight();
         | '&lt;' =&gt; BrainfuckExpression.MoveLeft();
         | '+' =&gt; BrainfuckExpression.Increment();
         | '-' =&gt; BrainfuckExpression.Decrement();
         | ',' =&gt; BrainfuckExpression.Get();
         | '.' =&gt; BrainfuckExpression.Put();
         | _ =&gt; throw NotSupportedException();
      }
   }

   BeginLoop(_ : NToken) : BrainfuckExpression
   {
      BrainfuckExpression.BeginLoop();
   }

   EndLoop(_ : NToken) : BrainfuckExpression
   {
      BrainfuckExpression.EndLoop();
   }

   Loop(begin : BrainfuckExpression, body : List[List[BrainfuckExpression]], end : BrainfuckExpression) : BrainfuckExpression.Loop
   {
      BrainfuckExpression.Loop(begin :&gt; BrainfuckExpression.BeginLoop,
                               body[0],
                               end :&gt; BrainfuckExpression.EndLoop);
   }

   Commands(commands : List[BrainfuckExpression]) : List[BrainfuckExpression]
   {
      commands;
   }
}
</pre>
<p>これだけで Brainfuck のパーサーが完成です。小難しいことはすべて勝手にやってくれます。なお，コンパイルする際には， Nemerle.Peg.dll と Nemerle.Peg.Macros.dll を参照に加える必要があります。</p>
<p>実際に使う際は，普通にインスタンスを生成して <code>Parse</code> メソッドを呼ぶだけです。パースに成功すれば <code>option.Some</code> が，失敗すれば <code>option.None</code> が返ってきます。</p>
<pre class="brush: nemerle; title: ; notranslate">
using System;
using System.Console;
using System.ComponentModel;
using Nemerle.Assertions;

module Program
{
   Main() : void
   {
      // Hello, world!
      def source = &quot;+++++++++[&gt;++++++++&gt;+++++++++++&gt;+++++&lt;&lt;&lt;-]&gt;.&gt;++.+++++++..+++.&gt;-.------------.&lt;++++++++.--------.+++.------.--------.&gt;+.&quot;;
      _ = Execute(source);
   }

   Execute(source : string, memorySize = 0x1000 : int) : array[char]
      requires source != null
         otherwise throw ArgumentNullException(&quot;source&quot;)
      requires memorySize &gt; 0
         otherwise throw ArgumentOutOfRangeException(&quot;memorySize&quot;)
      ensures value != null
   {
      def parser = BrainfuckParser();
      def memory = array (memorySize);
      mutable pointer = 0;
      match (parser.Parse(source))
      {
         | option.Some(commands) =&gt;
              foreach (c in commands)
              {
                 Proceed(c, memory, ref pointer);
              }
         | option.None =&gt; throw FormatException();
      }
      memory;
   }

   Proceed(command : BrainfuckExpression, memory : array[char], pointer : ref int) : void
      requires memory != null
         otherwise throw ArgumentNullException(&quot;memory&quot;)
      requires 0 &lt;= pointer &amp;&amp; pointer &lt; memory.Length
         otherwise throw ArgumentOutOfRangeException(&quot;pointer&quot;)
      ensures 0 &lt;= pointer &amp;&amp; pointer &lt; memory.Length
         otherwise throw OutOfMemoryException()
   {
      match (command)
      {
         | BrainfuckExpression.MoveRight =&gt; ++pointer;
         | BrainfuckExpression.MoveLeft =&gt; --pointer;
         | BrainfuckExpression.Increment =&gt; ++memory[pointer];
         | BrainfuckExpression.Decrement =&gt; --memory[pointer];
         | BrainfuckExpression.Get =&gt; memory[pointer] = ReadKey(true).KeyChar;
         | BrainfuckExpression.Put =&gt; Write(memory[pointer]);
         | BrainfuckExpression.Loop as loop =&gt;
              while (memory[pointer] != 0)
              {
                 foreach (c in loop.Body)
                 {
                    Proceed(c, memory, ref pointer);
                 }
              }
         | _ =&gt; throw InvalidEnumArgumentException();
      }
   }
}
</pre>
<p>このコードだけでも， Nemerle の特徴が随所に表れている気がします。</p>
<h3>感想</h3>
<p>Nemerle は Java 界隈で言うところの Scala 的な位置づけの言語だと思います。 C# のようなメジャーな言語とのギャップも小さく，かつ関数型の強力な表現力も持っています。マクロによる構文拡張はチート級です<sup>[<a href="http://blog.recyclebin.jp/archives/2449#footnote_1_2449"  id="identifier_1_2449" class="footnote-link footnote-identifier-link" title="例えばコード中の foreach や while は実はマクロです。">b</a>]</sup>。</p>
<p>.NET の言語としては Visual Studio によるサポートが弱いのがネックですが<sup>[<a href="http://blog.recyclebin.jp/archives/2449#footnote_2_2449"  id="identifier_2_2449" class="footnote-link footnote-identifier-link" title="Nemerle 1.1 RC では Visual Studio 2010 用の拡張も含まれています。しかし，プロジェクトとして扱えたりエディターでシンタックスハイライトができるくらいで，リファクタリングまわりはまったく使い物にならず，インテリセンスも弱いです。">c</a>]</sup>，とても書きやすい言語だと思います。</p>
<h3>ソースコード</h3>
<p><a href="https://bitbucket.org/kos59125/nemerle-brainfuck"  class="liexternal aga aga_36">ソースコードを Bitbucket にアップロードしています</a>。</p>
<h3>参考文献</h3>
<ul>
<li><a href="http://groups.google.com/group/nemerle-en/browse_thread/thread/ea5e098cf9b27423"  class="liexternal aga aga_37">Nemerle.PEG - Nemerle Forum</a></li>
</ul>
<h3>脚注</h3>
<ol class="footnotes">
<li id="footnote_0_2449" class="footnote">F# の判別共用体に相当するものだと思います。</li>
<li id="footnote_1_2449" class="footnote">例えばコード中の <code>foreach</code> や <code>while</code> は実はマクロです。</li>
<li id="footnote_2_2449" class="footnote">Nemerle 1.1 RC では Visual Studio 2010 用の拡張も含まれています。しかし，プロジェクトとして扱えたりエディターでシンタックスハイライトができるくらいで，リファクタリングまわりはまったく使い物にならず，インテリセンスも弱いです。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2449/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>イベント駆動で組み合わせを列挙する</title>
		<link>http://blog.recyclebin.jp/archives/2429</link>
		<comments>http://blog.recyclebin.jp/archives/2429#comments</comments>
		<pubDate>Tue, 10 Jan 2012 16:13:33 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2429</guid>
		<description><![CDATA[組み合わせの列挙を行いたいということはしばしば起こります。例えば 0, 1, 2, 3, 4 の 5 つの数字から 3 つを取り出す組み合わせというのは {0, 1, 2}, {0, 1, 3}, {0, 1, 4},  [...]]]></description>
			<content:encoded><![CDATA[<p>組み合わせの列挙を行いたいということはしばしば起こります。例えば 0, 1, 2, 3, 4 の 5 つの数字から 3 つを取り出す組み合わせというのは {0, 1, 2}, {0, 1, 3}, {0, 1, 4}, {0, 2, 3}, {0, 2, 4}, {0, 3, 4}, {1, 2, 3}, {1, 2, 4}, {1, 3, 4}, {2, 3, 4} の 10 通りあります。普通に書く場合は『<a href="http://msdn.microsoft.com/ja-jp/magazine/cc163957(en-us).aspx"  class="liexternal aga aga_39">Using Combinations to Improve Your Software Test Case Generation</a>』のように書けばよいのですが，ここではあえてイベントを利用して書いてみたいと思います。</p>
<p><span id="more-2429"></span></p>
<p>まず組み合わせを構成する要素を表すクラスを作成します。</p>
<pre class="brush: csharp; title: ; notranslate">
public class Element
{
   private readonly int capacity;
   private int value;

   public Element(int capacity, int value)
   {
      this.capacity = capacity;
      this.value = value;
   }

   public int Value
   {
      get { return this.value; }
   }

   public event EventHandler Exceeded;
   public event EventHandler ValueReset;

   public void Succeed()
   {
      this.value++;
      if (this.value &gt;= this.capacity)
      {
         OnExceeded(EventArgs.Empty);
      }
   }

   public void Reset(int value)
   {
      this.value = value;
      OnValueReset(EventArgs.Empty);
   }

   protected virtual void OnExceeded(EventArgs e)
   {
      if (Exceeded != null)
      {
         Exceeded(this, e);
      }
   }

   protected virtual void OnValueReset(EventArgs e)
   {
      if (ValueReset != null)
      {
         ValueReset(this, e);
      }
   }
}
</pre>
<p>最初に挙げた例のように，要素を 1 つずつカウントアップしていくのが簡単です。カウントアップして取りうる値の最大値になったら，前の要素をカウントアップして，自身はリセットします。この要素間の連絡をイベントが担うわけですね。</p>
<p>次に要素を管理するクラスを作成します。</p>
<pre class="brush: csharp; title: ; notranslate">
public class Combination
{
   private readonly LinkedList&lt;Element&gt; elements;
   private bool hasMore;

   public Combination(int n, int k)
   {
      if (n &lt; 0)
      {
         throw new ArgumentOutOfRangeException(&quot;n&quot;);
      }
      if (k &lt; 0 || n &lt; k)
      {
         throw new ArgumentOutOfRangeException(&quot;k&quot;);
      }
      this.elements = new LinkedList&lt;Element&gt;();
      while (--k &gt;= 0)
      {
         var count = this.elements.Count;
         var element = new Element(n - k, count);
         var node = this.elements.AddLast(element);
         AddEvent(node);
      }
      this.hasMore = true;
   }

   public bool HasMore
   {
      get { return this.hasMore; }
   }

   public int[] Current
   {
      get { return this.elements.Select(e =&gt; e.Value).ToArray(); }
   }

   public void MoveNext()
   {
      this.elements.Last.Value.Succeed();
   }

   private void AddEvent(LinkedListNode&lt;Element&gt; node)
   {
      var element = node.Value;
      if (node.Previous == null)
      {
         element.Exceeded += (sender, e) =&gt; this.hasMore = false;
      }
      else
      {
         var previous = node.Previous.Value;
         element.Exceeded += (sender, e) =&gt;
         {
            previous.Succeed();
            element.Reset(previous.Value + 1);
         };
         previous.ValueReset += (sender, e) =&gt;
         {
            element.Reset(previous.Value + 1);
         };
      }
   }
}
</pre>
<p><code>LinkedList</code> に追加する際に，追加する要素に前の要素と連絡をするためのイベントを追加します。実装を簡単にするために <code>IEnumerator&lt;T&gt;</code> と少し違うインターフェイスになっています。さらに言えば， <code>Current</code> を呼ぶたびに毎回新しい配列を作っていて微妙です。修正は容易ですが，あえてこの実装を採用することもないので，簡単のためにこうしています。</p>
<p>以下のように使います。</p>
<pre class="brush: csharp; title: ; notranslate">
for (var c = new Combination(5, 3); c.HasMore; c.MoveNext())
{
   var values = c.Current;
   Console.WriteLine(string.Join(&quot;, &quot;, values));
}

// output
// 0, 1, 2
// 0, 1, 3
// 0, 1, 4
// 0, 2, 3
// 0, 2, 4
// 0, 3, 4
// 1, 2, 3
// 1, 2, 4
// 1, 3, 4
// 2, 3, 4
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2429/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C# で enum を扱うメソッドってどう書くべきなのだろう</title>
		<link>http://blog.recyclebin.jp/archives/2402</link>
		<comments>http://blog.recyclebin.jp/archives/2402#comments</comments>
		<pubDate>Sun, 08 Jan 2012 01:51:38 +0000</pubDate>
		<dc:creator>kos59125</dc:creator>
				<category><![CDATA[プログラミング]]></category>
		<category><![CDATA[雑感]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[F#]]></category>

		<guid isPermaLink="false">http://blog.recyclebin.jp/?p=2402</guid>
		<description><![CDATA[C# の enum を扱うメソッドをジェネリックに書きたいと思うと，ジェネリック型制約に enum が使えないという問題に直面します[a]。何通りか書き方が考えらます。これを，フラグの列挙型の値を与えると，フラグを分解し [...]]]></description>
			<content:encoded><![CDATA[<p>C# の enum を扱うメソッドをジェネリックに書きたいと思うと，ジェネリック型制約に enum が使えないという問題に直面します<sup>[<a href="http://blog.recyclebin.jp/archives/2402#footnote_0_2402"  id="identifier_0_2402" class="footnote-link footnote-identifier-link" title="delegate もそうですね。">a</a>]</sup>。何通りか書き方が考えらます。これを，フラグの列挙型の値を与えると，フラグを分解して返すメソッド <code>DecomposeFlag</code> を書きながら考えて見ます。</p>
<pre class="brush: csharp; title: ; notranslate">
[Flags]
enum Flag { None = 0, A = 1, B = 2, C = 3, D = 4, E = 5 }

// DecomposeFlag(Flag.None) -&gt; { Flag.None }
// DecomposeFlag(Flag.A) -&gt; { Flag.A }
// DecomposeFlag(Flag.C) -&gt; { Flag.A, Flags.B }
// DecomposeFlag(Flag.C | Flag.E) -&gt; { Flag.A, Flag.B, Flags.D }
// DecomposeFlag(Flag.None | Flag.E) -&gt; { Flag.A, Flags.D }
</pre>
<p><span id="more-2402"></span></p>
<h3>ジェネリックを諦める場合</h3>
<pre class="brush: csharp; title: ; notranslate">
public static ISet&lt;Enum&gt; DecomposeFlag(Enum value)
{
   if (value == null)
   {
      throw new ArgumentNullException(&quot;value&quot;);
   }
   var enumType = value.GetType();
   if (Convert.ToUInt64(value) == 0)
   {
      return new HashSet&lt;Enum&gt; { value };
   }
   var flags = (from Enum flag in Enum.GetValues(enumType)
                where Convert.ToUInt64(flag) != 0
                where value.HasFlag(flag)
                select flag).ToList();
   var result= from flag in flags
                where flags.All(e =&gt; e == flag || !flag.HasFlag(e))
                select flag
   return new HashSet&lt;Enum&gt;(result);
}
</pre>
<h3>無理やりジェネリック</h3>
<pre class="brush: csharp; title: ; notranslate">
public static ISet&lt;TEnum&gt; DecomposeFlag&lt;TEnum&gt;(TEnum value)
   where TEnum : struct
{
   var enumType = typeof(TEnum);
   if (!enumType.IsEnum)
   {
      throw new NotSupportedException();
   }
   ulong bits = Convert.ToUInt64(value);
   if (bits == 0)
   {
      return new HashSet&lt;TEnum&gt; { value };
   }
   var flags = (from Enum flag in Enum.GetValues(enumType)
                let flagBits = Convert.ToUInt64(flag)
                where flagBits != 0
                where (bits &amp; flagBits) == flagBits
                select flag).ToList();
   var result = from flag in flags
                let flagBits = Convert.ToUInt64(flag)
                where set.Select(Convert.ToUInt64).All(e =&gt; e == flagBits || (e | flagBits) != flagBits)
                select (TEnum)Convert.ChangeType(flag, enumType);
   return new HashSet&lt;TEnum&gt;(result);
}
</pre>
<p>ちなみに整数のまま扱うなら以下のように書くこともできます。</p>
<pre class="brush: csharp; first-line: 14; title: ; notranslate">
   var flags = (from Enum flag in Enum.GetValues(enumType)
                let flagBits = Convert.ToUInt64(flag)
                where flagBits != 0
                where (bits &amp; flagBits) == flagBits
                select flagBits).ToList();
   Type underlyingType = enumType.GetEnumUnderlyingType();
   var result = from flagBits in flags
                where flags.All(e =&gt; e == flagBits || (e | flagBits) != flagBits)
                select (TEnum)Convert.ChangeType(flagBits, underlyingType);
   return new HashSet&lt;TEnum&gt;(result);
}
</pre>
<h3>折衷案</h3>
<pre class="brush: csharp; title: ; notranslate">
public static ISet&lt;TEnum&gt; DecomposeFlag&lt;TEnum&gt;(Enum value)
   where TEnum : struct
{
   if (value == null)
   {
      throw new ArgumentNullException(&quot;value&quot;);
   }
   var enumType = typeof(TEnum);
   if (enumType != value.GetType())
   {
      throw new NotSupportedException();
   }
   if (Convert.ToUInt64(value) == 0)
   {
      return new HashSet&lt;TEnum&gt; { (TEnum)Convert.ChangeType(value, enumType) };
   }
   var flags = (from Enum flag in Enum.GetValues(enumType)
                where Convert.ToUInt64(flag) != 0
                where value.HasFlag(flag)
                select flag).ToList();
   var removing = from flag in flags
                  where flags.All(e =&gt; e == flag || !flag.HasFlag(e))
                  select (TEnum)Convert.ChangeType(flag, enumType);
   return new HashSet&lt;TEnum&gt;(result);
}
</pre>
<h3>結局</h3>
<p>どれもいまいちに見えます。何か良い書き方はあるのでしょうか。</p>
<p>ここで唐突に F# に登場してもらいます。</p>
<pre class="brush: fsharp; title: ; notranslate">
let DecomposeFlag (value : 'T when 'T : enum&lt;_&gt;) : ISet&lt;'T&gt; =
   if Convert.ToUInt64(value) = 0uL
   then
      new HashSet&lt;'T&gt; ([value]) :&gt; ISet&lt;'T&gt;
   else
      let has flag = (flag :&gt; Enum).HasFlag
      let flags = Enum.GetValues typeof&lt;'T&gt;
                  |&gt; Seq.cast&lt;'T&gt;
                  |&gt; Seq.filter (fun flag -&gt; Convert.ToUInt64 flag &lt;&gt; 0uL)
                  |&gt; Seq.filter (has value)
      let result = flags
                   |&gt; Seq.filter (fun flag -&gt; Seq.forall (fun e -&gt; e = flag || not (has flag e)) flags)
      new HashSet&lt;'T&gt; (result) :&gt; ISet&lt;'T&gt;
</pre>
<p>なんだ最初から F# で書けば良かったのか，というお話でした<sup>[<a href="http://blog.recyclebin.jp/archives/2402#footnote_1_2402"  id="identifier_1_2402" class="footnote-link footnote-identifier-link" title="ちなみにこれを逆コンパイルして C# のコードに変換すると where T : Enum とかついてました。ずるい。">b</a>]</sup>。</p>
<h3>更新履歴</h3>
<ul>
<li>[2012-01-08 12:20] F# 版の返り値の型を明示。その他瑣末な修正。</li>
<li>[2012-01-08 16:00] C# 版で <code>Any</code> を使っていたのを， F# 版 の <code>forall</code> にあわせて <code>All</code> を使うように変更。</li>
<li>[2012-01-09 06:35] ジェネリック版でジェネリック型が enum でないときに投げる例外を NoSupportedException に変更。</li>
</ul>
<h3>脚注</h3>
<ol class="footnotes">
<li id="footnote_0_2402" class="footnote">delegate もそうですね。</li>
<li id="footnote_1_2402" class="footnote">ちなみにこれを逆コンパイルして C# のコードに変換すると <code>where T : Enum</code> とかついてました。ずるい。</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://blog.recyclebin.jp/archives/2402/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  blog.recyclebin.jp/feed ) in 0.47602 seconds, on May 21st, 2012 at 2:33 am UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on May 21st, 2012 at 3:33 am UTC -->
<!-- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
<!-- Quick Cache Is Fully Functional :-) ... A Quick Cache file was just served for (  blog.recyclebin.jp/feed ) in 0.00040 seconds, on May 21st, 2012 at 2:59 am UTC. -->
