エイホ(A)、ワインバーガー(W)、カーニハン(K)による小型のスクリプト言語。
ml archive (http://blade.nagaokaut.ac.jp/ruby/)
数値の型変換を行うメソッド。数値計算のメソッドは自分の知らないインスタンスが引数として渡された時にはcoerce メソッドを使って変換を行うように取り決められている。 coerceメソッドは引数として与えられた値(を変換した値)と自分(必要ならば変換した値)のペアを返す。
Rubyのライブラリの数値型の変換順序は
Fixnum -> Bignum -> Rational -> Float -> Complex
になっている。
CレベルのポインタをRubyオブジェクトとして見せるためのラッパー。 Cポインタと、mark関数、free関数から作る。Cを使ってRubyに機能を追加しようとする人はぜひこのクラスの使い方をマスターする必要がある。逆にいうとそういう予定のない人には用事がないクラスでもある。
いろいろなもの(式)が本当に定義されているかどうか調べてくれる演算子。定義されていなければnil、定義されていればその式の種別を示す文字列を返す。defined?はメソッドのようにみえるがRubyの文法に組み込まれた演算子で、引数の評価を行わない。よって
defined? print("abc\n")
はなにも出力しない。
オブジェクト指向プログラミング言語。matzは昔この言語の作者の本(Object-oriented Software Construction 邦訳「オブジェクト指向入門」)を読んで目から鱗が落ちたらしい。その割にはRubyは Eiffelに似ていない。似ているのはブロックがendで終るところと、rescueという予約語だけか。
ブロック構造を終える予約語。ある統計によればRubyを最初に見た人の33%がこれを見てPascalを連想するという(嘘)。しかし、実際にはbeginと対にならないこの形式はPascalというよりAdaやEiffel に近い。
RubyがCやPerlで慣れ親しんだ {}を使わなかったのは以下の理由である
* 単文・複文問題の回避
たとえばCでは
if (a==b) c();
に文を追加しようとして
if (a==b) c(); d();
などとするとややこしいバグの元になる。この問題はPascalにも存在する。
* ぶらさがりelse問題の回避
上記と類似だが、
if (a==b) if (c==d) foo(); else bar();
などと書いてしまうと面倒なことになる。上のプログラムは実は
if (a==b) { if (c==d) foo(); else bar(); }
という意味である。
* 可読性の向上
異論はあるようだが、endという単語でブロックを閉じた方がプログラムが読みやすいと考えている人がいる。
* begin, caseの構文上の問題
正直言うと、matzはendという名前の変数を使おうとして痛い目にあったことが何度かある。そこで、一度は { }を使った文法にしようと検討したが、beginとcase の文法がきれいにまとまらずに断念した。実をいうとこれが最大の理由であったりする。
環境変数をアクセスするためのHash と同様の動作をするオブジェクト。実際には特異メソッドを付加したObjectクラスのインスタンスである。このオブジェクトによって環境変数を変更すると、 Rubyの子プロセスにも引き継がれる。
よくある質問とその答え集。
Rubyにないもの。gotoがないのはそれが「あるべきでないから」ではなく、「実装するのが面倒だったから」である。 gotoの代りはcatch/throwや例外で実現する。
トップレベルでのself。 selfがないわけにはいかないので、ただそこにあるためだけの単なるObjectクラスのインスタンスであるが、 Objectクラスを操作するため、いくつかの特異メソッドを定義してある。
定義されている特異メソッド
* private
* public
* include
Rubyの作者。まつもと ゆきひろとも言う。 http://cmail.osdn.jp/ と4人の子供の父親でもある。
アイスクリームにいろんなものをまぜて新しい味を作ること。転じてモジュールをクラスに混ぜて機能を追加すること。継承を参照。
Rubyでは多重継承を採用せず、is-aの関係のための継承と、機能の共有のためのMix-inを用意している。これは多重継承を濫用すると関係が混乱するというmatzの信念のためである。
何だったっけ?
Principle of least surprise
Rubyのライバル。「年を経た蛇」。matzがPythonに満足していれば Rubyは生まれなかったであろう。一番気になっているのは名前の長さ(6文字)である。
Ruby Change Request
Ruby Document
オブジェクト指向スクリプト言語。Rubyの名前は「Perlに続く (pearlは6月の誕生石、Rubyは7月の誕生石)」という程度の意味で名付けられた。Rubyは別に何かの略ではない。
オブジェクト指向プログラミング言語。matzは EiffelよりもSatherが好きだ。しかし、 SatherもやっぱりRubyには全然似ていない。
レシーバを参照する式。なぜ selfかというと、メソッドを動詞と考えるとレシーバは主語に当たり、メソッドから見ると自分であるからという説があるが、Rubyでは深く考えず、単にSmalltalkを真似ただけだ、という説が有力である。
オブジェクト指向プログラミング言語。現在のオブジェクト指向というパラダイムの基礎を築いた言語。
オーバーライドしたメソッドから上位のメソッドを呼び出す方法。引数を省略した時には呼び出し元のメソッドと同じ引数で呼び出される。
* 問題:
引数として与えられた変数の値を変更した場合には、 superで元の値が渡るか、変更した値が渡るか。
def foo(a) print a end def self.foo(a) a=25 super end foo(5) # 5 or 25??
* 答え:
変更した値(25)。古いバージョンでは 5 を返すという仕様だった。現在はこの問題自体にあまり意味がないかも知れない。
もとはThread of controlの略。一連の制御の流れのこと。Rubyでは一つのプログラムの中に複数のスレッドが存在できる。
メソッドを未定義状態にすること。継承もMix-inもクラスにメソッドを追加することだが、undefを使えばメソッドを取り除くことができる。ただし、クラスの実装に必要なメソッド(メソッド内部から呼ばれているメソッド)を外してしまうと痛い目に遭う。
インスタンスの浅いコピー。フィールド内のインスタンスは、参照をコピーするだけである。例えば、配列に浅い複製を行った場合、配列はコピーされるが配列内の要素が参照しているオブジェクトはコピーされない。うっかり破壊的なメソッドを使ってしまうと思わぬ所に影響が出る恐れがあるため、気をつける必要がある。対義語 深い複製
ブロック付きメソッド呼び出しのこと。ブロック付きメソッドは当初繰り返し処理を行うために作られたため、未だにイテレータと呼ぶことがある。繰り返しを意図したメソッドをイテレータと呼ぶのはかまわないが、ブロック付きメソッド呼び出し全般をイテレータと呼ぶと混乱の元になるので気を付けるように。
オブジェクトのこと。オブジェクトがあるクラスに所属することを強調する意味あいがあるらしい。オブジェクトなんだかインスタンスなんだか混乱してオブジェクト指向に挫折する人は多いと聞く。
オブジェクトに固有の変数のこと。Rubyのインスタンス変数は識別子の直前に@をつけたものであり、メソッドの中からしか参照できない。
再定義のこと。スーパークラスまたはincludeしているモジュールで定義されているメソッドと同じ名前のメソッドを定義すること。オーバーライドした上位のメソッドは superを使って呼び出すことができる。
もののこと。「愛」は多分オブジェクトではないが、「ラブレター」はオブジェクトである。あるものがものであるか、そうでないかは多分に哲学的である。この辺がオブジェクト指向は難しいといわれる原因かも知れない。コンピュータ業界ではメモリ中の特定の空間のことをオブジェクトと呼ぶ人がいたりする人がいる。困ったものだ。カプセル化、抽象データ型参照。
オブジェクトを基本にしたパラダイム。英語の"Object-Oriented"という形容詞が、日本に来て名詞化した。オブジェクトを考え方の中心に置けば、なんでも良いようにも思えるが、一般的には
* 継承
* カプセル化
* ポリモルフィズム
(あるいは動的結合)
が必要らしい。なんでも解決できる「魔法」のように考える人もいるが、世の中そんなに甘くない。誕生から20数年を経てようやっと実用的に使われるようになった…んだろうな、多分。
オブジェクトを基本にしたシステム設計
オブジェクトを基本にしたプログラミング。
オブジェクトを基本にしたシステム分析。
データに対する直接的な操作はデータの型に付随する特定の手続き (メソッドと呼ぶ)からだけ行うことにより、内部構造や処理のアルゴリズムを外部から隠してしまうこと。抽象データ型参照。
Rubyはインスタンス変数はメソッドからしか参照できないので、カプセル化が強制されているといえる。
親プロセスから子プロセスに対して受け渡される値。 ENVでアクセスされる。子プロセスに渡るのは環境変数のコピーなので、子プロセスから親プロセスに環境変数を使って情報を受け渡すことはできない。親はなかなか子供に耳を傾けないものである。
厳密にいうとRubyに関数はない。しかし、レシーバを省略したメソッド呼び出しは外見が関数に似ているし、 selfやインスタンス変数などレシーバの情報を全く参照しない事実上の関数として働いているといっても良いメソッドもある。だから厳密でない言い方としてそういうメソッドを関数と呼ぶこともある。
そういう関数(的メソッド)は大抵レシーバを省略した形式でしか呼び出せないように可視性がprivateに設定してある。このようなメソッドの代表としてモジュール関数がある。
クラスのメソッド。全てのクラスのクラス Classで定義されている全てのクラスで共有されているメソッドとクラスそれぞれが固有に持っている特異メソッドとがあるが、そんなことは大した問題ではない。クラスメソッド内でのselfはクラスであるので勘違いしないように。
プログラム全体から参照できる変数。危険。多用しないこと。
先祖や親戚から受け継いだものに頼り切って、自分では最低限のことしかしないこと。現実世界では嫌な奴。転じて、あるクラスに機能を追加した新しいクラスを作ること。継承はis-aの関係を表現するのに有効である。たとえば、学生一般の性質を記述した「学生」クラスを継承して、実験に苦しめられる「工学部生」クラスを作ることができる。is-aの関係がなく、単に性質や機能を共有する場合にはMix-in を使うことが望ましいとされる。
オーバーライドのこと。
項目からその定義を取り出すことができるもの。転じてハッシュの別名。オブジェクト指向の起源とも呼べるSmalltalkにおいてハッシュに相当するデータ構造が「辞書」と呼ばれていたせいで辞書という用語になじんでいる一群の人々がいる。
オブジェクト(あるいは「なにか」)を「使える」状態にすること。インスタンスの初期化には Object#initialize メソッドを再定義する。クラスのメソッド Class#newのデフォルトの定義は新たに生成したインスタンスに対して、 initializeを実行する。newへの引数はそのままinitializeに渡される。また、 newがブロックとともに呼び出された時には initializeにそのブロックがそのまま与えられる。
ということはClass#new を再定義する必要はないはずだ。
台本。転じて、インタープリタが解釈する比較的短いプログラムのこと。もちろん中には超大作の台本もある。
スクリプトに従ってバッチ処理を行うインタープリタのこと。人間も台本を読むという点においてスクリプト言語である。
参照ではなく、実際の値が変数に格納されるもの。Rubyの現在の実装ではFixnum、Symbolとnil/true/falseだけが即値である。しかし、Fixnumが即値でないRubyの実装があっても構わないし、モデル上全ての値がオブジェクトへの参照であると考えても差し支えない。
順番に並べ替えること。Ruby は数え上げる事ができて (Enumerable がincludeされていて)、各要素に順序が定義されて(<=> が定義されて)いれば、配列に限らずどんな複雑なオブジェクトの集まりもソートしてくれる。
break, next, redo, retry, return などのメソッドの範囲内での脱出ではなく、捕捉されない限りメソッド呼び出しの階層を遡って中断するタイプのものを大域脱出と呼ぶ。 Rubyの大域脱出には、例外によるものとcatch/throwがある。
ほとんどの例外は(exitで発生するSystemExit を含めて rescue で捕捉できるが、捕捉することに意味がない例外 (例:メモリ割当に失敗した/インタプリタそのもののバグ)は捕捉の対象にならない。
catch/throwはthrowされると指定されたタグと同じタグを持つcatchまで一気にジャンプするものである。
ローカル変数 の一種。Rubyのローカル変数はスコープが静的に決まるためコンパイル時に変数が作成されるが、ダイナミックローカル変数は、実行の都度変数が作成される。ブロックの中で初めて代入されたローカル変数はダイナミックローカル変数となり、そのスコープはブロックの中だけとなる。これは、Thread 毎に独立した変数を持つためにある。
データの構造とそのデータに対する操作をひとまとめにしたものを抽象データ型と呼ぶ。抽象データに対する操作は必ずその操作を経由する必要がある。結果、データ構造は外部からは直接参照されず、内部構造の変更が外部に悪影響を及ぼさない。このことをカプセル化と呼ぶ。
一度定義したら値を変えることができない変数。でも、この定義は矛盾しているなあ。
操作の対象のデータ型に合わせて適切な手続き(メソッド)が実行時に選択されること。プログラムの柔軟性を高める働きがある。オブジェクト指向の要件のひとつ。 Rubyでは変数に型が無いので動的結合は必然である。
ある特定のオブジェクトだけのための仮想的なクラス。
ある特定のオブジェクトにだけ定義されたメソッド。メソッド参照。特異メソッドは以下の場合に他のオブジェクトにも引き継がれる。
* Object#cloneした場合
* サブクラスを作った場合
特異メソッドで元のクラスのメソッドをオーバーライドした場合はもとのメソッドは super で呼び出すことができる。
matzの苦手なもの。彼は普段から「ソースがドキュメントだ。バグも完全に記述されている」と主張しているが、誰も受け入れない。当り前だ。
クラス/モジュール定義の一番外側のコンテキスト。Rubyスクリプトはトップレベルのコンテキストから処理が始まる。
いきなり、 print "on Toplevel" というスクリプトを書いたとき、print メソッドはトップレベルから呼ばれている。
トップレベルの self は main を指す。
0x01020304という4バイトデータを1,2,3,4 と配置するか、4,3,2,1と配置するかということ。前者をビッグエンディアン、後者をリトルエンディアンと呼ぶ。どちらが良いかという論争は時のはじめから続いていてまだ結論が出ていない。
String#chop!, Array#concat などのメソッドは、レシーバの状態を変化させるので、「破壊的な作用をする」という。めったにコンピュータを壊すことはない。
Rubyにおけるキーから値へのマッピングを表すデータ構造。連想配列とか辞書とも呼ばれる。ハッシュがハッシュと呼ばれるのはその実現に「ハッシュ表」と呼ばれるアルゴリズムが使われているからである。ハッシュというのは「切り刻む」という意味で、「ハッシュド・ビーフ」の「ハッシュ」である。
「考え方」の難しい表現。素直に分かりやすい言葉を使えばいいのに…。
リテラル/ヒアドキュメント (行指向文字列リテラル) を参照してください。
アメリカ大陸原住民…はインディアン。こっちはエンディアンで語源はスウィフトの「ガリバー旅行記」に出て来る卵を丸い端から食べる人たちである。当然、尖った端から食べる人たちはリトルエンディアンである。コンピュータ業界ではCPUなどがデータを並べる時の形式のひとつで、ネットワーク族はビッグエンディアンを好むという。バイトオーダー参照
Rubyインタプリタ組み込みでインスタンスの構造が通常のオブジェクトと異なるクラス。これらのクラスを継承したクラスを定義することはお勧めしない。 Rubyのビルトインクラスは Builtin libraries に列挙されている。
インスタンスの深いコピー。フィールド内にインスタンスがある場合、そのインスタンス専用にメモリのコピーを行う。例えば、配列に深い複製を行った場合、配列をコピーし、配列内の要素が参照しているオブジェクトもすべてコピーされる。対義語 浅い複製 shallow copy
ループを構成したり、家や塀を建てたり、人を殴ったりするもの。
コードの集まり(ブロック)を受け取ることのできるメソッドをブロック付きメソッド呼び出しと呼ぶ。
ブロック付きメソッドの中では yield を使ってブロックを実行することができる。
当然のことながら、与えられたブロックをどのように処理するかはメソッド側に委ねられている。ので、内部でブロックを評価しないメソッドにブロックを与えてもなにも起きない。エラーも起きない。
メソッド定義時などに使用する &block などのこと。
ブロックに渡すパラメータのこと。
オブジェクトにつける名札。Rubyの変数にはグローバル変数、ローカル変数、インスタンス変数がある。それと定数は値を変えることができないので、変数ではないが、名札であるという点においては変数と同じである。
対象になるオブジェクトによって実際の操作が決定されること。 Rubyではレシーバのオブジェクトに応じてメソッドが選択されることによって実現されている。
* 例
obj = "abc" print obj.length, "\n" # => 3 obj = [1,2,3,4] print obj.length, "\n" # => 4
関数のように用いられるメソッドの中で、モジュールのメソッドとしても、特異メソッドとしても定義されているものはモジュール関数と呼ばれる。例えば Mathモジュールのほとんどのメソッドはモジュール関数である。これらのメソッドは、例えば
Math.sqrt(2)
という形式でも
include Math sqrt(2)
という形式でも使えて便利である。
オブジェクトに対する操作。操作対象のオブジェクト(レシーバ)は self で参照できる。 Rubyの場合ビルトインクラスのオブジェクトを除けば、オブジェクトの構造は動的に決まるので、あるオブジェクトの性質はそのオブジェクトに定義されているメソッドによって決定される。
最初10人いて段々減っていく。コンピュータ業界ではデータを並べる時の形式のひとつで、非常に大きなシェアを持つあるCPUメーカーはリトルエンディアンを好むという。バイトオーダー参照
例外的な状況で発生するもの。例外が発生すると begin の rescue 節を使って明示的に捕捉されない限り、呼び出し階層を遡ってプログラム(thread)の実行は中断される。例外のおかげでRubyプログラムはほとんどの場合例外的な状況についていちいちチェックせずにすむ。例外の発生した場所の情報は $@ に、例外そのものに関する情報は $! に格納されている。
メソッドの実行主体。メソッド呼び出し式の`.'の左側にあるもの。メソッド内では self で参照できる。レシーバのインスタンス変数は @変数名という形式でアクセスできる。
ハッシュの別名。ハッシュが任意のキーから値を取り出すことができるので、「連想」と、またハッシュは添字が数字でない配列とみなすことができるので「配列」と呼ぶらしい。昔々は連想配列(連想記憶と呼ばれていた)はハードウェアによって実現されるものだと考えられていたが、計算速度の向上や適切なアルゴリズムの発見(「ハッシュ表」と呼ぶ。ハッシュの語源)によりソフトウェアのみによって実現されるようになった。
ある範囲内でのみ参照可能な変数。その範囲をスコープと呼ぶ。 Rubyのスコープは
* プログラム全体
* クラス・モジュール定義
* メソッド定義
* ブロック
で、ブロックだけは外側のスコープのローカル変数もアクセスできる。ローカル変数の有効範囲はスコープでの最初の代入が現れた場所からスコープの終りまでである。有効範囲は静的に決まり、実際に実行されるかどうかは関係ない。