Personal tools
You are here: Home ブログ 井上
« March 2008 »
Su Mo Tu We Th Fr Sa
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Recent comments
Re:Software Design 2008年2月号「Emacsマスターへの道」の原稿を公開 elim 2008-07-25
Re:Rails(ActiveRecord)のJOINのイディオム inoue 2008-06-20
Re:「ピアレビュー」を読みました Anonymous User 2008-05-12
Re:「ピアレビュー」を読みました inoue 2008-05-10
Re:「ピアレビュー」を読みました Anonymous User 2008-05-09
Re:「ピープルウェア」再読 inoue 2008-04-20
Re:僅か30分で3つのバグ - Rubyの落し穴 - inoue 2008-04-20
Re:僅か30分で3つのバグ - Rubyの落し穴 - rubikitch 2008-04-19
Re:ソフトウェアインスペクションの試行 horii 2008-03-31
Re:「ピープルウェア」再読 anaka 2008-03-31
Re:WEB+DB Press Vol.43の記事への指摘 yanagisawa 2008-03-25
Re:マルスケと月刊I/O あなか 2008-03-23
Categories
カテゴリなし
 
Document Actions

縦置きモニター(続き) 1200x1920


24インチの液晶モニタを買いました。 ワイドモニタを自分で買うことはないと思っていましたが、売っているのがワイドモニタばかりなので、ワイドモニタを購入しました。

結論から言うと、つないだだけでは映りませんでした(debian etch)。 Xの設定をいじるのは何年ぶりか覚えていないぐらい久しぶりです。 感慨深さのかけらもありません。本当に不毛な作業です。

次の設定で1200x1920で表示できるようになりました。 915resolutionが必須なのかは検証していません(不毛さに疲れました)。

915resolutionパッケージをインストール
# aptitude install 915resolution

# vi /etc/default/915resolution
に次を記述

MODE=5c
XRESO=1920
YRESO=1200
BIT=32

# dpkg-reconfigure xserver-xorg
で対話的に/etc/X11/xorg.confの設定

dpkg-reconfigure xserver-xorg で完璧にハードウェア情報を自動取得してくれますが、Xを起動すると、無惨にも out of range とモニタに表示されます。 Monitorセクションに次のようなModelineを書き加えると、表示できるようになりました。

Section "Monitor"
      Identifier      "Generic Monitor"
      Option          "DPMS"
      HorizSync       30-83
      VertRefresh     56-76
      Modeline        "1920x1200" 154 1920 1968 2000 2080 1200 1203 1209 1235
EndSection

証拠

/Members/inoue/images/1920.png

10年以上前から、コンピュータのハードウェアの最も貴重なリソースは、CPUでもメモリでもディスクでもなく、また使いやすいキーボードでもなく、モニタの縦のピクセル数だと主張してきました。1920ピクセルを手に入れた今の感想は...もうどうでもいい...です。上の方を見るの疲れるし。もっと高い椅子が必要なのかもしれません。高いと言っても値段ではなく、座高の話です。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/1920pixels/tbping

Javaでタプルを返したけれど

「Javaでタプルを返したい」

上の結果、Tuple.javaがコミットされたのですが、その後、なんとTuple3.javaとTuple4.javaまでコミットされました。 こうなった原因は、元の命名が悪かったせいではないかと予想します。 次のようにすべきでした。

public class ConsCell<L,R> {
    public static <L,R> ConsCell<L,R> cons(L car, R cdr) {
        return new ConsCell<L,R>(car, cdr);
    }
    
    public final L car;
    public final R cdr;

    public ConsCell(L car, R cdr) {
        super();
        this.car = car;
        this.cdr = cdr;
    }

    // you can use methods if you want
    public final L car() {
        return car;
    }
    public final R cdr() {
        return cdr;
    }
}

つまらない落し穴があります。

ConsCell<String,String> c = ConsCell.cons("foo", "baz");
ConsCell<String,String> c = ConsCell.cons("foo", null);

これらはOK。

ConsCell<String,ConsCell<String,String>> lst = ConsCell.cons("foo", ConsCell.cons("bar", "baz"));

これもOK。

ConsCell<String,ConsCell<String,String>> lst = ConsCell.cons("foo", ConsCell.cons("bar", null));

これはコンパイルエラー。

ConsCell<String,ConsCell<String,String>> lst = ConsCell.cons("foo", ConsCell.cons("bar", (String)null));
System.out.println(lst.car);
System.out.println(lst.cdr.car);

キャストすると通ります。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/java-conscell/tbping

RubyはJavaより難しい(と思う) - Railsの acts_as の話 -

Rubyはやはり難しいです。

まず記号が多い点があげられます(http://www.ruby-lang.org/ja/man/html/Ruby_A4C7BBC8A4EFA4ECA4EBB5ADB9E6A4CEB0D5CCA3.html#a.3a)。一般的には、記号の多さは可読性を落とす気がします。 そして、(Railsが顕著すぎるのかもしれませんが)メタプログラミングの多用があります。メタプログラミングはクールですが、一般的には分かりやすいコードとは言えません。 そして、個人的見解ですが、そもそも未だに動的型言語が正しいとは思えていません。変数の型を明示しないことが便利に働く場面があることは認めます。Cで言えば、プリプロセッサマクロやvoidポインタで多態的なコードを書くような場面です。しかし、多く見積もっても、型を明示しないことが便利なケースは全体の20%程度だと思います。20%は結構多く見積もっているつもりです。残り80%は、変数に型を明示した方が可読性が上がると思います。書く側にも読む側にも安心感が得られるからです。そしてコンパイルさえ通せば、想定している型と違うオブジェクトだったという、あまりに基本的なバグから(ほぼ)逃れられます。

ぼくがプログラミングで最も重視するのは、読み手のコストです。読み手のコストを減らすためには、書き手は相当のコストを背負っても良いと思っています。

と、Ruby大嫌い人間みたいですが、Rubyの話です。

Ruby on Railsのpluginのコードの話です。acts_as_listを例にコードを見てみます。コード例はv2.0.2ベースです。

init.rbは以下のようになっています。

$:.unshift "#{File.dirname(__FILE__)}/lib"
require 'active_record/acts/list'
ActiveRecord::Base.class_eval { include ActiveRecord::Acts::List }

これを呼び出す場所は調べていませんが、pluginsディレクトリ下にあるinit.rbをロードする処理がどこかにあるはずです。

最初の行はロードパス変数 $: (型はArray) に相対パスを挿入しています。次の行で相対パスのlist.rbファイルをロードします。list.rbファイルは後で見ます。 3行目で、既存クラスの ActiveRecord::Base にモジュールをincludeしています。class_evalに渡すブロック内の self はActiveRecord::Baseのクラスオブジェクトを参照しています。 ここは、次のように書いてもいいはずです。

class ActiveRecord::Base
  include ActiveRecord::Acts::List
end

list.rbの骨子だけ抜き出すと次のようなコードになっています(コメントはごっそり削除)。

module ActiveRecord
  module Acts #:nodoc:
    module List #:nodoc:
      def self.included(base)
        base.extend(ClassMethods)
      end

      module ClassMethods
        def acts_as_list(options = {})
          configuration = { :column => "position", :scope => "1 = 1" }
          configuration.update(options) if options.is_a?(Hash)

          configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/

          if configuration[:scope].is_a?(Symbol)
            scope_condition_method = %(
              def scope_condition
                if #{configuration[:scope].to_s}.nil?
                  "#{configuration[:scope].to_s} IS NULL"
                else
                  "#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}"
                end
              end
            )
          else
            scope_condition_method = "def scope_condition() \"#{configuration[:scope]}\" end"
          end

          class_eval <<-EOV
            include ActiveRecord::Acts::List::InstanceMethods

            def acts_as_list_class
              ::#{self.name}
            end

            def position_column
              '#{configuration[:column]}'
            end

            #{scope_condition_method}

            before_destroy :remove_from_list
            before_create  :add_to_list_bottom
          EOV
        end
      end

      module InstanceMethods
        def insert_at(position = 1)
          insert_at_position(position)
        end
        多くのメソッド...(略)
      end 
    end
  end
end

このコードをぱっと見て、どこがどんなタイミングで呼ばれるかすぐに分かればすごいです。少なくともぼくは分かりません。

Rubyの考え方として、上のinit.rbからrequireされたタイミングで、list.rbのコードがすべて評価される(実行される)と考えてください。例えばもし、module Listの行の下に print "foobar" と書いてあれば、requireされた直後に foobar が出力されます。実際のlist.rbの中にはdefしかないので、defの中身はメソッド定義として評価され、中身が実行されるのは各メソッドが呼ばれた時になります。

最初のポイントは、self.included がinit.rbの3行目のincludeのタイミングで呼ばれることです。includedメソッドの動作は次のようにirbで確認できます。

irb> module M
       def self.included(m)
         p "M included"
       end
     end

irb> class C 
       include M
     end
"M included"

includedメソッドの中身は base.extend(ClassMethods) です。この base は ActiveRecord::Base のクラスオブジェクトを参照しています。extendはオブジェクトにモジュールを加えるメソッドです。この場合、クラスオブジェクトにモジュールをextendしているので、意味的には次と同じ処理になります。

class ActiveRecord::Base
  class << self
    include ClassMethods
  end
end

ClassMethodsの中にはacts_as_listがあります。これは次のように呼ばれることを想定しています(Booksは開発者が作るクラス)。

class Books < ActiveRecord::Base
  acts_as_list
end

上のように呼ばれると、acts_as_list内のclass_evalが実行されます。この時、class_eval内の self は Books を参照しています。意味的には次のようなincludeと同じになります。

class Books
  include ActiveRecord::Acts::List::InstanceMethods
end

これでめでたくBooksクラスのオブジェクトは、InstanceMethodsモジュールのメソッドを使えるようになりました。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/ruby-is-hard/tbping

tracの集計処理結果をGoogle Chart APIでグラフ化するブックマークレット

tracでは、SQLを書くだけで集計処理が簡単にできます(参考 http://dev.ariel-networks.com/column/tech/tracreport-tips/view)。

例えば、次のような集計結果があるとします。カラムの意味は企業秘密なので書けません。

/Members/inoue/images/trac/trac-list.png

この第3カラムの値の変化をグラフ化するために、Google Chart APIを使ってみました。

CSV形式で表示して、データ部分を選択します。

/Members/inoue/images/trac/trac-list-csv.png

次のブックマークレットを実行します。言うまでもありませんが、ブックマークレットと言ってもブックマークする必要はありません。単にブラウザにURLとして解釈させれば良いだけです。URL欄にでもペーストしてください。getSelection()を使っているので、IEでは動きません。

javascript:(function() {location='http://chart.apis.google.com/chart?chs=800x200&cht=lc&chd=t:' + getSelection().toString().replace(/[^,]*,[^,]*,([^, ]*)/g, '$1,').replace(/(.*) $/, '$1').replace(/(.*),$/, '$1');})()

文字列をsplitして配列にする方が楽なのですが、変数使ったら負けな気がしたので、文字列操作だけでがんばってみました。しかし、時間軸の新しい方がグラフの左側になって見辛いので、結局、配列を使って次のように書き直しました。試合に負けて勝負に勝った、ようなものでしょうか。

javascript:(function() {var a = getSelection().toString().split(' ').reverse(); var a2 = [];for (var i = 0; i < a.length; i++) { if (a[i]) {a2.push(a[i].split(',')[2]);} }; location = 'http://chart.apis.google.com/chart?chs=800x200&cht=lc&chd=t:' + a2.join(',');})()

グラフは次のようになりました。

/Members/inoue/images/trac/trac-graph.png

一番気にいらない部分は、getSelection()でデータを取得しているので、わざわざ必要な部分を選択しなければいけない部分です。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/trac-to-google-chart/tbping

Rubyの好きなところと嫌いなところ

最初、Rubyのブロックを良いとは思いませんでした。他の言語の経験もあるので、概念自体はすぐに分かりました。スコープを考えなければ関数オブジェクト、スコープを考えればクロージャが、引数に見えないシンタックスで引数で渡る仕組みです。良いと思わなかった点は、どうせ関数オブジェクト(クロージャ)作っているなら、作っていることが明示的な方が良いし、引数で渡すなら、引数らしく見える方が良いと思ったためです。JavaScriptやLispのように、記述が明示的な方が良いと思ったのです。

慣れというのは恐ろしいもので、今はRubyで一番好きなところがブロックです。明示的に関数オブジェクトを作っていないように見えることや、引数に見えないことが、これほどの表現力を生むとは予想外でした。railsもまあまあですが、rakeの方が感動しました。

以前なら、プログラミング初心者に、Perl、Python、Rubyは何が違うんですか、と聞かれたら、似たようなものです、シンタックスは違いますが、それはささやかな違いです、と答えていました。シンタックスの違いは、Lispぐらい違えばともかく、Perl、Python、Rubyぐらいの差ならささやかなものだと思っていました。Rubyを知って、考えを改めました。小さなシンタックスの違いが大きな表現力の差を生むからです。

嫌いなところもあります。一番嫌いな部分は、ローカル変数の参照とメソッド呼び出しの区別をするために、コードの上に向かって(ローカル変数の)初期化があるかを探さなければいけない点です。

次のようなコードがある時、barがローカル変数の参照なのかメソッド呼び出しなのかを知るために、引数にbarがあるか(あればbarは引数のbar)、コードXの部分に bar = の行があるかを調べる必要があります。

def foo(引数)
  ...コードX...
  p bar
end

もう少し具体的に書くと次のようになります(かなり恣意的なコードです)。

#!/usr/bin/ruby
class My
  def initialize
    @foo = 2
  end
  def foo
    p 'foo called'
    @foo
  end
  def foo=(n)
    p 'foo= called'
    @foo = n
  end

  def doit
    p foo             # メソッドfooの呼び出し
    foo = 0           # ローカル変数fooの初期化
    p foo             # ローカル変数fooの参照になる
    self.foo = 1      # メソッドfoo=の呼び出し
    p self.foo        # メソッドfooの呼び出し
  end

end

obj = My.new
obj.doit

何が一番気にいらないかと言うと、=のついたメソッド(上の例で言えばfoo=)は必ずself付きで呼ばざるを得ない非対称性です。名前が被った時にselfで限定しなければいけない問題(上の例で言えばself.foo)は、JavaでもC++でもあるので気になりませんが、self.foo=に関しては、文法規則と被るので限定しなければいけない点が気持ち悪いです。

慣れとは恐ろしいもので、まあ別にいいか、という気分にもなっていますが。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/ruby-love-and-hate/tbping

WEB+DB Press Vol.43の記事への指摘


下記の件、裏を取ってから書こうかと思ったのですが、まだ裏を取っていません。

WEB+DB Press Vol.43に「コンピュータが扱う数字」という記事を書きました。

読者の柳澤さんからありがたい指摘をいただきました。 まずはお誉めの言葉(社交辞令とも言う)から。

さて、WEB+DB Press Vol.43 の「コンピュータが扱う数字」という記事を興味深く拝読いたしました。 私自身啓蒙される所がありましたし、新人の教育用などにもこの記事を有効利用させていただきたいと存じます。

指摘はここから。

「1の補数」が123ページにて「1's complement」と表記されている点です。 ビット反転を表す「1の補数」は、「2の補数」と違って「1たち(複数形)の補数」という意味ですので、 その英語表記は正しくは「1s'/ones' complement」となります。

更に

なお、「1の補数」を「ones' complement」と表記すべきだということの根拠としては、たしか私の記憶に間違いがなければ、 D. Knuth の The Art of Computer Programming のarithmetic calculations の章に記数法を扱った部分があったと思うのですが、 その中のどこかに関連する記述があったように思います。

柳澤さんからは、誤植だったらすいません、と心遣いをしてもらいましたが、単純に無知ゆえに知りませんでした。持っている(大学で使った)教科書にも one's complement と書いてあるし。言い訳ですが。

なお、柳澤さんが勤めている会社名の公開は自由と承諾を得ましたが、社長が牧野さん、でとどめておきます。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/number-article/tbping

Re:WEB+DB Press Vol.43の記事への指摘

Posted by yanagisawa at 2008-03-25 07:50
こんにちは、柳澤です。
私のつまらない指摘をわざわざお取り上げいただき恐縮です。

>下記の件、裏を取ってから書こうかと思ったのですが、まだ裏を取っていません。

個人的に気になったので、書店で立ち読みして確認したところ、
D. Knuth, The Art of Computer Programming の邦訳 Volume 2 の 191 ページに記述がありました。
いわく、「2の補数」は2の冪乗である単一の数と相補的であるのに対して、
「1の補数」は個々のビットがそれぞれ1と相補的なのであるから、
アポストロフィの位置は ones' complement とするのが正しいのである、と。

Ruby on Rails - ActiveRecord - 勉強会資料

「Ruby on Rails - ActiveRecord - 勉強会」資料を公開しました。

どんなSQLが発行されるか確認しないと、恐くてORMを使えない人向けです。

http://dev.ariel-networks.com/Members/inoue/ruby-article に、Rails勉強会は来月もしくは来年と宣言していたので、約束は守っています。RailsのWeb周りの勉強会はいつになることやら。今年中にはやりたいものです。

諸般の事情により、Javaの勉強会をはさむかもしれません。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/rails-activerecord/tbping

タイムエイドでミーティングの時間管理

会議室に時計があればミーティングの時間が短くなるかと期待していましたが、あまり効果がありません。もっと、脅迫的にカウントダウンしてくれる代物が無いものでしょうか。

「ミーティングタイマー」という、これは、と思わせる名前の製品がありました。

しかし、これはイメージと違います。これでは、ただの目覚し時計です。

「タイムタイマー」という製品がありました。

「残り時間が減っている感」があって良い感じです。

この製品、ミーティングの時間管理が目的ではなく、タイムエイドと呼ばれる時間感覚の無い障害者向けの製品のようです。

このぐらいなら、わざわざ購入しなくても、PC上で簡単に再現できそうです。

「時計型カレンダーをcanvasで実装」(http://dev.ariel-networks.com/Members/inoue/clock-calendar)の時のコードを少し改造して、作ってみました。

指定時間(デフォルトは1時間)経つと、ミーティングをやめるようにと懇願が始まります。 1時間待てない人のために、Quick modeもつけました(トグル動作でないのは仕様です)。

JavaScriptのみなので、ファイルさえ持っていれば、オフラインでも動きます。ただし、canvasを使っているので、IEでは動きません。

The URL to Trackback this entry is:
http://dev.ariel-networks.com/Members/inoue/mal9000/tbping

Copyright(C) 2001 - 2006 Ariel Networks, Inc. All rights reserved.