JDEEを使ってみる

Android書くときに、Eclipseもいいんだけど、やっぱり手馴れたエディタを使いたいよねってことでJDEEを試してみる。

というわけで、自分用コマンドリファレンス。

インストール

http://jdee.sourceforge.net/
JDEEとelibをダウンロードしてmake install

設定

Android SDK にもパスを通しておく
JDKのバージョンとか場所は適宜。書いてあるのはUbuntu環境でのもの。

;; jdee
(add-to-load-path "elib")
(add-to-load-path "jdee/lisp")
(autoload 'jde-mode "jde" "Java Development Environment for Emacs" t)
(setq auto-mode-alist (cons '("\.java$" . jde-mode) auto-mode-alist))

;; cedet
(add-to-load-path "cedet/cogre")
(add-to-load-path "cedet/common")
(add-to-load-path "cedet/contrib")
(add-to-load-path "cedet/ede")
(add-to-load-path "cedet/eieio")
(add-to-load-path "cedet/semantic")
(add-to-load-path "cedet/speedbar")
(add-to-load-path "cedet/srecode")

(setq semantic-load-turn-useful-things-on t)
(load "cedet")
;;(semantic-load-enable-code-helpers)

;; jde-mode-config
(custom-set-variables
 '(jde-jdk-registry (quote (("1.6.0.24" . "/usr/lib/jvm/java-6-sun/"))))
 '(jde-global-classpath (quote (
                                "~/lib/android-sdk/platforms/android-4/android.jar"
                                "~/lib/android-sdk/platforms/android-7/android.jar"
                                "~/lib/android-sdk/platforms/android-8/android.jar"
                                "~/lib/android-sdk/platforms/android-10/android.jar"
                                "~/lib/android-sdk/platforms/android-11/android.jar"
                                ))))

(add-hook 'jde-mode-hook
          '(lambda ()
             (c-set-offset 'arglist-intro '+)
             (c-set-offset 'arglist-close 0)
             (c-set-offset 'topmost-intro-cont 0) ;; new line on annotation
             (c-set-offset 'func-decl-cont 0)
             (setq indent-tabs-mode nil)
             (setq c-basic-offset 4)
             (setq c-set-style "java")
             ))

;; custom variables
(setq compilation-window-height 8)
(setq bsh-vm-args '("-Duser.language=en"))
(setq jde-import-auto-sort t)

;;; ant on jdee
(setq jde-build-function '(jde-ant-build))
(setq jde-ant-enabled-find t)
(setq jde-ant-program "/usr/bin/ant")
(setq jde-ant-read-target t)

;;; check style on jdee
(setq jde-checkstyle-option-rcurly (list "alone"))

(let ((elem (assq 'encoded-kbd-mode minor-mode-alist)))
  (when elem
    (setcar (cdr elem) "")))

コマンドリファレンス

  • テンプレート生成
Key Event
M-x jde-gen-class クラスのテンプレート生成
M-x jde-gen-xxx テンプレート自動生成
M-x jde-gen-get-set or M-x jde-wiz-gen-get-set-method Getter/Setter 生成
M-x jde-wiz-implement-interface インターフェースの実装ひな形生成
C-c C-v C-o オーバーライドメソッドのひな形生成 (jde-wiz-override-method)
Key Event
C-c C-v C-c コンパイル
C-c C-v C-r 実行
C-c C-v C-b antビルド
C-x ' or M-g n 次のエラー箇所へジャンプ
M-g p or M-g M-p 前のエラーへジャンプ
C-c C-v C-d デバッガ起動
M-x jde-bug-set-breakpoint カーソル位置にブレークポイントを設定
M-x jde-bug-clear-breakpoint カーソル位置のブレークポイント解除
M-x compile => ant -emacs build.xmlに従ってビルド
M-x compile => ant -emacs junit junitの実行
コンパイルエラー表示行でC-m エラー行へジャンプ
  • Import
Key Event
C-c C-v z 必要なimportをすべて追加する (jde-import-all)
C-c C-v C-z import文単体の挿入
M-x jde-import-kill-extra-imports 不要なimport文を削除
  • Edit
Key Event
C-c C-v C-. コード補完 (jde-complete)
C-c C-v C-l println
C-c C-v C-y カーソル位置のクラスのソースを表示
C-c C-v C-w カーソル位置のクラス名のマニュアルを表示
C-c C-v j Javadocコメント生成
C-c C-v C-s Speedbar起動
C-c C-v C-n JDKのドキュメントを表示
C-c C-v C-w クラスのJDKドキュメントを表示
C-c . 編集スタイルの切り替え
  • Othres
Key Event
M-x jde-chckstyle checkstyle
C-c C-v C-f プロジェクト内のgrep検索 (jde-find)
M-x jde-find-dig 実行時に設定可能なgrep検索
M-x jde-bsh-exit BeanShellの終了

Linux Kernelをビルドする

環境: Ubuntu 11.04 (VMWare fusion)

準備

$ sudo apt-get install build-essential
$ sudo apt-get install kernel-package libncurses-dev ncurses-dev libqt3-mt-dev

ソースを用意する

$ sudo apt-get install linux-source-2.6.38

$ cd /usr/src
$ sudo tar xvfj linux-source-2.6.38.tar.bz2
$ cd linux-source-2.6.38

バグフィックス

via https://bugs.launchpad.net/ubuntu/+source/linux/+bug/505420

$ ln -s /usr/src/linux-source-2.6.38/ubuntu /ubuntu

config

いったん設定初期化してから設定画面を立ち上げる。

$ sudo make mrproper
$ sudo make menuconfig
変更するconfig

Core i7 の 4coreでこんな感じの設定にしてみた。

Processor type and features:

Processor family > Core 2/newer Xeon
Maximum number of CPUs > 8
Preemption Model > Preemptible Kernel(Low-Latency Desktop)
Timer frequency >1000Hz
現在の設定をそのまま使うとき
$ sudo cp /boot/config-2.6.35-24-server .config
$ sudo make oldconfig

カーネルバージョンを変える

Makefileの4行目を書き換える

EXTRAVERSION=.3 

コンパイル

revisionは数値のみ指定できるみたい。適当に日付を指定。

$ make-kpkg clean
$ make-kpkg -j8 --initrd --revision=yyyymmdd kernel_image kernel_headers

20~30分かかりました。

インストール

$ dpkg -i ../linux-image-2.6.38_yyyymmdd_amd64.deb

再起動して完了。

TokyuRuby会議03で酔ってきました

というわけで、先週日曜に開催されたTokyuRuby会議03で盛大に酔いを晒してきました。

http://regional.rubykaigi.org/tokyu03
当日の様子: http://togetter.com/li/143092

勧められるがままにビールを空けていたら、いつのまにやら・・・
本当にすいません。

さて、本人は全く覚えてないのですが、抽選LT用に作っていた資料で話したらしいです。お酒って怖いですね。

一応資料上げておきます。
http://gomlog.com/docs/tqrk03/slides.html

最近はAndroid漬けな日々なので、それとRubyをからめてRubotoの紹介です。


迷惑をかけた方々、すみませんでした。
スタッフの皆様、おつかれさまでした。

メソッドの呼び出し方

PHPでは、static宣言なしでもメソッドのstatic呼び出しができてしまう。
で、どっちが速いの?という話。
メモリの使用量も比べてみたかったけど、速さのみ。

<?php
require_once 'Benchmark/Timer.php';

class MyTest {
  public function myMethod() {
    return;
  }
  public static function staticMethod() {
    return;
  }
}

$max = 100000;
$timer = new Benchmark_Timer();
$t = new MyTest();

$timer->start();

for($i = 0; $i < $max; $i++) {
  MyTest::staticMethod();
}
$timer->setMarker('static');

for($i = 0; $i < $max; $i++) {
  MyTest::myMethod();
}
$timer->setMarker('static2');

for($i = 0; $i < $max; $i++) {
	$t->myMethod();
}
$timer->setMarker('instance');

$timer->stop();
$timer->display();

/*
------------------------------------------------------
marker    time index            ex time         perct   
------------------------------------------------------
Start     1293934691.81032700   -                0.00%
------------------------------------------------------
static    1293934691.85720200   0.046875        21.74%
------------------------------------------------------
static2   1293934691.99593900   0.138737        64.35%
------------------------------------------------------
instance  1293934692.02592700   0.029988        13.91%
------------------------------------------------------
Stop      1293934692.02593700   0.000010         0.00%
------------------------------------------------------
total     -                     0.215610       100.00%
------------------------------------------------------
*/
$ php --version
PHP 5.3.3 (cli) (built: Aug 22 2010 19:41:55)

static宣言なしのメソッドをstaticに呼ぶのは遅いってことかしら。

ちなみにrubyだとこうなった。
static methodは存在しないので、class method。このへんはうろ覚えなので、ちょっと自信ない・・・

require 'benchmark'

class MyTest
  def myMethod
    1 + 2
  end

  def self.classMethod
    1 + 2
  end
end

module MyModule
  def moduleMethod
    1 + 2
  end
end

module MyModule2
  def moduleClassMethod
    1 + 2
  end
end

max = 100000;

Benchmark.bmbm(10) do |x|
  t = MyTest.new
  x.report("instance: ") {
    max.times do
      t.myMethod
    end
  }

  x.report("class   : ") {
    max.times do
      MyTest::classMethod
    end
  }

  MyTest.class_eval {
    include MyModule
  }
  t = MyTest.new
  x.report("module : ") {
    max.times do
      t.moduleMethod
    end
  }

  MyTest.extend MyModule2
  x.report("module class : ") {
    max.times do
      MyTest::moduleClassMethod
    end
  }
end
Rehearsal ---------------------------------------------------
instance:         0.040000   0.000000   0.040000 (  0.043314)
class   :         0.050000   0.000000   0.050000 (  0.049375)
module :          0.040000   0.000000   0.040000 (  0.042887)
module class :    0.050000   0.000000   0.050000 (  0.045320)
------------------------------------------ total: 0.180000sec

                      user     system      total        real
instance:         0.040000   0.000000   0.040000 (  0.042020)
class   :         0.040000   0.000000   0.040000 (  0.046069)
module :          0.040000   0.000000   0.040000 (  0.041350)
module class :    0.040000   0.000000   0.040000 (  0.045474)
$ ruby --version
ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10]

マージソート

基本に立ち戻って、マージソートをやってみた。
Ruby, C, Scala, Gaucheの4種類。
最初にRubyで書いて、他に移植という流れ。


ScalaGaucheはほぼ同じ。普通に再帰で書いたけど、Scalaは末尾再帰に最適化されてるそうな。


Cだけは配列をガンガン作ろうとするとmallocが大変なことになるので、1つを使いまわす形に。
tempはmallocしないで静的に定義してもいいかも。
Cはまだまだ慣れない。


Ruby

C

Scala

Gauche

Google Readerの"v"で背面にタブを開くChrome拡張を作りました

た。
Google Reader Open entry in background tab - Google Chrome extension gallery

いくつか既存のがあるのですが、1度に複数タブが開いてしまったりキーが他のだったりで自分の使い方にはあわなかったので、
作ってしまいました。

とりあえず最低限の機能だけ付けて公開しています。
バグとかこうして欲しいみたいなのがあったらコメントでください!

雑感とか

  • Chrome 拡張は開発しやすい。デバッガが素敵!!
  • Javascriptをまともに書いたことなかったので、DOMのイベントリスナ周りで四苦八苦
  • Star openerも付けたい
  • キーも入れ替えられるようにしたい

東京Ruby会議#03に行ってきた

とても内容が濃く、充実した会議(講義?)でした!
スタッフ・講師の皆様お疲れ様でした。


セッションがかなりヘビーというか、Rubyの実装周りの話がてんこ盛りで
ついていくのがやっと or ついていけてない部分もありました。
でも、勉強になる部分がとても多かったです。


勉強不足を痛感したので、さらに頑張ろうっと。

会議自体へのフィードバック

  • 喫茶無償++
  • 今度はGCの話とか聞いてみたい!


というわけでメモ公開。
聞くだけでもいっぱいいっぱいだったので、正確ではないかもしれません。


Yuguiさん メタプログラミング



  • メタプログラミングとは

  • Rubyにおける特性

  • 道具立て

  • 用例


メタプログラミングとは


プログラムをプログラミングすること




  • ループ

    • 繰り返し


  • 例としてのアクセサ

    • getter/setter をメタプロ



Rubyの特性


  1. S式ではない!

  2. First Class Object

  3. コンパイルがない


非S式


  • メタプログラミングといえばLisp

  • Rubyには?

    1. ブロック

      • proc


    2. 文字列

      • 文字列を生成してeval

      • eval<<-EOS, binding,FILE, __LINE__+1を渡して、スタックトレースを読めるようにする




コンパイルがない


  • 実行時間とコンパイル時間が同一=隠蔽している

    • 内部的にはASTに変換、1.9ではコンパイルしている




  • 副作用が気軽に使える

  • classは定義ではなく、副作用を持つ式である

    • クラスの継承元すら動的に定義できる

    • メソッド定義も条件式で分岐させるなど

    • 動的すぎるため、最適化が難しい。rubyを遅くしている原因のひとつ


  • C++では?

    • Templateでできる。けどつらい。

    • コンパイル時に決まってしまう

    • Boost MPLライブラリを使う


  • 副作用の代表格: IO



  • 構文の変更不可

  • Lispだとリーダーマクロ

    • Matzter Yoda はマクロを否定

    • Rubyでは予約語の変更ができない


  • Rubyでは言語内DSLが不能

    • ブロックを使って言語内DSLを実現可能



ex.) Rake
task :a, do... end


  • マクロではなく、ブロックでバランスをとる

  • Rubyのメタプログラミングに不安を感じる人はJavaへ。


道具立て


  • class

    • 特異クラス


  • callable object

  • eval族

  • method_missing, send


class


  • Classクラスのインスタンス

  • クラス階層

    • BasicObject

    • Object

    • Module

    • Class


  • 特異メソッド

    • クラスのあるインスタンスにだけ存在するメソッド

    • クラスメソッドとして頻繁に使用




  • 特異クラス

    • 元クラスから継承したクラスに内部的に付け替える


  • 特異クラスの定義イディオム


eigenclass = (class << obj; self end)


  • 特異メソッドは内部で特異クラスを定義している


obj = Object.new
class << obj
def foo; end
end


  • クラスメソッド

    • 実際はClassオブジェクトの特異メソッドを定義している

    • つまり親クラスの特異メソッドとして扱われているだけ。特殊な定義ではない。

    • クラスのクラスはメタクラス


  • 全てのクラスはClassクラスの特異クラス

    • 図が欲しい。 => yuguiさんのflikr


  • メタクラスのクラスはメタメタクラス

  • boot時にメタクラスを全て作るとメモリがなくなる。


呼び出し可能オブジェクト


  • Object

    • Proc

    • Method

    • UnboundMethod

    • Continuation





  • 相互変換可能


eval族


  • eval

  • instance_eval

  • class_eval



  • current class

  • TOP LEVEL

    • self: main

    • current class: Object


  • class expr

    • self: the class

    • cc: the class


  • def expr

    • self: insatnce

    • cc: NONE




  • コンテキストについて



  • instance_eval

  • self: instance

  • cc: eigenclass

    • レシーバの特異クラス




  • class_eval

  • self: class

  • cc: class



  • eval

  • コンテキストはbindingに依存 (引数で指定)


用例集

メソッド定義


  • define_methodでのブロック定義より、eval+heredoc の方が実行速度は早い

    • railsはeval多用

    • define_methodならシンタックスハイライトとかシンタックスエラーを検出



メソッドをまとめて定義


  • 継承元クラスで実装が必要なメソッドにまとめてエラー定義


クラス定義

DSL


  • メソッド内でサンドボックスとなるオブジェクトを提供し、そこにModuleをextend。instance_evalで評価することで

    そのメソッド内のみでModuleの機能を使用可能


モジュール定義


  • サンドボックス定義

    • 評価するブロック内で変数を定義されたりしても、予期せぬ書き換えなどが防げる



def sandbox(block)
Module.new(&block)
end


  • リモートのdrbのプロセス状態を、手元の端末からirb相手側のプロセスにinstance_eval流し込み

    • リモートプロセスのirbを汚染しないため、生成したirbセッションで特異メソッド定義

    • printなどはリモートから手元の端末のIOに逆転送するようにメタプロ


  • drbのポートを不用意に開けておくとものすごく危険!


Rails 3 ハンズオン 松田さん


Rails 3とは?


  • beta版がリリースされている


インストール


  • gitプロトコルが通らない!

  • gemが入らない!

  • 環境は事前に準備しておきましょう。


アプリケーションを作成


  • コマンド出力がカラフル

  • .gitignore がデフォルト

    • 今後のバージョン管理はgitで!

    • .gitkeep もある




  • Model名にする予定のものはアプリケーション名にできない

  • Rubyのクラス名に使えないものはアプリケーション名にできない


HTML5準拠


  • jsが綺麗になった


Model


  • validates がカラムを基準にかけるようになった



A Reintroduction to Ruby i17n 成瀬さん



  • 日本に生まれたことを後悔したくなるらしい



  • 字体としては、JISでは同じだがUnicodeでは別

  • 符号化文字集合 = コードポイント

  • 文字符号化方式: 符号化文字集合の番号をバイト列に変換する

  • エンコーディングとは?

  • Charset: 各エンコーディングに名前をつけて管理するためのもの

    • 現実と仕様の乖離も存在する


  • 用語の整理


I18N


  • 略語まとめ

    • L10N (地域化)

    • I18N (国際化)

    • M17N (多言語化)



歴史


  • ASCIIが始まり

  • 拡張してみた

    • 大量の文字集合が・・・

    • 敵を知る。知った上で個別撃破


  • ISO 646 – 分裂の始まり

  • Unicode

    • 1つのUnicode文字列には複数の言語を混ぜられない

    • フラットな空間にすべての文字を入れる

    • 漢字統合: 言語の指定が必要

    • ASCIIも言語の指定が必要


  • Unicode以前の文字コードは?

    • CP932



円記号問題


  • バックスラッシュを円記号に変換してしまう

  • Shift_JISでの0x5C

  • Unicodeでは U+005C

    • Windowsでは日本語フォントだけ円記号にしている



波ダッシュ問題


  • U+301C (WAVEDASH)


機種依存文字


処理系の問題


  • 内部コードをどうするか?

    • UCS正規化: 内部では特定の1つに変換する

      • 内部コードを統一

      • 入出力時に変換を行う


    • CSI (Code Set Independent): それぞれの文字コードに対応する



Ruby1.9


  • 文字単位での処理

  • 正規表現エンジンが鬼車に

  • 文字型はなく、1文字Stringを使う

  • 文字型に必要なもの

    • コードポイント、エンコーディング


  • 1.9.1-p3xxや1.9.2では\wがASCIIのみにマッチするようになった

  • 適切にencodingを設定しておく


Magic Comment


  • デフォルトはASCII

  • ERBにも必要



<%= #coding : utf-8 %>



IOとEncoding


  • 入出力のEncodingを指定する

  • open (‘text.txt’, ‘r:UTF-8’)

  • ネットワークではバイナリ扱い => 強制指定 (force_encoding)する

    • socketやnet系のライブラリで必要

    • 濫用は避けましょう


  • KCODEはやめましょう



エンコーディング


  • ASCII互換

  • ASCII非互換

  • ダミー


エンコーディング変換


  • nkf

  • kconv

  • iconv

  • uconv

  • String#encode

  • Encoding::Converter



  • SJISWindows-31Jは混同しやすい

  • M17N未対応のライブラリを使った時など

    • ASCII-8BIT でかえされるので、明示的にエンコーディングを指定する



Ruby 1.9 での課題


  • 携帯絵文字: 対応中

  • 結合文字

    • 複数のコードポイントを1文字として扱う。濁音や半濁音など


  • 異体字セレクタ (IVS): Ideographic Variation Sequence

    • 結合文字同様、複数のコードポイントを1文字扱いする必要がある


  • 1つのStringに2つの言語を入れたい



  • 文字幅

    • 言語に依存して期待される幅が異なる


  • Unicode大文字小文字

    • ASCIIでしか動作しない


  • String#sort

  • 文字集合によって並び順が変わってしまう

    • sort_byで指定する




  • よいAPIを設計するには、ユースケースの収集が大事。feedbackが重要

  • Magic Commentを書け。


Open 3 のはなし 田中 哲 (akr)さん



  • Rubyからのプロセス起動

    • 問題点: system, IO.popen…




  • 解決

    • spawn メソッドの追加

    • open3ライブラリの追加



プロセス属性


  • ファイルディスクリプタ

  • Unixのプロセス起動はforkとexecを組み合わせる

    • 2つのコマンドの間にプロセス属性を変更することで、パイプやリダイレクトを実現する


  • Unix以外ではプロセス属性変更のために引数が複雑になりがち


Rubyで実現したいこと


  • OSが提供するプロセス起動機能を使いたい

  • シェルで出来ることをRubyでもやりたい

  • Unixと非Unixでの差異を吸収したい

  • よくやることは簡単に

  • できることはなんでもできる


API

既存のメソッドを拡張する?


  • forkは非Unixでは動きそうにない

  • system: プロセスを待たないようにするのは変

  • IO.popen: パイプなしは変

  • `command`: 構文上、指定を付加しづらい


新しいメソッドを作る


  • 要求が衝突する

  • よくやることを簡単にできる

  • なんでも可能なのが欲しい

  • => ひとつのメソッドで全ての要求を満たすのは困難



  • 高位・低位APIへ分割


ライブラリのレイヤ



  • どのレイヤのライブラリを提供するか?

  • 高位になるほどライブラリの自由度が高く「賢い」

  • 低位になるほど詳細な制御が可能になる

低位API: spawn


  • OS固有の機能も利用可能

  • OS間で共通の機能については差を気にしなくてよいくらいには高位


既存メソッドへの不満


  • 既存メソッドはシェルを呼び出す

    • シェルを呼びたくないこともある



基本の使い方

spawn(env, command, option)


pid = spawn("make all")
Process.wait pid


  • 引数を分けて与えるとシェルを経由しない


spawn("make", "all")


  • 最初の引数を配列にするとargv0も指定できる



  • リダイレクト


spawn("make all", :out => "make.log")

spawn("make all", :err => :out)

spawn("make akk", :out => :err, :err => :out)


  • パイプ


IO.pipe {|r,w|
spawn("ls", :out => w)
spawn("sort -r", :in => r)
}


spawn({LC => 'env'}, "ls -l")

spawnのデザイン


  • 多機能なものが単一関数でいいのか?

  • 簡単なことが難しくなっていいのか?

    • posix_spawnの複雑な引数を吸収している


  • 将来の拡張に耐えられるか?

    • キーワード引数


  • fdの扱いは適切か?

    • 最終的な状態を指定する

    • 3番以降のfdを継承しない

    • 子と親のfdの関係を書く




  • fork はメモリ内部もコピーする

  • Rubyでforkを避ける理由

    • NetBSD4ではforkした子プロセスではスレッドが動かない

    • Ruby1.9 ではタイマースレッドというスレッドを常に必要とするから




  • POSIXではfdに空きがないなどの理由で今のposix_spawnになった


spawnのまとめ


  • プロセスを起動するプリミティブ

  • fork + プロセス属性変更 + exec


高位API: open3


  • とりあえずシェルのパイプラインくらいまで提供

  • シェルの嫌なところは避ける

  • パイプよりも複雑な用途は今後の課題



  • 標準添付ライブラリ

  • 3つの標準パイプでコマンドと通信する

  • 命名はPerl由来


Open3.popen3("command") {|i, o, e|
# some script
}

既存のopen3nの問題


  • ゾンビの回収とdouble fork

    • 親がwaitせずに死ぬと、子はinitの養子になる

    • initはwaitしまくって亡骸を回収する

    • 意図的にdouble forkすることでゾンビを防止




  • double forkの問題点

    • pidを得られない: シグナルを送りづらい

    • 終了ステータスを得られない




  • open3 類が乱立


解決法


  • Process.detach によってwaitスレッドを生成することで解決



  • 標準エラー出力はパイプにしない方がよいことも多い

  • ひとつのパイプにして提供して、制御しやすくもできる


Open3で解決した問題

※ (問題自体を書き逃した)

  • Open3.capture*

  • Open3.popen2e*

  • Open3.pipeline*



  • spawnによるパイプラインは厄介

    • 大学の試験になるくらい




  • shell ライブラリ

    • shellの記法を模したDSL


*1:帰宅後にedgeの環境用意したけど、まだ試せていない