タグ

ブックマーク / i.loveruby.net (22)

  • 第20章 Rubyの未来

    そして次々世代の開発版がruby 2、コードネームRite、である。 この名前はLとRの区別がつけられない日人へのオマージュらしい。 一言で2.0はどこが変わるかと言うと、コアほとんど全部だ。スレッド、評価 器、パーサ、これが全部変わる。もっとも、コードがカケラも出てきていない のであくまでここに書くのは全て「予定」である。あまり期待しすぎると失望 するかもしれない。そういうわけで、軽く期待、ということにしておこう。 記述言語 まず使う言語。間違いなくCだろう。Ruby英語メーリングリスト ruby-talkでのまつもとさんの発言によると I hate C++. だそうなので、C++を使うというのはまずありえない。いくら全面作り直しと 言ってもオブジェクトシステムはほぼそのまま残ると考えられるので、そのあ たりでの手間が増えないようする必要もある。ただしCはCでも今度はANSI Cに

  • 第19章 スレッド

    rubyスレッド スレッドは「みんな一斉に動く」というのが建前だが、実際には少しの時間ず つ順番に動いているわけだ。厳密に言えばマルチCPUのマシンでそれなりに工 夫すれば同時に二つ動いたりもできるが、それでもCPUの数以上のスレッドが あればやはり順番に動かなければならない。 つまりスレッドを作り出すためにはどこかで誰かがスレッドを切り替えてやら ないといけないわけだが、その手法には大きく分けて二種類ある。 カーネルレベルスレッドと ユーザレベルスレッドだ。これはどちらも読んで字の如く、ス レッドというものをカーネルで作るかユーザレベルで作るかという違いである。 カーネルレベルならマルチCPUを生かして複数のスレッドを同時に動かしたり もできる。 ではrubyのスレッドはどうなのかと言えば、これはユーザレベルスレッドで ある。 そして(それゆえ)同時に動けるスレッドは厳密にただ一つと制限

  • 第18章 ロード

    概要 インターフェイス Rubyレベルでロードに使える手続きは二つある。 requireとloadだ。 require 'uri' # URIのライブラリをロード load '/home/foo/.myrc' # なにかのリソースファイルを読む どちらも通常のメソッドであり、他のコードと全く同様にコンパイル され、評価される。つまり、完全にコンパイルして評価の段階に移ってから ロードが起こる。 二つのインターフェイスははっきりと用途が分離されている。 ライブラリをロードするときはrequire、任意のファイルをロード しようとするときはloadだ。それぞれ詳しく特徴を説明していこう。 require requireの特徴は四点だ。 ロードパスからファイルを探してくる 拡張ライブラリもロードできる 拡張子.rb/.soを省略できる 同じファイルは二度以上ロードしない Rubyのロードパスは$

  • 第17章 動的評価

    概略 評価器の仕組みそれ自体については前章までで既に完結している。章ではそ の全てにパーサまでを加えた「広義の評価器」としての全体像を検証しよう。 対象となるのはeval・Module#module_eval・Object#instance_evalの三つであ る。 eval evalについては既に話したが、ここではより細かい話をしようと思う。 evalを使うと実行時にその場で文字列をコンパイルし、評価することができる。 返り値はそのプログラムの最後の式の値だ。 p eval("1 + 1") # 2 evalする文字列の中からはそのスコープの変数も参照できる。 lvar = 5 @ivar = 6 p eval("lvar + @ivar") # 11 ここまで読んできた読者なら「そのスコープ」という言葉を安直に読み飛ばせ なくなっているだろう。例えば定数の「スコープ」はどうなっている

  • 第16章 ブロック

    イテレータ この章ではRubyスタック七のうち最後の大物、BLOCKが登場する。 これが終われば評価器の内部状態についてはわかったも同然だ。 全体像 イテレータの仕組みはいったいどうなっているのか。 まず次のような小さいプログラムで考えてみよう。 ▼ソースプログラム iter_method() do 9 # ブロックを探す目印 end 用語を確認しておく。このプログラムで言うとiter_methodが イテレータメソッド、do〜endがイテレータブロックだ。 このプログラムの構文木をダンプしたらこうなった。 ▼対応する構文木 NODE_ITER nd_iter: NODE_FCALL nd_mid = 9617 (iter_method) nd_args = (null) nd_var = (null) nd_body: NODE_LIT nd_lit = 9:Fixnum イテレータブ

  • 第12章 構文木の構築

    またnode.hではこの共用体メンバにアクセスするためのマクロも用意されて いる。 ▼NODEアクセス用マクロ 166 #define nd_head u1.node 167 #define nd_alen u2.argc 168 #define nd_next u3.node 169 170 #define nd_cond u1.node 171 #define nd_body u2.node 172 #define nd_else u3.node 173 174 #define nd_orig u3.value : : (node.h) 例えばこんなふうに使う。 NODE *head, *tail; head->nd_next = tail; /* head->u3.node = tail */ ソース中ではほぼ間違いなくこのマクロのほうが使われる。そのごくわずかな 例外はparse.

  • 第15章 メソッド

    この章ではメソッドの探索と起動について話す。 メソッドの探索 用語 この章ではメソッド呼び出しとメソッド定義の話を両方やる関係で、 実に様々な「引数」が出てくる。そこで紛らわしくならないように ここで厳密に用語を決めてしまうことにしよう。 m(a) # aは「通常の引数」 m(*list) # listは「配列引数」 m(&block) # blockは「ブロック引数」 def m(a) # aは「通常のパラメータ」 def m(a=nil) # aは「オプションパラメータ」、nilは「そのデフォルト値」 def m(*rest) # restは「restパラメータ」 def m(&block) # blockは「ブロックパラメータ」 ようするに渡すときは全部「引数」、受けるほうは全部「パラメータ」で 種類によってそれぞれ形容詞を付ける、ということだ。 ただし、ここで挙げたうち「ブロック引

  • https://i.loveruby.net/ja/rhg/book/module.html

  • 第13章 評価器の構造

    main発ruby_run経由rb_eval行き コールグラフ 評価器の真のコアはrb_eval()という関数なのだが、 この節はmain()からそのrb_eval()までの道筋を追ってゆく。 まず以下はrb_eval()周辺のおおまかなコールグラフである。 main ....main.c ruby_init ....eval.c ruby_prog_init ....ruby.c ruby_options ....eval.c ruby_process_options ....ruby.c ruby_run ....eval.c eval_node rb_eval * ruby_stop 右側にはファイルが移動するところでファイル名を入れておいた。 これをジッと見てみてまず気付くのは、eval.cの関数からmain.cの 関数を呼び返していることだ。 呼び返している、と書いたのは、mai

  • 第11章 状態付きスキャナ

    概要 理論のように、スキャナはただひたすらトークンに区切り、パーサはその並び だけを扱い、両者は完璧に独立している……という段階で済むならば、それは とてもありがたいことだ。しかし現実はそううまくはいかない。プログラムの 文脈によってトークンの切りかたや記号を変えなければならないということは よくある。この章ではスキャナとパーサの連携について見ていくことにする。 具体例 普通のプログラム言語なら、空白は単語の区切りになる以外はたいし て意味を持たない。しかしRubyは普通ではないので空白のあるなしで全く意味 が変わってしまうことがある。例えば次のような場合だ。 a[i] = 1 # a[i] = (1) a [i] # a([i]) 前者はインデックス代入であり、後者はメソッド呼び出しの括弧を省略して引 数に配列の要素を渡している。 また次のような場合もある。 a + 1 # (a) +

  • 第10章 パーサ

    指針 パーサの構築 パーサのメインソースはparse.yである。*.yだからyaccの入力で、 ここからparse.cが生成される。 また他にはlex.cという思わせぶりな名前のファイルがあるのだが、スキャナ が入っているわけではない。これはgperfというツールが生成したファイルで、 予約語のハッシュテーブルが定義されている。その入力ファイルはkeywordsだ。 lex.cはparse.cに#includeして使われる。 中身について説明するのはその場にならないと難しいので後にまわそう。 まとめるとパーサの構築手順は図1のようになる。 Windowsで生きている人のために説明するとmvはファイルを移動する コマンドである。ccはもちろんCコンパイラでcppは Cのプリプロセッサだ。 図1: パーサの構築手順 parse.yの腑分け 続いてparse.yを眺めてみよう。 おおざっぱに言う

  • 第9章 速習yacc

    概要 パーサとスキャナ プログラム言語のパーサの書きかたは昔からしつこく研究されてきており、 かなりしっかりした定石がある。よほど変な(または曖昧な)文法でない 限り、定石にのっていけば解決できるものだ。 まず最底辺には文字列を単語(トークンとも言う)の列に切り出す部 分がある。これをスキャナ(scanner)とかレクサ(lexer)と言 う。日語で言うと字句解析器だが、言いにくいのでスキャナと呼ぼう。 スキャナというものが出てくる根底にはそもそも「単語の区切りには空白ある でしょ」という常識がある。そして実際にたいていのプログラミング 言語はそういう仕様になっている。そのほうが楽だからだ。 例えば古いFortranでは空白が意味を持たなかった。つまり空白を入れても 単語区切りとは限らないし、変数の途中で何の前触れもなく空白を挿入したり することもできた。ところが解析が恐ろしく面倒なもの

  • 第8章 Ruby言語の詳細

    これまで話していないRuby言語の構文と評価の詳細について述べる。完全な説 明をしようとは思っていないので、書に登場しない細かい仕様は全てカット した。だからこれだけ読んでもRubyプログラムが書けるようになるということ は、まずありえない。完全なものが必要なら添付CD-ROMに同梱したリファレン スマニュアル\footnote{Rubyリファレンスマニュアル:添付CD-ROMarchives/ruby-refm.tar.gz}を 読んでいただきたい。 Rubyを知っている読者はこの章も飛ばして構わない。 リテラル Rubyはリテラルを使った式の表現力が非常に高い。 Rubyをスクリプト言語たら しめているのは第一にトップレベルの存在、第二がリテラルの表現力だと筆者 は考えている。第三には豊富な基ライブラリが挙げられるだろう。 リテラルは単体でも非常に強力だが、組み合わせるとさらに強力

  • 第6章 変数と定数

    章の概要 Rubyの変数 Rubyには以下のようにかなりたくさんの種類の変数・定数が存在する。 スコープの大きいほうから並べよう。 グローバル変数 定数 クラス変数 インスタンス変数 ローカル変数 インスタンス変数については既に第2章『オブジェクト』で説明した。 章では残りのうち グローバル変数 クラス変数 定数 について解説する。 また残るローカル変数については第三部で話す。 変数関連API 章の解析対象はvariable.cである。 まずそこからエントリポイントとなるAPIを紹介しておこう。 VALUE rb_iv_get(VALUE obj, char *name) VALUE rb_ivar_get(VALUE obj, ID name) VALUE rb_iv_set(VALUE obj, char *name, VALUE val) VALUE rb_ivar_set(V

  • 第7章 セキュリティ

    原則 セキュリティと言ってもパスワードとか暗号化とかの話ではない。Rubyのセキュ リティ機能はCGIプログラムのような環境で「信用できない」ものを扱うため に存在する。 例えば数値を表現した文字列を手軽に整数に変換したいとき、その文字列を evalするという方法がある。しかしevalというのは「文字列を Rubyプログラムとして実行する」というメソッドであり、ネットワーク越しに どこの誰かもわからない人から受け取った文字列をevalしてしまったりすると、 とても危険だ。しかしそういうことをプログラマが逐一管理して、これは安全、 これは危険……と分けていくのは非常にしんどい。めんどい。従って確実にい つか間違える。だからそういうのは言語にやらせよう。というわけだ。 ではRubyはどういうふうにその危険から守ってくれるのだろうか。危険な操作、 例えば意図しないファイルを開いたりすること、の原

  • 第4章 クラスとモジュール

    章ではクラスとモジュールの作りだすデータ構造について詳細を見ていく。 クラスとメソッドの定義 まずはCレベルでRubyのクラスを定義する方法を少しだけ見ておきたいと思う。 この章ではある意味「特殊な」ところばかりを追求するので、圧倒的多数を占 める通常ルートを先に知っておいてほしいのだ。 クラスとメソッドを定義する主要なAPIは以下の六つである。 rb_define_class() rb_define_class_under() rb_define_module() rb_define_module_under() rb_define_method() rb_define_singleton_method() 多少の派生バージョンはあるものの、拡張ライブラリはもちろん、基クラス ライブラリまでのほとんどがこれだけのAPIで定義されている。順番に紹介し ていこう。 クラスの定義 rb_d

  • 第5章 ガ-ベージコレクション

    プログラムの実行時イメージ 突然だが、章を始めるに先立ち、プログラム実行時のメモリ空間の状態につ いて予習をしておこうと思う。この章ではコンピュータの低レベルな部分にか なり踏み込んでいくことになるので、あらかじめある程度の知識を仕入れてお かないと太刀打ちできないのだ。それにこの後の章になればいずれ必要になっ てくる。ここで一回やってしまえば後が楽だ。 セグメント 一般的なCプログラムではメモリ空間の中に以下の部分を持つ。 テキスト領域 スタティック変数やグローバル変数の置場 マシンスタック ヒープ テキスト領域はコードが置いてあるところ。二番目は見ての通り。マシンスタッ クには関数の引数やローカル変数が積まれる。ヒープはmalloc()で割り当てて もらうところだ。 三つめのマシンスタックについてもう少し話そう。マシン「スタック」と言う くらいだから当然スタック構造をしている。つまり

  • 第2章 オブジェクト

    例えば文字列オブジェクトならstruct RStringを使うので 図2のようになる。 図2: 文字列オブジェクトの表現 オブジェクト構造体の定義をいくつか見てみよう。 ▼オブジェクト構造体の例 /* 一般のオブジェクトのための構造体 */ 295 struct RObject { 296 struct RBasic basic; 297 struct st_table *iv_tbl; 298 }; /* 文字列(Stringのインスタンス)のための構造体 */ 314 struct RString { 315 struct RBasic basic; 316 long len; 317 char *ptr; 318 union { 319 long capa; 320 VALUE shared; 321 } aux; 322 }; /* 配列(Arrayのインスタンス)のための構造体

  • 第3章 名前と名前表

    st_table メソッドテーブルやインスタンス変数テーブルとしてst_tableは既に何度か登 場してきた。章ではまずこのst_tableについて詳しい作りを見ていくことに しよう。 概要 st_tableはハッシュテーブルだということはもう言った。ではハッシュ テーブルは何かと言うと一対一対応を記録するデータ構造である。一対一の対 応とは例えば変数名とその値、関数名とその実体、などだ。 ただしもちろんハッシュテーブル以外でも一対一対応は表せる。 例えば次のような構造体のリストを使ってもいい。 struct entry { ID key; VALUE val; struct entry *next; /* 次のエントリを指す */ }; しかしこの方法は「遅い」。もしリストが1000個あったら最悪1000回リンクを たぐって探さなければならない。つまり要素の個数に比例して検索時間が長く

  • 第1章 Ruby言語ミニマム

    Ruby言語について、当面第一部を理解するのに必要な知識だけ簡単に解説して おく。プログラミング上のテクニックであるとか注意すべきところなんてもの は全く指摘しないので、この章を読んだからと言ってRubyプログラムが書ける ようになるわけではない。既にRuby言語の経験がある読者はこの章は飛ばし て問題ないだろう。 また文法については第二部で嫌というほど話すから、この章ではできるだけ文 法の詳細には関らないようにする。ハッシュリテラルなどバリエーションがあ る表記は最も多用されるもののみ示す。省略可能なものは原則的に省略せずに 示す。そのほうが構文規則がシンプルになるからだ。いちいち「省略できる」 とも言わない。 オブジェクト 文字列 Rubyプログラムが操作できるものは全てオブジェクトである。Javaのintや longのような「基型(primitive)」はない。例えば以下のように書