Fork me on GitHub

2011/11/29


このエントリーをはてなブックマークに追加
なんでか知らんけどリポジトリ消されたwww

今日githubのdashboard見てたらtwitterが簡素なクラスライブラリを提供してた。
twitter/dove - GitHub

Simple OO helpers for JavaScript

https://github.com/twitter/dove
たいした物ではないが、ORMを意識したシステムにも使えるんじゃないかと思った。 まずはdove.htmlからsubとextend
var User = Dove.Class.sub({
  prop: 'Alex',

  init: function(name){
    this.name = name;
  }
});

var Person = User.sub();

var ORM = {};
Person.extend(ORM);

var person = new Person('Alex');
console.log(person.name);
ちょっとpropとnameのどちらかがtypo臭いけど。
次にinclude
var Animal = Dove.Class.sub({ kind: 'Animal' });
var Human = Dove.Class.sub();

var animal = new Animal();
Human.include(animal);
var human = new Human();
console.log(human.kind);
そしてproxy
var Drunker = Dove.Class.sub({ drink: function(month) {
    return month + "は正月ーで酒が飲めるぞー!酒が飲める飲めるぞ!酒が飲めるぞ!";
}});

var drunker = new Drunker();
[1,2,3,4,5,6,7,8,9,10,11,12].map(drunker.proxy(function(e) {
    console.log(this.drink(e));
}));
と、一般的なOOに必要そうな物がちっちゃくまとまってる感じ。
ライセンスも何も明記されてないので商用利用していいかは知らない。
Posted at 10:06 in ソフトウェア::javascript
Tagged as: javascript
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2011/09/26


このエントリーをはてなブックマークに追加

※ネタです

※UDFです

Vimテクニックバイブル ~作業効率をカイゼンする150の技 Vimテクニックバイブル ~作業効率をカイゼンする150の技
Vimサポーターズ
技術評論社 / ¥ 3,129 (2011-09-23)
 
発送可能時間:在庫あり。


正誤表を書くのにしばらくこの本をちょっと眺めてみたら、SQLiteのUDFって簡単に作れるんだなー、と思った && そういやV8ってライブラリとして簡単にリンクできるはずだな、と思い出した ので、ついカッとなって作った。

sqlite3udf-jseval - GitHub

http://github.com/mattn/sqlite3udf-jseval

UDFうんぬn

ほとんど↑の本、全然関係ないと思ってたけど、やっぱりSQLiteのUDFについて全然書いてなかった。しょうがないので軽く紹介しておくと

UDFを追加する場合、SQLiteの再コンパイルは必要ない (しかるべき所に.soがおいてあればいい)
UDFはこの辺読んどけばだいたい分かる。

例えば文字列っぽいものを返すmyfuncっていうUDFを作りたい場合
SQLITE_EXTENSION_INIT1 static void js_eval_func(sqlite3_context *context, int argc, sqlite3_value **argv);
int sqlite3_extension_init(sqlite3 *db, char **errmsg, const sqlite3_api_routines *api);
の二つの関数を実装したmyfunc.cっていうコードを用意してあげて
gcc -o myfunc.so myfunc.c `sqlite_config --cflags` -shared
という風にコンパイルして(これはLinuxの場合)、しかるべき場所(LD_LIBRARY_PATHが通る場所)に置いた後、sqliteのシェルで
> select load_extension("myfunc.so");
とやればいきなり使える。

sqlite3_value_textはアロケートした文字列を渡して、最終引数に開放関数を渡すというのがUDFのお作法らしい。strdupで確保したポインタは最終引数の関数でfreeする、みたいな。

動かす手順

で、今回作ったのはV8とリンクして、JSの文字列をevalしてくれるjs_evalというUDF。
多分試す人はいないと思うけど、動かすための手順を書くと

V8のビルド

V8を落としてきてビルドする。ただし、SQLiteのUDFは別に-fPICを付けなくてもおk。

js_eval.cppをコンパイル

V8をビルドしたディレクトリにもっていって
g++ -o js_eval.so js_eval.cpp `sqlite_config --cflags` -shared -Iinclude libv8.a -lpthread
そうすると、js_eval.soができるので、これをLD_LIBRARY_PATHが通ったディレクトリに置く

読み込むる

シェルに入って
> select load_extension("myfunc.so");
(※このUDF、食わせるものによってはSQLiteごと落ちるかもしれないので良い子のみんなは注意だ)

キターーーッ

すごい。
sqlite3udf1

全然
sqlite3udf2
役に立つ気がしない。
sqlite3udf3
というかSQLite力が低すぎてどうしたら面白くなるか思いつかない。これを発展させていってTEXTとかに突っ込んだJSONの中身を効率よく検索とか出来たら面白い&実用的なんだけど、道は遠そうだ。


参考
やったーJavaScriptの動くMySQLできたよー - 愛と勇気と缶ビール

しばらく 積ん読 していたこの本をちょっと眺めてみたら、 MySQL のUDFって簡単に作れるんだなー、と思った && そういや V8 って ライブラリ として簡単にリンクできるはずだな、と思い出した...

http://d.hatena.ne.jp/zentoo/20110925/1316961032
Posted at 14:15 in ソフトウェア::lang::c
Tagged as: c++, javascript, sqlite, ネタ
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2011/06/30


このエントリーをはてなブックマークに追加
javascript:for (var b=document.getElementsByTagName("*"), n = 0; n < b.length; n++) { if (b[n].getAttribute("g:type") == "plusone" && b[n].getAttribute("aria-pressed") != "true") b[n].click() }

2011/05/23


このエントリーをはてなブックマークに追加
部下にも何度も説明してて、この辺がC言語のポインタみたいな鬼門なのかなーとか思いながら。
javascriptでhtml内のonclickの内容を書き換えようとしています.. - 人力検索はてな

javascriptでhtml内のonclickの内容を書き換えようとしていますが 変更後の関数に変数を渡すと、変更後の関数(load)自体が実行されてしまい、うまくいきません 現在は以下のように、onclickの内容を変更しようとしていますが、 関数を実行させずに、html内のonclickの内容だけ書き換える場合はどのようにしたらいいですか?

document.getElementById('box').onclick = (function(id){ load(id) })(userid);

http://q.hatena.ne.jp/1305849029
こういうコードになった経緯を考えると、その間違いがなぜ起こったかわかりやすいし、人力検索で回答貰った後で再度間違う事も少ないと思う。

おそらくだが、この人はこのコールバック関数登録をループかなんかの中で行おうとしたんじゃないかと(勝手ながら)思った。
<script>
window.onload = function() {
    var elem = document.getElementsByTagName('a');
    for (var n = 0; n < elem.length; n++) {
        elem[n].onclick = function() {
            alert(n);
        }
    }
}
</script>
<body>
<a href="#">foo1</a>
<a href="#">foo2</a>
<a href="#">foo3</a>
</body>
このHTMLでfoo1,foo2,foo3をクリックするとどうなるだろう。0,1,2と答えた人は、この質問者と同じ間違いを起こすだろう。答えは全て3が表示される。
これが何故起きて、どう解決すべきかが分かると今後の理解も早いと思う。

ループのインデックスであるnは、コールバック関数から見ると外のスコープにある。つまりコールバック関数が呼び出された時にはループは3回回ってしまっていて、結果どれをクリックしても3が表示される。
じゃぁどうするか。
var elem = document.getElementsByTagName('a');
for (var n = 0; n < elem.length; n++) {
    var f = n
    elem[n].onclick = function() {
        alert(f);
    }
}
こうじゃない?って答えた人は×。それ何も変わってないから、どれクリックしてもまた3だよって答えた人も×。答えは全て2。
なぜ前回は3が表示されたのか。それはforループが回りきってループを外れる条件に達した、つまり3になったから。ではなぜ今回は2なのか。ループは0,1,2の時にしか実行されなかったから。
わかりますよね。

じゃぁこれ、どうやって個々に0,1,2の値を表示させるのよ...となる。答えは聞いてない!答えは複数ある。
人によってはeval()使っちゃう人もいるだろうし、昔のコードでは結構見た。未だにそんなコードの保守をやらされる場合もある。出来るだけモダンな書き方したいですよね。
問題はスコープでしたよね。毎回同じスコープが実行されちゃってるのが問題で、コールバック関数から見ると全て同じ変数を見てしまっているのが問題。
そこでループの度にスコープを作ってあげるのです。以下の様なコードを見ることが多いと思います。
(function() {
    // ...
})()
関数を文として扱わず、式として呼び出しているんですよね。最近はこんな書き方もある様です。
+function() {
    // ...
}()
これで新しいスコープが出来ます。でもこれだけでは解決しません。この作ったスコープで変動しない値を保持してあげます。
var elem = document.getElementsByTagName('a');
for (var n = 0; n < elem.length; n++) {
    (function() { // ココが決め手
        var f = n
        elem[n].onclick = function() {
            alert(f);
        }
    })() // ココが決め手
}
変数fにn渡してます。このループが3回実行されると3回スコープが作られ、それぞれにfというスコープ内変数が宣言されます。これにより個々のイベントハンドラから0,1,2が参照出来る様になるという事です。
ちなみにvar宣言したくない人はよく
for (var n = 0; n < elem.length; n++) {
    (function(n) {
        elem[n].onclick = function() {
            alert(n);
        }
    })(n)
}
こう書いたりもします。
今回の問題、よくカウントダウンタイマを作ろうとして
for (var n = 0; n < 10; n++) {
    setTimeout(function() {
        document.getElementById('timer').innerHTML = '残り' + (10 - n) + '秒'
    }, 1000 * n)
}
こう書いちゃう人もいます。理屈は同じですよね。気をつけて。
Posted at 12:56 in ソフトウェア::lang::javascript
Tagged as: javascript
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip