概要
Rubyの言語機能学習中に躓いた部分をまとめました。
理解が簡単だった物は含めていないので、他言語学習済みのRuby初心者向けだと思います。
Kernel.#p
#printの引数にinspectと改行を適用した値が表示される
print "a" #=> a(改行なし)
p "a" #=> "a"(改行あり)
慣習
# 行末までコメント
# 慣習的に#=>の右側に実行結果を書く事が多い
# aの実行結果が1という説明(printが省略される事もある)
a = 1
a #=> 1
# 真偽値を返すメソッドの最後に?を加える
def true?
true
end
# 破壊的な作用をもつメソッドの最後に!を加える
def break!
# 自分自身を書き換える等
end
# 一番最後に評価した式が自動でreturnされるので、明白な場合はreturnを省略する
def default_array
[] # return []と同じ
end
ハッシュ
#:を付けるとシンボルとなり、常に一意のオブジェクトが返ってくる
h = {:symbol => "a"} # h = {symbol: "a"}と同じ
h[1] = "b"
h["string"] = "c"
class Foo; end
foo = Foo.new
h[foo] = "d"
p h #=> {:symbol=>"a", 1=>"b", "string"=>"c", #<Foo:0x007efefc73e1a8>=>"d"}
式展開
任意の式を文字列に埋め込むことができます。
p "1 + 1 = #{1 + 1}" #=> "1 + 1 = 2"
ブロック
do ... end
または{...}
で囲まれた範囲をメソッドの後ろに付ける事ができ、このコード片をブロックと呼びます。
# ブロック付きメソッド呼び出し
# メソッドの後にブロックを書く事ができる
p {a}
# ブロックパラメータ
# ブロックが受け取る変数を定義できる
p {|a, b| p a, b}
# ブロック内部はyieldが実行される度に実行される
def foo
yield
yield
end
foo {print "a"} #=> "aa"
# 利用する関数に引数を適用したりyieldで値を返したりできる
def bar(a)
yield a
end
bar(1){|a| p a} #=> 1
proc, lambda
ブロックをオブジェクトにした物です。
def foo(a, function)
function.call(a)
end
foo(1, lambda{|a| p a}) #=> 1
foo(1, -> a{p a}) #=> 1
foo(1, proc{|a| p a}) #=> 1
foo(1, Proc.new{|a| p a}) #=> 1
&演算子
&演算子はProcオブジェクトをブロックへ変換し、ブロックをProcオブジェクトへ変換します。
# 引数が無いのでブロックしか渡せない
def foo
yield
end
foo {p 1}
# &演算子でブロックに変換する必要がある
foo &lambda{p 1}
# ブロック引数
# ブロックを受け取るには&演算子でprocに変換する必要がある
def foo(&function)
function.call()
end
foo {p 1}
foo &lambda{p 1}
# &演算子を使わない場合はブロックは受け取れない
def bar(function)
function.call()
end
# bar {p 1} # エラー
bar lambda{p 1}
# &演算子の要求に従い、シンボルはSymbol#to_proc関数によりprocに変換される。そして、&演算子によりブロックに変換される
def foo
p yield(1, 2) # 1 + 2
end
foo(&:+) #=> 3
参考
http://www.infoq.com/jp/news/2008/03/to_proc-currying-ruby19
展開
配列を引数に展開して渡したり、引数を配列で受け取ったりできます。
# 配列を引数に展開して渡す
def foo(a, b, c, d)
print a, b, c, d
end
array = [2, 3, 4]
foo(1, *array) #=> 1234
# 引数を配列で受け取る
def bar(a, *b)
print a, b
end
bar(1, 2, 3, 4) #=> 1[2, 3, 4]
範囲式
print 1..9 #=> 1..9
print *1..9 #=> 123456789
p [*1..9] #=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
メソッド
Rubyには3種類のクラスへのメソッド設定方法があります。
# Instance methods
# インスタンスしかメソッドを利用できない
class Foo
def speak; end
end
# Singleton methods
# インスタンスにメソッドを追加する
class Foo; end
foo = Foo.new
# 特異メソッド形式
def foo.speak; end
# 特異クラス形式
class << foo
def speak; end
end
# Class methods
# クラスにメソッドを追加する
# 特異メソッド形式
class Foo
def self.speak; end
end
# 特異クラス形式
class Foo
class << self
def speak; end
end
end
注意しなければいけない点として、特異メソッド形式では通常のprivateが適用されない点があります。
class Foo
private
def self.speak; end
end
Foo.speak # エラーが出ない
private_class_methodにシンボルを渡す事でエラーにする事ができます。
class Foo
def self.speak; end
private_class_method :speak
end
参考
http://www.integralist.co.uk/posts/eigenclass.html
include, extend
includeで取り込んだmoduleはInstance methodsとして取り込まれ、extendで取り込んだmoduleはClass methodsとして取り込まれます。
module Base
def function; end
end
class Foo
include Base
end
class Bar
extend Base
end
# Foo.function #エラー
Bar.function
Foo.new.function
# Bar.new.function #エラー
また、moduleはnewできないので利用方法がシンプルになります。
module A
def foo; end
def bar; end
end
module B
include A # ここでextendするとfooの中でbarもsuperも使えない
def foo
bar
super
end
end
module C
extend B # ここでincludeするとmoduleはnewできないので利用できない
end
C.foo
また、selfを付ける事で関数を利用する事ができるようになりますが、再利用が難しくなります。
module A
def self.foo; end
end
module B
include A
end
module C
extend A
end
A.foo
#B.foo # エラー
#C.foo # エラー
参考
Rails: includeされた時にクラスメソッドとインスタンスメソッドを同時に追加する頻出パターン
http://sekai.hateblo.jp/entry/2013/08/23/083258
%記法
エスケープやコマンド結果を取得する記法です。
種類が多いのと書き方が自由なので判別が難しいです。
# 任意の非英数字を挟むリテラルに使える
p %!a! #=> "a"
p %$a$ #=> "a"
p %[a] #=> "a" # 括弧も使える
# %の後の記号でエスケープ方法を選択できる
p %!"'\"! #=> "\"'\""
p %q["'\"] #=> "\"'\\\""
p %r("'\") #=> /"'\"/
p %w(a b c) #=> ["a", "b", "c"]
特殊変数
$から始まる変数はグローバル変数です。
その中でも特殊変数と呼ばれるグローバル変数があります。
https://gist.github.com/kwatch/2814940
参考
http://qiita.com/merrill/items/0a77df7f61d0d6b8e875
http://qiita.com/kidach1/items/15cfee9ec66804c3afd2