ボンジュール・マドモアゼル

本サイトの情報は自己責任にてご利用下さい。

[未分類] javac エラーメッセージ出力言語の切替え

 
コンパイラから出力されるメッセージを次のように日本語から英語へ切り替えることができる。
javac -J-Duser.language=en -J-Duser.country=us ファイル名
以下も参考に。
happynowの日記 — Java デフォルト・ロケールの上書き実行

[Java] assert文の構文

 
Java の assert文の文法は次のとおり。
AssertStatement

assert Expression1 ;
assert Expression1 : Expression2 ;
したがって
assert(f);
というのはメソッドを呼び出しているわけではない。
(f) という boolean式を assert の後ろに書いているだけ。
  1. 2012/04/21(土) 16:03:56|
  2. Java|
  3. トラックバック(-)|
  4. コメント:0

[Microsoft Access] ADODB.Recordset.Find 実行時エラー '3001': 引数が間違った型、許容範囲外、または競合しています。

 
ADODB.Recordset.Find メソッドは複数フィールドを対象とした検索ができない。

[Java] NavigableSet の floor と ceiling のイメージ、覚え方

 
NavigableSet の floor と ceiling の振る舞いを、
「引数を基準としてコレクションからそれに該当する要素を抽出する」と捉えるよりも
「引数 → 切り捨て(切り上げ)られた値」という引数に対する計算と捉えた方が
数値計算の floor と ceiling の感覚と近くなり、メソッド名のイメージをより理解しやくなると思う。

フロアは、NavigableSet集合の順序構造において引数を切り捨てる。
シーリングは、NavigableSet集合の順序構造において引数を切り上げる。

以下のイメージ図を見比べれば覚えやすい。

数値計算の floor と ceiling


数値計算の floor と ceiling のイメージ

NavigableSet の floor と ceiling


NavigableSet の floor と ceiling のイメージ

シーリングはシーリング・ライトのシーリング。
  1. 2012/04/20(金) 15:34:01|
  2. Java|
  3. トラックバック(-)|
  4. コメント:0

[用語] Yコンビネータ(不動点演算子)について

 
Yコンビネータ(不動点演算子)について
このエントリは、次の記事を参考に、応用面よりYコンビネータについて説明したものです。

おとうさんにもわかるYコンビネータ!(絵解き解説編)
さあ、Yコンビネータ(不動点演算子)を使おう!

Yコンビネータなどの不動点演算子は、関数を第一級市民として扱うプログラミング言語(もしくは、擬似的にそれを扱える言語)において、
再帰関数の汎用的なカスタマイズを行うために利用できる。
たとえば、階乗を計算する次のような関数があったとする。
function factorial(x) {

if (x == 1)
return 1;
else
return x * factorial(x - 1);
}
この関数を以下のように改変すると、この関数にキャッシュ機構を組み入れることが出来る。
cache = {};

function factorial2(x) {
if (x == 1)
return 1;
else {
if (!(x in cache))
cache[x] = x * factorial2(x - 1);
return cache[x];
}
}
しかし、このような仕方では、個々の再帰関数毎にカスタマイズが必要となる。
不動点演算子はこのような場面で役に立つ。
不動点演算子を使用すると、キャッシュ機構をひとつ作っておけば、それを任意の再帰関数に適用することができる。

イメージ的なことを言えば、不動点演算子を使うと、次のような f の再帰呼び出しに対して
f (f (f (f (f (f (f ()))))))

^ ^ ^ ^ ^ ^ ^
^ で示した f の内部的な呼び出しの前後に、外部から何かしらの処理を挿入することが可能となる。
別な言い方をすれば、f の実装を拡張することができる。

不動点演算子を考える上で、主要な要素は次の3つである。

再帰関数 f
仕様となる再帰関数である。不動点演算子を使う場合、これは直接コーディングされない。
実行時、「不動点演算子」と「再帰関数の雛形を組み込んだ関数生成機」により動的に構成される。
再帰関数の雛形を組み込んだ関数生成機 M
この関数生成機に、再帰関数 f の雛形が組み込まれる。
この雛形は、再帰関数の処理をコーディングしているものであるが、通常の再帰関数と違い、
内部で自分自身を呼び出すところをパラメータ化して、内部で呼び出す関数を指定できるようにしている。
「再帰関数の雛形を組み込んだ関数生成機」は、雛形で内部的に呼び出される関数を引数として取り、
戻り値として、その渡された関数を雛形に適用した関数を返す。
不動点演算子 Y
「再帰関数の雛形を組み込んだ関数生成機 M」をもとに再帰関数を生成する関数である。
不動点演算子で再帰関数を扱うには、再帰関数を特殊な形でコーディングしてやらなければならない。
この特殊な形でコーディングされたものが 再帰関数の雛形を組み込んだ関数生成機 である。

再帰関数の雛形を組み込んだ関数生成機 M が具体的にどのように構成されるか、さきほどの factorial 関数を用いて説明する。
まず、内部で呼ばれる関数をパラメータ化する。
function factorial_template(x, g) {

if (x == 1)
return 1;
else
return x * g(x - 1);
}
そして、渡された関数をこの雛形に適用して出来た関数を返す関数生成機に仕立てる。
function m(g) {

return function(x) {
return factorial_template(x, g);
}
}
普通は、再帰関数の雛形と関数生成機と分けて書かずに、次のように雛形を関数生成機 M のなかに展開して書く。
function m(g) {

return function(x) {
if (x == 1)
return 1;
else
return x * g(x - 1);
}
}
重要なのは、この関数生成機 M と再帰関数 f の関係である。次の等式が成り立つ。
f = M(f)
したがって、
f = M(M(...(M(f))))
f は M の不動点である。逆に言えば M の不動点こそ再帰関数 f である。
例でいうと
factorial = m(factorial)
となる。面白いのは、関数生成機 M を不動点演算子に渡すと f が出来る点だ。
つまり、
f = Y(M)
である。Y と M だけで関係を示せば、
Y(M) = M(Y(M))
さて、Yコンビネータであるが実は、名前呼出し(call-by-name) 機構のない言語の上では Y コンビネータ を定義することは出来ない。
値呼出しの機構の上では不動点演算子として Y コンビネータの一部をη変換することで得られる次の Z コンビネータが使える。
function Z(f) {

return (function(x) {
return function(y) {
return f(x(x))(y);
};
})(function(x) {
return function(y) {
return f(x(x))(y);
};
})
}
Z コンビネータも不動点演算子なので当然次の等式は成り立つ。
f = M(f)

f = Z(M)
Z(M) = M(Z(M))
さて、これで動的に再帰関数を構成できる。
var factorial = Z(m);
キャッシュ機能、メモ化機能については以下のように追加する。
function memo(m) {

var cache = {};
return function(f) {
return m(g(f));
}
function g(f) {
return function(n){
if (!(n in cache)) {
cache[n] = f(n);
}
return cache[n];
};
}
}
var factrial_memo = Z(memo(m));
勿論、このメモ化拡張は汎用的に使える。
function fib_m(g) {

return function(x) {
if (x < 2)
return x;
else
return g(x - 1) + g(x - 2);
}
}
var fib_memo = Z(memo(fib_m));


Yコンビネータによって再帰関数を汎用的に拡張できることがわかったが、
Yコンビネータを使わずとも以下のような形式であれば拡張性のある再帰関数を書ける。
そうすると、Yコンビネータ をあえて使うメリットは何だろうか。
function factorial_template(x, g) {

if (x <= 1)
return 1;
else
return x * g(x - 1, g);
}

function fib_template(x, g) {
if (x < 2)
return x;
else
return g(x - 1, g) + g(x - 2, g);
}

function gen_func(f, g) {
if (g === undefined)
return function(x) {
return f(x, f);
};
else {
var h = g(f);
return function(x) {
return h(x, h);
};
}
}

function memo(f) {
var cache = {};
return function(x, g) {
if (!(x in cache)) {
cache[x] = f(x, g);
}
return cache[x];
}
}

function trace(f) {
return function(x, g) {
document.writeln("called with argument: '" + x + "'");
return f(x, g);
}
}

function composite(f, g) {
return function(x, h) {
return g(f(x, h));
}
}

factorial = gen_func(factorial_template);
fib = gen_func(fib_template);

factorial_memo = gen_func(factorial_template, memo);
fib_memo = gen_func(fib_template, memo);

var factorial_trace = gen_func(factorial_template, composite(trace, memo));
var fib_trace = gen_func(fib_template, composite(trace, memo));


document.writeln("\tfactorial\t\tfib");
for(var i = 1; i <= 10; i++)
document.writeln("" + i + ":\t" + factorial(i) + "\t\t\t" + fib(i));

document.writeln();
document.writeln("\tfactorial_memo\t\tfib_memo");
for(var i = 1; i <= 10; i++)
document.writeln("" + i + ":\t" + factorial_memo(i) + "\t\t\t" + fib_memo(i));

document.writeln();
document.writeln("fib_trace(5)");
fib_trace(5);
  1. 2012/04/15(日) 13:42:10|
  2. 用語|
  3. トラックバック(-)|
  4. コメント:0
次のページ