CentOS5.5にMadwifiインストール。

なんか超久しぶりのエントリー。

自宅のLAN環境がイマイチ過ぎて泣けてきたのでLinuxBoxでルーターを作ることにした。
pppoeとdhcpはまぁすんなりと。

有線環境が整ったところで無線も・・・と思ったら未知領域過ぎてこけまくる。
NICはBuffaloのWLI-UC-GNを買ってきて、クライアントモードはなんとか完了したものの、未だAPにするための途上。


ここまで最大のずっこけポイントのMadwifiをとりあえず越えたので備忘録。

ath/if_athvar.cの118行目。

//#define ATH_GET_NETDEV_DEV(ndev)      ((ndev)->dev.parent)
#define ATH_GET_NETDEV_DEV(ndev)        ((ndev)->class_dev.dev)

これだけ。
これでmakeが通った。


あとは完成したらまとめを書こう・・・

言われなきゃ気付かない$.extendの引数。

$.extendも$.fn.extendも同じなんだけど、このメソッドには引数が3種類ある。

まずはメジャー系2種。

$.extend({ foo: 'bar' }); // jQuery.foo = 'bar';

var o = $.extend({ foo: 'bar' }, { fizz: 'buzz' }); // merge but shallow

jQuery自体を拡張する1引数extendと、引数をマージする複引数extend。
この辺はplugin作ったりなんだりで良く見かける。


わざわざ「but shallow」とか書いた時点でオチが読めるとは思うけど、
第3のコール方法は、deep mergeのためのもの。

var o = $.extend(true, { foo: 'bar' }, { fizz: 'buzz' });

第1引数をboolean値にすると、deep mergeの有無を指定するフラグとして扱われる。


デフォルトがshallow mergeなだけに何かしらdeep mergeする手段はあると思ったけど、こういうことだったらしい。

superが呼べる継承メソッド。

javascriptで継承といえば、

var Parent = function() {};
var Child = function() {};
Child.prototype = new Parent();

という感じで「prototype継承」を使うのが普通(だと思う)。


ただ、この手法で困るときがある。
オーバーライドした子クラスのメソッド中で親クラスの同名メソッドを呼びたいとき。

Child.prototype.method = function() {
  Parent.prototype.method.apply(this);
};

一応上記の方法で子クラスのインスタンスのコンテキストで呼ぶことはできる。
ただ、記法が冗長になってしまうのと、
親クラス名をハードコーディングするか、プロパティ等に保持していないといけない。


というわけで以下のように使える継承メソッドを作ってみた。

var Parent = function() {};
Parent.prototype = {
  name:   'Parent',
  method: function() {
    alert(this.name);
  }
};

var Child = (function() {}).inherit(Parent);
Child.proto({
  name:   'Child',
  method: function() {
    this.super().method();
  }
});

var p = new Parent();
var c = new Child();

p.method(); // Parent
c.method(); // Child

Functionオブジェクトからinherit()を呼ぶと、引数で与えたFunctionオブジェクトを継承する。
また、proto()メソッドで既存のprototypeに要素を追加できる。

子クラスのメソッドからsuper()を呼ぶと、
自分自身のコンテキストで親クラスのメソッドを呼べるオブジェクトが返る。
なお、何も継承していないクラスのオブジェクトから呼ばれた場合は、Objectを親クラスの代わりに使用する。



(´・ω・`)しかし世の中に既にあったりしないんだろうか


id:amachangさんにレビューしてもらえたらなぁ・・・という願望。


コードの中身は以下。

/**
 * inherit.js - utility for class inheritation
 */

(function() {
    Object.prototype.proto = function(proto) {
        for (key in proto) {
            this.prototype[key] = proto[key];
        }

        return this;
    };

    Object.prototype.inherit = function(s) {
        if (typeof(s) != 'function') throw new Error('cannot inherit from non-function variable');

        var f = function() {};
        f.prototype = new s();

        var p = this.prototype;

        this.prototype = new f();
        this.proto(p);
        
        this.prototype.__super_proto__ = s.prototype;
        
        return this;
    };
    
    Object.prototype.super = function() {
        if (typeof(this.__super_proto__) != 'object') this.__super_proto__ = Object.prototype;
        
        if (typeof(this.__super__) != 'object') {
            var s = {};
            var p = this.__super_proto__;
            
            for (key in p) {
                if (typeof(p[key]) != 'function') {
                    s[key] = p[key];
                    continue;
                }

                s[key] = (function(origin, target, method) {
                    return function() {
                        var args = Array.prototype.slice.call(arguments);

                        return (this === origin) ? method.apply(target, args) : new method(args);
                    };
                })(s, this, p[key]);
            }

            this.__super__ = s;
        }

        return this.__super__;
    };
})();

Functionにまつわる変態的検証。

JavaScriptの不思議な言語構造、Function。
どうなるか気になる挙動があったので確認してみた。

Functionをnewするときとcallするときでthisってどうなるの?

まずFunctionが何かっていうと、

var f = function() {};

のようにして作られる「関数型オブジェクト」のこと。
Perlの無名関数のように、そのままcallすることができる。

f();

JavaScript独特の挙動として、このFunctionオブジェクトはクラスのようにも振る舞う。

var o = new f();

とすると、oには「fというクラスのインスタンス」とも言えるオブジェクトが入る。
その他prototypeが云々というのもあるが、今回の件とは関係ないので割愛。

そして本題へ

今回の主旨は、「関数としてもコンストラクタとしても呼べるFunctionを両方の呼び方したらthisの値はどうなるのか」を検証すること。
まずは以下のコード。

var f = function() {
  alert((this === window));
};

f();     // true
new f(); // false

windowのコンテキストで単に呼ぶとthisがwindowになる。
これは普通の挙動として知ってはいた。

本命は以下。

var f = function() {
  alert((this === window));
};

var Foo = new function() {};
Foo.prototype.normal = function() { f(); };
Foo.prototype.create = function() { new f(); };

var foo = new Foo();

foo.normal(); // true
foo.create(); // false

他クラスのインスタンスのコンテキストで呼んでみたらwindowじゃなくてインスタンスがthisになるんじゃないかと思ったけど、
そうでもないらしい。
どこから呼ぼうとapplyなどでコンテキストを明示しない限りwindowをthisとして実行されるようだ。


つまり、if (this === window)でコンストラクタとして呼ばれたかどうかが分かるわけで・・・フフフ

Catalyst/PSGIに入門。

遅まきながら、perlの必修項目としてCatalystPSGIに入門することにした。


まずはcpanで以下をインストール。

Plack
DBIx::Class
Template
Catalyst
Catalyst::Devel
Catalyst::Engine::PSGI

したらworkspaceで

$ catalyst.pl MyApp

これで原型ができる。
次にplackupするために

$ cd MyApp/
$ ./script/myapp_create.pl PSGI

すると"script/myapp.psgi"が生成される。
このままplackupしたいところだけど、

Can't Locate MyApp.pm

と怒られてしまうので、psgiファイルにちょっと手を入れる。
冒頭の

use MyApp;

より前に

use File::Basename;
use lib sprintf("%s/../lib", dirname(__FILE__));

を追加する。
これでCatalystのファイルレイアウトに合った形になるので、

$ plackup script/myapp.psgi

で起動可能。


今日はこれだけ!

bashのパス補完で.svnを無視する。

bashのTabによるパス補完。
もうこれなしでは生きていけないんだけど、たまーに不便に思うときがある。


それはsvnのworking copyをcdで潜っていくときのこと。

/home/shellcat/repos/workspace

リポジトリをチェックアウトしたとして、

workspace/perl/FooBar/trunk/Foobar

という風になったとする。
このとき/home/shellcatから移動しようとすると、mainより下に行くときに
Tab補完が.svnのせいでチマチマ止まる。
最初の1文字を入力すれば補完が効くけど次の階層でまた止まる。


これがちょっとしたストレスだったんだけど、ようやく解決法を知ることができた。


~/.bashrcにて

export FIGNORE=${FIGNORE}:.svn

PATHのexportと同じ文法でFIGNOREの値に.svnを加える。
そうすると.svnっていう名前が補完の候補から外れるので、Tab連打で降りていくことができる。


超気持ちいい!

expectスクリプトまつがい。

#!/bin/bash

set timeout 20
spawn ssh hogehoge.com
expect "password :"
send "fizzbuzz"
interact

こうやって書いたら「spawn not found」とか言われた。

確かにspawnってコマンドはインストールされてないな・・・






とか思ってたwwwwwwwwwwwwwwwwwww


spawnってexpect専用ワードじゃんwwwwwwwwwwwwwwwwwwwwwww


orz


↓これが正解。

#!/usr/bin/expect

set timeout 20
spawn ssh hogehoge.com
expect "password :"
send "fizzbuzz"
interact


expectってシェルなのね・・・