プログラム

Ethna_AppSeaechObjectを使ってみた

EthnaのAppObjectを使ってデータベースに検索条件を設定する場合、条件一致の場合は次の様にすればよい。
例えばSAMPLEというテーブルがあって、次の様な形だった場合、

NO MAILADRS USER URL MODE
1 foo@foo.com hideack ttp://d.hatena.ne.jp/hideack/ 1
2 bar@bar.com taro ttp://d.hatena.ne.jp/sample1/ 0
3 hoge@hoge.com hoge ttp://d.hatena.ne.jp/sample2/ 1

次の様なSQLを発行するのと等価な処理は、

SELECT MAILADRS,USER FROM SAMPLE WHERE MODE=1;

次の様になる。

<?php
$sample = $this->backend->getObject("SAMPLE");
$prop_ary = $sample->searchProp(
array("MAILADRS", "USER"),      // 取得する項目名
array("MODE" => "1"),           // 一致条件(検索条件, SQLのWHEREの内容)
null,
null,
null
);
?>

こうすると、$prop_ary[0]には条件一致した件数が格納され、$prop_ary[1]には取得された結果が格納される。
で、例えば単純な条件一致ではない場合、

SELECT MAILADRS, USER FROM SAMPLE WHERE NO>=2 AND NO<5

の様な条件を設定したい場合は、AppSearchObjectを使うと検索条件を設定できる。

<?php
$search = new Ethna_AppSearchObject("2", OBJECT_CONDITION_GE);
$search->addObject(
"SAMPLE",
new Ethna_AppSearchObject("5", OBJECT_CONDITION_LT),
OBJECT_CONDITION_AND
);
$sample = $this->backend->getObject("SAMPLE");
$prop_ary = $sample->searchProp(
array("MAILADRS", "USER"),  // 取得する項目名
$search,                    // 複数条件(AppSearchObjectのインスタンス)
null,
null,
null
);
?>

OBJECT_CONDITION_GE etc... は検索条件を設定するための定数で定義の一覧はリファレンスに記載されている。

今までいくつか条件が重なる様な検索条件を発行するときは、AppObjectではなくて直接操作していたので試しに使ってみたのだけど、こういう使い方が一般的なのだろうか?
少し複雑な気もしなくもない...。

JavaScriptで連想配列をつくるとき

Javascriptで次の様な連想配列が作りかったとき。
PHPで書くとこの様な...。

<?php
$str = "foo";
$ary = array(
$str => "bar";
);
?>

連想配列のキーは別途変数で保持られていて、値は直接与えられるケース。
これを、そのままのノリでJavaScriptで書くとこうなる。

str = "foo";
ary = {str : "bar"};

ただ、こう書くと...

alert(ary.foo);   // "undefined" と表示される
alert(ary.str);   // "bar"と表示される

となる。
少し悩んで、こう書いてみた。

str = "foo";
ary = {};
ary[str] = "bar";
alert(ary.foo);  // "bar"と表示される

もう少しスマートに書けないものかと...。
教えて偉い人。

MD5の逆引きの話

PerlCPANに、こんなライブラリがあった。

Digest-MD5-Reverse-1.3
http://search.cpan.org/~blwood/Digest-MD5-Reverse-1.3/

要はMD5の得られたハッシュ値から、MD5に渡された値を得られる機能を持つらしい。
ソースのサンプルはこんな感じ。

    use Digest::MD5::Reverse;
print "Data is ".reverse_md5("acbd18db4cc2f85cedef654fccc4a4d8")."\n";
# Data is foo

なんで、こんなことができるのかな?と、思いつつソースとかドキュメントを読むと、世界各地で公開されているハッシュ値が収められた辞書を運営しているWebサービスがあってそこにリクエストを出して、逆引きの結果を読んでいるらしい。
なるほど、それであれば確かに不可能ではないのはわかる気がする。

で、もっとお気軽に逆引きする方法がblogに紹介されていた。

あまり感心しない用途だとは思われますが、MD5 Hash 値を逆変換したい、と思ってる人に朗報です。Hash 値を Google で検索してみてください。結構な確率でヒットするそうな。つっても Salt 無しの場合だけですけど。
MD5破りにGoogleを活用 - Rauru Blog

なるほど...。ちょっと試してみた。
たとえば、"digital"という文字列をMD5に通すと、次の値が得られる。

<?php
print md5("digital");
?>

こうすると出力されるhash値は、"e0e1d64fdac4188f087c4d44060de65e"という値だ。
これを、googleの検索ワードとして渡してやると、次の結果が得られる。
f:id:hideack:20090114224523j:image

まぁ、ものの見事に見つかりましたがな。
なので、MD5そのものの強さ云々という問題もありますが、そもそもハッシュ関数を通して何かするときは、saltを対象文字列に付与しておきましょうということで。

JavaScriptで加えられたDOM要素に対して後からスタイルシートを適用する

id:its-tomから昨夜質問があった内容の回答。
質問の内容は表題の通り。
遅いかもしれないし、もう謎は解けたのかもしれないし。そもそも、私が質問を理解していないのかもしれない(ぉ
昨夜はバテバテでちょっと書けなかったので今日書いてみた。

JavaScriptとベースのHTMLは以下の通り。
この段階ではcssは読み込まれていないしDOMの操作でも触っていない。

で、実行結果は次の通り。
「要素を加える」で、area1にadd1という要素とメッセージを流し込む。
「スタイルを変える」で外部にあるスタイルシートを読み込んで加えた要素にスタイルを適用される。
f:id:hideack:20081218231131p:image

追加で読ましているスタイルシートは次の様な感じ。

div#add1 {
border: 1px solid #cee6e6;
background-color: #cccccc;
}

こんなんでよかったのだろうか。

Cisco developer content

以前、アルバイトで来てくれていた方*1が紹介してくれた。

シスコは、「プラットフォームとしてのネットワーク」のコンセプトを軸としたイノベーションの推進を目指して、既成概念にとらわれない考え方(think outside the box)のできるアプリケーション開発者の方々に向けて、コンテストを開催します。総額 10 万米ドルの賞金を目指して、Cisco Application Extension Platform(AXP)上で動作するエキサイティングな Linux アプリケーションを開発してみませんか?
Cisco AXP Developerコンテスト

というか、こういうプラットフォームがあること自体知らなかった。
ルーターの上で直にアプリケーションが動かせてしまうという訳ですね。C,Java,Perl,Pythonが使えるみたい。
普段の業務とかで太いネットワークを扱っていてCiscoの製品使っていたりすると、こういったプラットフォームがあるのは既知だったりするのだろうか。
少し私には知識が足りない様だ。残念。*2

もっとも、こういう話題を見たときに、私のことを思い出してメールしてくれることだけでも嬉しい。

*1:友達だ。戦友だ。

*2:提案書が英語である必要もあるところもハードルだ(笑)

Mapreduce1

最近、全く新しい知識が入らないので自発的に勉強中。
Mapreduceは、googleで利用されている分散処理アルゴリズム。
名の通り、"Map処理"と"Reduce処理"の2段階に分けて処理が行われる。
詳しくは末尾の参照ページをば。
内容をざっくり書くと...

  • Map処理
    • 入力情報に何らかの処理を加えて連想配列(Key-Valueの組み合わせの配列)*1を構築する処理
    • 入力情報が膨大であっても、分割可能な問題であればMap処理を行う処理系の数に入力情報を分割して分散して処理ができる
  • Reduce処理
    • Map処理で作られた連想配列をまとめる処理をして出力情報を作る*2

といった具合。
やってることはシンプルなのだけど、googleもこのアルゴリズムを使ったアプリケーションはかなり多く書かれているそうだ。

で、何かプログラムを書いてみないとわからないということで書いてみる。
ほとんど、下の参照ページ "www.joelonsoftware.com"のままですが...。JavaScriptで書いてみました。
あと、ここではMap処理の出力のKeyと入力のKeyが一致していますが、一致している必要は本来はないはずだし、もう少し別の書き方もある気がする。Umm....

var Mapreduce = Class.create();
Mapreduce.prototype = {
initialize : function(){
},
map : function(fn, ary){
for(i=0; i<ary.length; i++){
ary[i] = fn(ary[i]);
}
},
reduce : function(fn, ary, init){
var s = init;
for(i=0; i<ary.length; i++){
s = fn(s, ary[i]);
}
return s;
}
};
    • 配列の各要素を2倍してその合計を求めるというもの
mapreduce = new Mapreduce();
sample_ary = [1,2,3];
mapreduce.map(function(a){return a*2}, sample_ary);
s = mapreduce.reduce(function(x,y){return x+y;}, sample_ary, 0);
alert(s);

もしかしたら、まだ続くかもしれない。

*1:PHP的な言い方?

*2:大ざっぱすぎる理解かもしれない...

prototype.js bindメソッド

昨日の続き。

this.timer =  new PeriodicalExecuter(this.showCounter, 2);

と書いたときに何故未定義のエラーになったか。
prototype.jsのPeriodicalExecuterクラスのコンストラクタの定義を見ると、

PeriodicalExecuter:[constructor](callback, interval)

引数名 内容
callback a function that will be passed the PeriodcalExecuter object itself as the only argument
interval the interval (in seconds)

となっている。
第一引数には、関数オブジェクトを渡してあげないとならない。
が、JavaScriptの場合、上の様な書き方をするとthisは関数オブジェクトを呼び出したときにその関数オブジェクトを格納していたインスタンスを指し、このタイマーが収められているインスタンスを指さない。
(書いている人=私は指してるつもりだったのだけど)

で、ここでprototype.jsの拡張、"bind"メソッドを使う。

this.timer =  new PeriodicalExecuter(this.showCounter.bind(this), 2);

と書く事によって、thisが指す先を束縛することができる。bindの引数には束縛するインスタンスを指定する。
ここでは、自身のクラスから生成されたインスタンスを指すので 〜.bind(this) とすることで問題が解決した。

…ややこしいなぁ。まだ、「なんとなく」わかった状態だ。
絵に描いたらわかるかなぁ。と思ってノートにメモ書きしてみたけど、ますます混乱…。

委譲とPeriodicalExecuterとprototype.jsと。

とりえあずサンプル。
次の様なHTMLと...

<html>
<head>
	<script type="text/javascript" src="prototype.js"></script>
	<script type="text/javascript" src="mainctrl.js"></script>
	<script type="text/javascript">
		//<![CDATA[
		var mainctrl = new Mainctrl();
		// ]]>
	</script>
	</head>
<body>
<input type="button" onclick="mainctrl.start();" value="start"/><br/>
<br/>
<input type="button" onclick="mainctrl.stop();" value="stop"/><br/>
<hr>
<div id="status">
</div>
</body>
</html>

次の様なJavaScript

var Mainctrl = Class.create();
Mainctrl.prototype = {
counter : 0,
timer : null,
initialize : function(){
this.timer =  new PeriodicalExecuter(this.showCounter.bind(this), 2); // ← 委譲
this.timer.stop();
},
start : function(){
this.timer.registerCallback();
},
stop : function(){
this.timer.stop();
},
showCounter : function(){
this.counter = this.counter + 1;
$('status').innerHTML = this.counter;
}
};

で、ポイントは、

this.timer =  new PeriodicalExecuter(this.showCounter.bind(this), 2); // ← 委譲

である。
ここを、

this.timer =  new PeriodicalExecuter(this.showCounter(), 2);

この様に書くとエラーとなる。

this.callback is not a function

以後、後日へ続く。(あは

PHPでRSSを生成する。

何らかのフィード(AtomかRSSか)を作りたいな。と思ったので、ライブラリを探してみた。
簡単に探して見つかったのが次のライブラリ。

RSS74 - Version 0.3
RSS74 is a PHP class with that you can create RSS files.
It provides a simple interface to do that. Just look at the examples. (2 examples included)
snippets - PHP classes

大分前にPHPSpotでも紹介されていまいしたね...。(ここ)
RSS2.0を生成することができます。

使い方はおそらく同梱されているサンプルを見ればおおよそ問題ないかと。
ライブラリのソースを眺めたのですが、そのまんま。でした。
あと、title, description要素とかに日本語を使うには、ライブラリ(inc.rss74.php)のhtmlentities関数をhtmlspecialchars関数に書き換える必要があることに注意。