LoginSignup
8

More than 5 years have passed since last update.

Ruby学習ログ

Last updated at Posted at 2015-09-10

概要

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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8