Upload
takeshi-akima
View
535
Download
0
Embed Size (px)
DESCRIPTION
2008年11月のLL温泉でRubyの話をした時の資料
Citation preview
Rubyの基本LL温泉 2008/11/14~16
Takeshi AKIMA
agenda•はじめに
•メソッドの基本
•基本的なクラスを押さえる
•ブロックの基本
•モジュールの基本
はじめに対象者をちょっとRubyを触ったことがある人に限らず、基本的な部分をひたすら試していきます
楽しんでいきましょー!
Happy Hacking!
irb•対話型のRubyの実行環境
•コンソール(コマンドプロンプト)で
> irb
で実行
•今日は基本これでやるよ
Rubyのリファレンス•困ったらここを見よう
http://www.ruby-lang.org/ja/man/
•最新版はあるんだけど、これで勉強した僕としては、ここが一番!
•でもちょっと取っ付きにくいので、他のを見てもOK
try!try!
メソッドの基本
•処理の基本はとにかくメソッドっす
•「クラスとは」とか言わずに、ひとまずやってみようぜ~
•例えば、fooって出力するfooメソッドを持っているオブジェクト、どう作る?
こんな感じが普通かな?class Foo def foo puts "foo" endendobj = Foo.newobj.foo
でもね、こんな風にも書けるよ
obj = Object.newdef obj.foo puts "foo"endobj.foo
ちょっと変かもだけどさ・・・
•ふつーはクラスを作ることを考えるかもしれないけど、それって絶対?
•クラスを考えなくてもいい時があるんじゃない?
•クラスじゃなくてオブジェクトを中心に考えていこう!
メソッドの呼び出し?いやいや、メッセージ送信!
•「メソッドの呼び出しをメッセージ送信と呼ぶ」なんてオブジェクト指向の本に書いてあるけど、それはそういう言い方をするだけだよね?なんて思っているアナタ!Rubyでは違うんだよ~
必ず戻り値があるよobj = Object.newdef obj.fooendobj.foo
def obj.bar "BAR"endobj.bar
obj = Object.newdef obj.baz(a) if a.to_i > 0 return "a natural number" else "number?" endendobj.baz(2)obj.baz(-100)
method_missingobj = Object.newdef obj.method_missing(method, *args) "message received! #{method}"endobj.fooobj.bar("XXXX")obj.baz(1, 2, 3, :x => 500, :y => 200)
send
obj = Object.newdef obj.foo "FOO"endobj.fooobj.send('foo')
本当にメッセージを送ってる感じがするで
しょ?
メッセージ受信可?obj = Object.newdef obj.foo puts "foo"endobj.respond_to?(:foo)obj.respond_to?(:bar)
重要!
重要!
Rubyのメッセージング
•オブジェクトが本当にメッセージを送信してるのが体感できた?
•メソッドが定義されてなくても、
メッセージを送信することはできる!
==> 普通エラーになるけどね
デフォルト引数を受け取ってみよう
obj = Object.newdef obj.foo(a, b = 1) "a => #{a.inspect}, b => #{b.inspect}"endobj.foo("A")obj.foo("B", 5)
可変引数で何個でもobj = Object.newdef obj.foo(name, *args) "#{name} #{args.inspect}"endobj.foo("A")obj.foo("B", 1, 2)obj.foo("C", 1, 2, 3, 4, 5, 6, 7, 8, 9)
名前付き引数?
obj = Object.newdef obj.foo(options) options.inspectendobj.foo(1)obj.foo(:name => "A", :no => 10)
名前付き引数obj = Object.newdef obj.foo(a, b, options)endobj.foo(1, 2, :name => "A", :no => 10)obj.foo(1, 2, {:name => "A", :no => 10})obj.foo(1, {:name => "A", :no => 10}, 2)obj.foo(1, :name => "A", :no => 10, 2)上の2つのfooの呼び出しは全く同じ意味です。{}はHashという連想配列のオブジェクトね。引数の一番最後には{}を省略してHashを記述することができます
変数、定数ローカル変数 一般的な変数。小文字で宣言されているもの。 慣習とし
ては、underscore_style
インスタンス変数 インスタンス毎に保持される変数。@が先頭に付きます。 慣習としては、@underscore_style
クラス変数 クラス毎に保持される変数。@@が先頭に付きます。 慣習としては、@@underscore_style
グローバル変数 $で始まるやつ。既にある奴を使うだけにしておこう!
定数 大文字で始まるもの。通常全部大文字のUNDERSCORE_STYLE
クラス名 大文字で始まるもの。通常CamelCaseStyle
try!try!カウントさせよう
obj = Object.newdef obj.count_up # この中身を書くだけでできるはずendobj.count_up #=> 1obj.count_up #=> 2obj.count_up #=> 3
関数ちっくに書く•Rubyではオブジェクトを省略してメソッドを書けるよ。まるで関数だね。
•実はKernelってやつのメソッドになります
• Kernel.methods.sort で調べてみてね
• Kernelについてはまた後で
def foo "FOO"end
リファレンスと本だけが調べる術じゃないっす
•Rubyのオブジェクトは結構自分自身のことを語ってくれます。
Object#methods
"ABC".methods:ABC.methods[1,2,3].methods{"A" => 1, "B" => 2}.methods1.methodstrue.metodsnil.methods
Object#class"ABC".class:ABC.class[1,2,3].class{:a => 1, :b => 2}.classa = "ABC"a.is_a?(String)a.is_a?(Symbol)a.is_a?(Array)
基本的なクラス
•押さえておきたいクラスはそんなに多くないっす
• Array, Hash, Symbol, Stringを押さえておけば、ひとまずはOK
Strings = "ABC"s << "D"s += "EFG""a,b,c,d".split(',')"now: #{Time.now}""a,b,c,d".gsub(/b/, "B")"123".to_i"ABC"[1]"DEF".downcase"ghijk".include?("gh")
Symbol
"a".to_sym:a.to_s"a".object_id"a".object_id:a.object_id:a.object_id
Stringの問題try!try!
try!try!
try!try!
•文字列の中から数字のみを抜き出すpickup_numberメソッド
• SymbolかStringのオブジェクトを渡すと、末尾に _onsen が付いたSymbolを返す onsenizeメソッド
• s = "ABC" に対して以下の違いは何?s << "D"s += "D"
Arraya = [1, 2, 3]a[1]a << 4a += [5, 6]a.lasta.popa[1..-2] = [20, 30, 40]a.join(",")a.each{|value| puts value}
[4, 6, 4, 9].sort[4, 6, 4, 9].reverse[4, 6, 4, 9].uniq
try!try!
try!try!
try!try!
• get_at([1,2,3], :first) => 1get_at([1,2,3], :last) => 3となるようなget_atメソッド
•カンマ区切りの文字列をバラして、ソートするsplit_sortメソッド
•数値のみで構成される配列の要素の合計を求めるsum_arrayメソッド
Arrayの練習
Hashh = {"A" => 65, "B" => 66}h["A"]h["C"]h["D"] = 67h.keysh.valuesh.each do |key, value| puts "#{key} => #{value}"end
try!try!
try!try!
try!try!• Hashと文字列を渡すと、キーの一部が該当する値を配列で返す、select_valuesメソッド
•複数のHashの足し算をするmerge_hashメソッド(キーが重複したら上書きね)。def merge_hash(*hashes) って感じで
•どんなHashでもJSONのオブジェクトになる文字列 "{'キー': '値'}"にしちゃう、to_jsonメソッド
Hashの練習
try!try!可変引数で、最後は名前付きの引数•これまでのテクを組み合わせればきっとできる!
• obj.foo(1, 2, 3) => [1, 2, 3] {:name => "A", :no => 1}
• obj.foo(1, 2, :name => "B") => [1, 2] {:name => "B", :no => 1}
• obj.foo(:name => "B") => [] {:name => "B", :no => 1}
• というfooをよろしく
ブロックの基本
•メソッドよりも細かく処理の断片を記述するもの
•クロージャとか色んな呼び方があるけど、「ブロック」って呼んでね。
重要!
重要!
ブロック[1, 2, 3, 4].each{|value| puts value}[1, 2, 3, 4].each do |value| puts valueend
「[1, 2, 3, 4]っていう配列のeachメソッドにブロックが渡されている」って読んでください。
どんなメソッドでもブロックは受け取れる
def foo "FOO"endfoo{ puts "BAR" }
ただし、受け取るだけで勝手に呼び出すことはできないっす
渡されたブロックを呼び出す
def foo yieldendfoo{ puts "BAR" }
def bar yield yield yieldendbar{ puts "BAR" }
渡されたブロックに引数を渡して呼び出すdef foo yield("FOO")endfoo{ "BAR" }
foo{|v| v }
ブロックの戻り値を使う
def foo yield * 100endfoo{ 1 }foo{ "BAR" }
ブロックを他のメソッドに渡す
def foo yield("FOO")enddef bar(&block) foo(&block)endbar{|v| v * 3 }bar{|v| "C" + v }
ブロックを他のメソッドに渡す
def foo yield("FOO")enddef bar foo{|v| yield(v) }endbar{|v| v * 3 }bar{|v| "C" + v }
try!try!処理の順番のログがほしい!
def foo log("in foo"){ yield("FOO") }enddef bar log("in bar") do foo do |v| log("in block for foo"){ yield(v) } end endendbar do |v| log("in block for bar"){ v * 3 } end
in bar beforein foo beforein block for foo beforein block for bar beforein block for bar afterin block for foo afterin foo afterin bar after=> "FOOFOOFOO"
左のコードを実行したら、下のように出力されるlogメソッド。{}のブロックは、do...endに置き換えた方が分かるかも。
モジュールの基本
•Rubyのモジュールは、メソッドは持ってるから、クラスっぽいけどインスタンスは作れないやつです
•モジュールを使うと、オブジェクトにメソッドを追加することができます
オブジェクトにメソッドを追加する方法
•def obj.foo
• fooを持ったモジュールをobjにextend
• objのクラスで def foo
• fooを持ったモジュールをクラスにinclude
オブジェクトに追加obj = Obj.newdef obj.fooendobj.bar
Object
obj
foo
extendで追加obj = Obj.newobj.foomodule Foo def foo endendobj.extend(Foo)obj.foo
Object
obj foo
Foo
普通にクラスで書く
class Foo def foo endendobj = Foo.newobj.foo
Object
foo
Foo
obj
includeで追加class Barendobj = Bar.newobj.foomodule Foo def foo endendclass Bar include Fooendobj.foo
Object
Bar
obj
foo
Foo
モジュールはモジュールをinclude可能
module Foo def foo; endendmodule Hoge include Fooendclass Bar include Hogeendobj = Bar.newobj.foo
Object
Bar
obj
foo
Foo
Hoge
モジュールを何個でもinclude可能
module Foo def foo; endendmodule Baz; endmodule Hoge include Foo include Bazendmodule Fuga include Bazendclass Bar include Hoge include Fugaendobj = Bar.newobj.foo
Object
Bar
obj
foo
Foo
Hoge
Fuga
Baz
重要!
重要!Enumerable重要!
•ArrayやHashなどRubyの便利なクラスがincludeしているモジュールです。
•ここには非常に便利なメソッドが沢山用意されています。
•map, select, any?, all?, inject・・・
もう一回練習
try!try!
try!try!•文字列の配列から各要素をn回繰り返し、それらをカンマで区切った文字列を返すrepeat_joinメソッド
•数値のみで構成される配列の要素から奇数を抽出して合計を出すodd_sumメソッド