第34回 Ruby/Rails 勉強会 - 演習 1

第34回 Ruby/Rails 勉強会 の宿題。

疎な配列と同じデータを表現するハッシュを比較する。

以下のようにアクセスできるデータを作成して比較する。

a[0]    # => 0
a[10]   # => 10
a[90]   # => 90

each すれば違いが分かる。

def dump(e)
  print e.class
  e.each{|i| print " #{i.inspect}"}
  puts
end

a = []
a[0] = 0
a[10] = 10
a[20] = 20

h = {}
h[0] = 0
h[10] = 10
h[20] = 20

dump a  # >> Array 0 nil nil nil nil nil nil nil nil nil 10 nil nil nil nil nil nil nil nil nil 20
dump h  # >> Hash [0, 0] [10, 10] [20, 20]

90 だとデカすぎるので 20 で。

Ruby であまり for 式が使われない理由をみっつ考えてください。

グループで each と for の違いを議論した。

  • each はメソッドで for は Ruby の構文。
  • each はブロックなのでスコープができる。
  • for はスコープを作らない。

each なら、ブロックを抜けるとブロック内の変数にはアクセスできない。

(0..9).each do |i|
  j ||= 0
  j += i
end
j   # => undefined local variable or method `j' for main:Object (NameError)

for なら、ループを抜けても変数にアクセスできる。

for i in 0..9 do
  j ||= 0
  j += i
end
i   # => 9
j   # => 45

肝心の理由は、

  1. for は Ruby らしくないから。

かな?

階乗を求めるプログラムのループ版を書いてください。

レッスンで紹介された再帰

def factorial(n)
  return 1  if n <= 1
  n * factorial(n - 1)
end

factorial 5             # => 120

(1..5).inject(&:*)      # => 120

inject 版はマニアックすぎ。
女子大生に質問されて困ったww

ループ版

def factorial(n)
  f = 1
  for i in 2..n do
    f *= i
  end
  f
end

factorial 1     # => 1
factorial 3     # => 6
factorial 5     # => 120

無理矢理 for 使ってみた。