東京Ruby会議03 に行ってきた
- 雨と東京マラソンとの戦い
メタプログラミング入門
Ruby における特性
class LogWritable %w[host time].each do |attr| attr_reader attr end end
-
-
-
-
- 宣言ではなく普通に式であって,実行時に順次評価されるもの
- コンパイル時にどうこうされるようなものではない
- 宣言ではなく普通に式であって,実行時に順次評価されるもの
-
-
-
class Foo; end class Bar; end class Baz < (rand < 0.5 ? Foo : Bar) if gets == "ok" def foo; end end end
道具立て
klass = Class.new do def foo; end end
-
- 特異クラス
- クラス階層
- BasicObject < Object < Module < Class
- 特異メソッド
- クラス階層
- 特異クラス
class Bar; end bar1 = Bar.new bar2 = Bar.new def bar2.foo; end # => bar2 のみに定義される
-
-
-
- 特定のオブジェクトにだけメソッドを定義できる
- 特異クラス
- bar2 に特異メソッドを作ったときには,内部的に新しいクラスを定義している
- これを特異クラスと言う
- Ruby からは見えないが,見る方法がある
- これを特異クラスと言う
- bar2 に特異メソッドを作ったときには,内部的に新しいクラスを定義している
-
-
eigenclass = (class << obj; self end)
-
-
- メタクラス
- クラスのクラス
- クラスのクラスは,特異クラス
- クラスのクラス
- メタクラス
-
class Foo def self.static; end # 特異メソッド定義 end
-
-
-
-
- Foo と言うクラスは Foo の特異クラスに属している
- Foo を継承した Bar の特異クラスは,Foo の特異クラスを継承している
- Class クラスにも特異クラスがある
- Foo と言うクラスは Foo の特異クラスに属している
-
-
-
- 特異クラスは特殊なクラス
- callable objects
- Proc
- ブロック
- Proc.new / lambda / proc / &blk
- &blk => 呼び出し時に指定されたブロックが Proc オブジェクトに変換されて渡されるもの
- Method
- メソッド自身のオブジェクト
- UnboundMethod
- インスタンスが bind されていないメソッド
- Method#bound <-> UnboundMethod#bind
- Continuation
- callcc
- 各種変換ができる
- Proc
- eval 族
- eval / instance_eval / class_eval
- self
- デフォルトのレシーバ
- current class
- メソッド定義時に指定されるクラス
- TOPLEVEL
- self -> main
- current class -> Object
- class 定義中
- self -> the class
- current class -> the class
- def 式の中
- self -> 実行しているインスタンス自身
- current class -> NONE(無い)
- instance_eval
- self -> インスタンス自身
- current class -> 特異クラス
- class_eval
- self -> クラス自身
- current class -> クラス自身
- 特異メソッドが生成される
- eval
- binding に依存する
- method_missing / send
- "いいですね"
用例集
- メソッド定義
- Rails で
class Foo < ActiveRecord::Base [ %w[bar bas], %w[hoge piyo] ].each do |through, to| has_one through has_one to, :through => through define_method(:"#{to}=") do |val| self.send(:"#{through}=", val.send(through)) end end end
def sandbox(&block) Module.new(&block) end
ワークショップログ
東京 jpmobile 会議
- どう Rack 化するか
- Sinatra から使いたい
- Rails 2.3.x 用は
- ブランチを分けて,タグを切ってリリースにあわせる
- Rails 2.3.x 系はメンテナンスだけする
- ブランチを分けて,タグを切ってリリースにあわせる
- Rack 化
- テストはどうするか
- Rack::Middleware としてテストする?
- 絵文字は @mrkn さんの
- デモを見せてもらいました!いい感じでできあがる予感!?
- Rails の文字エンコードの出入の部分
- 絵文字が変換されてしまわないかとかチェック
- Content-type: を指定すればいい
- 絵文字が変換されてしまわないかとかチェック
- variants をどうするか
- Proc を渡すとか
- Proc で判定していく
- 動くものではなくて,仕様について相談してみるのがいいのではないか
- Proc を渡すとか
- 表 -> リクエスト生成(jpmobile) -> フィルター(jpmobile) -> アプリケーション
- 絵文字変換のフォールバック
- ハッシュテーブルとか文字を指定できれば
- 変換テーブルとかIPアドレステーブルとかを外部に出すと本体のメンテナンスやパッケージ化とかで手を煩わせなくていいんじゃないか
まとめ
- とりあえず実装してみてはどうかと思ったので,Rack 化をやってみよう
A REINTRODUCTION TO RUBY M17N
- 成瀬さん
- 地球に生まれたことを後悔することになるらしい
- 文字コードとは
- グリフやフォントよりちょっとした
- 文字集合
- 違うことの決定
- 何を扱うか
- 扱う文字を増やせば必要ビット数が増える
- 文字の同定
- 何が一文字か
- 字形の違い
- g とか l とか
- フォントや書体によって違う
- 字体の違い
- 符号化文字集合
- Coded Character Set
- Unicode Scalar Value
- ASCII / JIS X 0208 とか
- 文字符号化方式
- コードポイントを符号化する
- エンコーディング
- あるバイトデータを解釈するには「文字符号化方式」と〜を指定する必要がある
- IANA Charset
- インターネット上に流すデータは登録されている必要がある
- charset -> 文字集合
- 文字コード -> 文字集合 or encoding
- 国際化の歴史
- もともと国際対応じゃない
- 最初は ASCII
- 数字とアルファベットと記号の一部
- 数が足りない
- 拡張!
- して 500 種類以上?!
- どうしてこうなった?
- 製薬の中でベストを尽くそうとするため
- どうするか
- 各個撃破
- 罠は「歴史的経緯」にあり!
- ISO 646 - 分裂の始まり
- まだまだ足りないので
- ISO/IEC 2022
- 拡張方法を定めたもの
- ISO 2022 系
- 詳しくは文字コード本を
- 状態を持つのでいろいろ大変
- そこで Unicode
- 文字コードから地域・言語を分離
- フラットな空間に全てを入れる
- Plain Text は存在しない
- Legacy Encoding
- CP932 を知ってますか?
- 円記号問題「¥」
- ISO 646 の \ か¥かからはじまった
- 制御記号になったので
- シフトJISで問題が起こることも
- 波ダッシュ問題「〜」
- JIS X 0208 と CP932 で違うコードに変換される
- 機種依存文字
- 内部コードはどうするか
- UCS 正規化
- 入出力で変換する
- CSI (Code Set Independent)
- UCS 正規化
- Ruby 1.9
- String にエンコードがある
- 1.9 の String に必要なこと
- encoding を適切に設定すること
- encoding が誤ってるとき
- IO と Encoding
- encoding とは
- String にとっての「型」
- Encoding
- エンコーディングを司るクラス
- nkf
- Network Kanji Filter
- kconv
- iconv
- 挙動が環境依存
- uconv
- Unicode 変換用拡張モジュール
- String#encode
- String#encode(to, from, opt)
- Encoding::Converter
- 不必要な変換は避ける
- open() の引数に指定するなど
- Ruby M17N の難しさ
- テストがしづらい
- SJIS と Windows-31J
- Windows 環境だと,入力は Windows-31J だから,Windows-31J が正しい
- ASCII非互換の正規表現
- ケータイ絵文字
- @mrkn さんたちが作業中
- 1.9.2 に入るかも
- Windows の Unicode パスについてはパッチ待ち?
- 結合文字
- 「が」を「か」+「゛」で表すとか
- 複数のコードポイントを1文字扱いにする必要がある
- 異体字セレクタ/IVS
- String と言語
- Unicode ユーティリティ
- 半角か全角かは文脈依存だったりする
- Unicode 大文字小文字化
- String#sort
- Feedback を
open3 のはなし
- 田中哲さん
- 目的
- プロセスを動かす方法を提供する
- いい API を定義する
- Ruby のプロセス起動の問題
- system or fork
- system
- 環境依存だったりする
- fork
- UNIX でしか動かない
- system
- system or fork
- 解決
- spawn メソッドの新設
- open3 ライブラリの標準添付
- プロセス
- ps コマンド出力の1行
- プロセス属性
- 標準入出力
- fd の 0, 1, 2 は標準入力, 出力, エラー出力
- 0, 1, 2 は基本的に端末につながる
- リダイレクト
- プロセスの標準入出力をファイルに繋ぎかえる
- パイプ
- プロセスとプロセスをつなぐ
- Unix のプロセス起動
- fork
- fork を呼び出したプロセスの複製を作る
- exec
- exec を呼び出したプロセスを指定したコマンドで置き換える
- fork と exec の組み合わせ
- fork
- 非 UNIX では fork / exec は別れていない
- プロセス属性を指定する引数が複雑になりがち
- Ruby で実現したいこと
- API 案
- 既存のメソッドを拡張する? -> 上手くいかない
- 要求の衝突
- いろいろあるので,ひとつのメソッドで全部出来そうにない
- 高位・低位 API への分割
- 高位API : open3
- とりあえずパイプラインくらいまで提供
- エスケープしたりとか,コマンドのステータスをみたいとか
- 低位API : spawn
- fork はポータブルじゃないとか
- ライブラリのレイヤ
- 高位になるほどライブラリの自由度が高く「賢い」
- 低位になるほど詳細な制御が可能になる
- open3 と spawn のレイヤ
- open3
- OS 間の共通機能にフォーカスした高位 API
- spawn
- OS 固有の機能も出来る限り指定できる程度に低位
- open3
spawn について
- プロセス起動手法には起源がある
- いまの不満
- いろいろ OS でできたことが Ruby 上からできない
- プロセス起動の問題
- ポータブルではない部分がある
- perl では?
- ruby では?
- spawn 関数の導入
- fork + プロセス属性設定 + exec
- spawn の基本
pid = spawn("make all") Process.wait pid
-
- シェルを通さない方法も提供
- リダイレクトもある
spawn("make all", :out => "make.log")
open3 について
- 標準添付ライブラリ
- STDIN / STDOUT / STDERR とパイプを繋げて通信するライブラリ
- open3 の歴史は今日刻まれた
- ゾンビプロセス
- 終了した後,親により wait されていないプロセス
- open3 で言われる問題
- ゾンビ -> double fork
- Windows
- 終了ステータスが得られない -> double fork だから
- pid が得られない -> シグナルを送るのが困難 -> double fork だから
- 亜種が発生
- open3 による detach の効果
- ゾンビが発生しない
- double fork しないので pid が得られる
- 終了ステータスも得られる
- Open3.popen3 でいろいろ解決
- でも足りないので高位 API が必要
- open3 と標準エラー出力
- 標準出力と別々のパイプにするには扱いが面倒
- パイプにしないことがいいことも多い
- ひとつのパイプにマージしていいケースもある
- 標準出力と別々のパイプにするには扱いが面倒
- 高位 API のメソッド追加
- 出力を文字列で得る
- os, es, st = Open3.capture3
- 標準出力と標準エラーを出力をマージする
- Open3.popen2e
- パイプライン
- Open3.pipeline
- 出力を文字列で得る
- 複数パイプラインは必要か?
- spawn によるパイプラインは厄介
- パイプを作って閉じて〜を繰り返す必要がある
- spawn によるパイプラインは厄介
- shell ライブラリ というのもある
まとめ
- spawn / open3 の紹介
- 高位と低位に分けたデザイン
- パイプの用法の考察
懇親会
- エアとしていろいろ.そろそろかとかいろいろ.
全体のまとめ
- クラス/メソッド定義中のスコープについて考えると,特異メソッドやクラスメソッドのことがよくわかる
- 評価順は上からであって,クラス式は宣言式ではないので,C のように考えてはいけない
- 実際会議っぽくなりました
- 文字周りはいろいろカオスですね
- プロセス周りはちゃんと勉強したいです