こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

rubyの特異メソッド

Rubyプログラミング入門という本を読んでいた際、
フィボナッチ数列を求めるプログラムが例としてありました。
以下はソースと実行結果です。

def (Fib = [0, 1]).[](n)
super || Fib[n] = Fib[n-1] + Fib[n-2]
end
p fib(30)[0] #=>832040

このプログラムを理解するキーワードは特異メソッドと明記されていましたが、
(Fib = [0, 1]).[](n) や super || Fib[n] の部分がわかりません。
ご教授よろしくお願いします。

投稿日時 - 2008-07-15 10:21:25

QNo.4177879

暇なときに回答ください

質問者が選んだベストアンサー

>p fib(30)[0] #=>832040
これ、本当にこの通りですか?

たぶんFib[30] だと思うんですが。


>irb
irb(main):001:0> def (Fib = [0, 1]).[](n)
irb(main):002:1> super || Fib[n] = Fib[n-1] + Fib[n-2]
irb(main):003:1> end
=> nil
irb(main):004:0> fib(30)[0]
NoMethodError: undefined method `fib' for main:Object
from (irb):4
from :0
irb(main):005:0> Fib(30)[0]
NoMethodError: undefined method `Fib' for main:Object
from (irb):5
from :0
irb(main):006:0> Fib[30]
=> 832040
irb(main):007:0> Fib.class
=> Array
irb(main):008:0> Fib.methods.sort
=> ["&", "*", "+", "-", "<<", "<=>", "==", "===", "=~", "[]", "[]=", "__id__",
"__send__", "all?", "any?", "assoc", "at", "class", "clear", "clone", "collect",
"collect!", "compact", "compact!", "concat", "delete", "delete_at", "delete_if",
"detect", "display", "dup", "each", "each_index", "each_with_index", "empty?",
"entries", "eql?", "equal?", "extend", "fetch", "fill", "find", "find_all",
"first", "flatten", "flatten!", "freeze", "frozen?", "grep", "hash", "id",
"include?", "index", "indexes", "indices", "inject", "insert", "inspect",
"instance_eval", "instance_of?", "instance_variable_defined?",
"instance_variable_get", "instance_variable_set", "instance_variables",
"is_a?", "join", "kind_of?", "last", "length", "map", "map!", "max",
"member?", "method", "methods", "min", "nil?", "nitems", "object_id", "pack",
"partition", "pop", "private_methods", "protected_methods", "public_methods",
"push", "rassoc", "reject", "reject!", "replace", "respond_to?", "reverse",
"reverse!", "reverse_each", "rindex", "select", "send", "shift",
"singleton_methods", "size", "slice", "slice!", "sort", "sort!",
"sort_by", "taint", "tainted?", "to_a", "to_ary", "to_s", "transpose", "type",
"uniq", "uniq!", "unshift", "untaint", "values_at", "zip", "|"]
irb(main):009:0> f = [0,1]
=> [0, 1]
irb(main):010:0> f.class
=> Array
irb(main):011:0> f[0]
=> 0
irb(main):012:0> f[1]
=> 1
irb(main):013:0> f[2]
=> nil
irb(main):014:0>

で、
def (Fib = [0, 1]).[](n)

Fib = [0, 1]

def Fib.[](n)
に分解されます。
Fib = [0, 1] で、Array クラスのインスタンス Fib を作ります。
そして、インスタンスFibの特異メソッドを定義します。

super || Fib[n] = Fib[n-1] + Fib[n-2]
は、まずメソッド super を実行します。つまり、Arrayクラス本来の [] メソッドを実行しますが
その戻り値が nil であった場合、||の右側を実行します。
つまり、フィボナッチ数列の第n項を求めます。
式の値は代入の結果であり、、また最後に実行された式なので
メソッドの返す値となります。

投稿日時 - 2008-07-15 21:32:22

お礼

>たぶんFib[30] だと思うんですが。
他のフィボナッチ数列のサンプルプログラムと誤植してました。
まさにその通りです。すいませんでした。

>def (Fib = [0, 1]).[](n)
def Fib.[](n)で引数がnの時の特異メソッドを定義し、

>super を実行、つまりArrayクラス本来の [] メソッドを実行
このsuperで既に計算してある第n項があればその値を返すのですね。

大変勉強になりました。ありがとうございます。

投稿日時 - 2008-07-15 23:52:49

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(1)

あなたにオススメの質問