- Rubyの関数・メソッドの引数の特徴
- コードブロックの効果的な使い方
2.2節 Rubyの引数
Ruby では引数のデフォルト値を指定できる「オプション引数」を宣言できたりします。def foo(bar="defaultvalue")こうやって宣言した関数 foo は、 foo "hoge" とも foo (= foo "defaultvalue" と同じ)とも関数呼び出しができます。
...
end
ただ、オプション引数は複数存在するとその順番によって、省略できなくなってしまいます。
擬似的なキーワード引数
オプション引数とは別の話として、ハッシュを使った擬似的なキーワード引数の話が載っています。キーワード引数の良いところは、順番に依存しない関数・メソッド呼び出しが行えることです。
「累乗を計算する power 関数は、第一引数が底だっけ?指数の方だっけ?」と迷うことなく
power({ :base => 2, :exp => 10 })と記述することができ、うっかり 10の2乗を計算することを回避できます。
合わせ技
ハッシュによるキーワード引数とオプション引数(の考え方)とを組み合わせると、任意の場所の引数についてデフォルト値を定められる(= 省略可能にできる)関数やメソッドを定義できる、というのが 2.2 節のまとめです。2.1節 統一された呼び出しインターフェース(API)
順番が逆ですが、2.2節で出てきたような引数処理のテクニックを利用すると、関数・メソッドを同一の呼び出し方法で異なる使い方が可能になる、という例を Table() メソッドを例に示しています。異なる使い方:
- hash データを引数として受け取り、それを解釈して、Table を構築
- csv ファイル名を引数として受け取り、それを読み込んで、Table を構築
- csv フォーマットの string を引数として受け取り、それを解釈して、Table を構築
2.3節 コードブロック
話題は変わって。本の中でも「Enumeratable を使ったことがあるなら、自然とコードブロックを使っているはずだろう」と触れられているように、普通の Ruby プログラムであればコードブロックはいたるところに出てきます。
僕の中で一番最初に思いつくのは Array#each でしょうか。
この本では、コードブロックを使ってリファクタリング(共通部分の抽出)を行う例が挙げてありました。
元 Java の人としては、exec(...) を宣言した ISomeMethod インターフェースを実装するクラスを作って、そのインスタンスを対象のメソッドの引数として渡し、そのメソッドの中で exec(...) を呼び出す形に対応付けて覚えることにしました。
2.4節 Rubyらしいコード
また、話題は変わって。「Ruby らしいコード」になるためのテクニックをいくつか紹介しています。
attr_*
Ruby のクラスにクラス変数 ( @varname ) を定義するとき、たいていの Rubyist は(Javaプログラマと違って)
class Messageと書くそうです。
attr_accessor :message
def initialize(m)
@message = m
end
end
こう書けば、(本来カプセル化されてアクセスできないはずの)Message#message を参照・書き込みできます。
読み出し・書き込みのどちらか一方だけ自動生成したい場合は、attr_reader / attr_writer があります。
メソッドの後ろの "!" と "?"
Ruby の「暗黙のルール」として、- methodname? は bool 値を返す
- methodname! は「注意するべき操作」を示している
- 一般的には、破壊的操作(元のデータを書き換える操作)を示していることが多い
- 逆に ! のついていない対応する methodname は「(元のデータそのものではなく)コピーされた値を処理する操作」
演算子もメソッド
つまり、再定義によるカスタマイズが可能、ということです。 + や << などで表現できる「操作」があれば、それをカスタマイズされた演算子として定義するとコードがすっきりしそうです。おまけ:inject
2章の途中で、(かなり嘘が入っていますが、ざっくり言うと)こんなサンプルプログラムが出てきます。a = [ 1, 3, 4, 5, 7]あまり Ruby の経験のない自分ですが、このコードが異様なのは何となく分かります。「sum って一体どこから出てきたのだろう。どうやら要素の足し算をしているようだけど…」
a.inject(0) { |sum, element| sum + element }
# => 20
inject について調べてみたら、関数型言語で言うところの fold 関数であるらしいことが分かりました。
fold 関数については関数型言語好きな後輩から「foldはすばらしいですよ」と解説を受けたことがあったので、…存在だけは知っています(ごめんなさい、自信を持って理解してるって言えません)。「畳み込み」っていう言葉もイメージだけはできている気分です。
僕の中では、(配列・リストの)要素に対して構文木を作るイメージなんですが、それで伝わる人ってどのくらいいるんでしょうか…。
0 件のコメント:
コメントを投稿