社内ruby勉強会資料 #2
今回のお題
- ブロック
- イテレータ
- Enumerable
なぜこのお題を選んだか
対象は他言語経験者
対象は他言語経験者
一般の方に向けては説明不十分だったが、今回の対象は他言語の経験者のため、多くの言語に共通する概念は説明不要。
例えば、文字列って何? 配列って何? といった話は、すでにわかっているものとして進む。
オブジェクト指向についても、言語の色はありつつも大枠は共通認識を持っていると考えている。
rubyのオブジェクト指向については、後々説明していく。
で、なんでこれ?
- rubyの特色がよく現れている
- この辺を使いこなせば、ああruby書く人だなと感じられる
- 訓練されたrubyistは
for
/while
/loop
の構文を忘れている1
- ブロックやイテレータはやはりとっつきにくい
- js書いてればわかるかなとは思いつつも
- 実際のコーディングで一番使い勝手が良い
ブロック
分類としてはメソッドを呼び出すときのシンタックスの一つ。
特別な機能を持っているわけではない。
見た目
パターン1
obj.foo(arg){ |bar| puts bar.do_something } # {}で囲われている部分がブロック
ブロック内が短く、呼び出すメソッドと同じ行内で済む場合、こちらが用いられることが多い。
パターン2
obj.foo(arg) do |bar|
baz = bar.do_something_with(other)
baz.save!
end
ブロック内での処理が複数行に渡る場合はdo 〜 end
を使うことが多い2。
注意事項
実は単なる見た目だけの違いだけではない。
評価時の結合度にも違いがあるので注意が必要。
参考1
参考2
- ブロックを使うときには
()
を省略しない - 複数行で評価される結果を使おうとしない3
あたりを気をつけていれば罠にハマることもないだろう。
やってみよう
余分なこともしつつ・・・
require 'tempfile'
tempfile = Tempfile.new
File.open(tempfile, 'w') do |f|
f.puts "Learning ruby"
f.puts "great language ruby"
end
content = File.read(tempfile)
p content.lines.map{|l| l.split.count}
-
split
はデフォルトで空白区切り- 楽だけど可読性を犠牲にしてる気もする(ほんの少しの驚きを与える)
イテレータ
- 反復・繰り返し処理を行うための機構
- 20年前に比べればかなり一般的な言葉になったね
- XPでイテレーションって呼ぶよね
- rubyはイテレータが強力なので
for
やwhile
を使う機会はほぼない
- 繰り返す内容はブロックで渡す
例
- 20年前に比べればかなり一般的な言葉になったね
- XPでイテレーションって呼ぶよね
for
やwhile
を使う機会はほぼない一緒にやってみよう
n回の繰り返し
5.times { puts "I love ruby" } # 洗脳中
# どういうことか確かめる
puts "------------------"
5.times { |i| printf("I love ruby%s(%d)\n", "!" * i, i) } # 更に洗脳中
ある範囲の値で
def schedule
1.upto(9) do |n|
puts " #{n}月 まだ大丈夫"
end
(10..12).each do |n|
puts "#{n}月 頑張る"
end
end
schedule
-
downto
もあるよ -
while
の代わりとしてはFloat::INFINITY
使うかなぁ4
コレクションに対する繰り返し処理
%w[string integer fixnum numeric bignum float array hash class module].each do |klass|
klass_name = klass.gsub(/^(.)/){|c| c.upcase}
puts klass_name + " < Object"
end
イテレータまとめ
- イテレータはブロックを使って繰り返し処理するもの
-
(n..m)
はRange
オブジェクトになるけど、(n...m)
と境界条件を間違えるかも - 処理内容と意図が直観的にわかるものを採用しよう
-
each
便利すぎるよ
Enumerable
-
each
を起点とした様々な便利メソッド群。
- ArrayとかHashとか、組み込みクラスにはもとからmix-inしているクラスが多い
- 多くのメソッドが実務でもsilverでも頻出なので、使いながら覚えよう。
やってみよう
- 1〜10の整数をすべて2乗する(
map
またはcollect
)
- 1〜10の整数で偶数のみ取得する(
find_all
またはselect
)
- 5000以上の整数の中で、13でも97でも割り切れる最初の数を取得する(
Float::INFINITY
使いつつfind
またはdetect
)
- 1〜500まで全てかけた積(
reduce
またはinject
)
- 1〜500まで全て足した和(
sum
)
- 1〜500までの数を8で割った剰余のみを足した和(
sum
)
-
{ruby: 1993, Elixir: 2012, golang: 2009, C: 1972, PHP: 1995 }
5を年代順に並べ替えよう(sort_by
)
-
[0,"",Object.new,Class,Module,[],{}]
がすべて真偽値として真となるか(all?
6)
-
("Aaaaa".."Zzzzz")
の範囲に'Ateam'が現れるか(any?
)
-
Enumerableのメソッドを
each
をもとにして自分で作ってみよう(暇な人用:車輪の再開発による理解)
each
を起点とした様々な便利メソッド群。map
またはcollect
)find_all
またはselect
)Float::INFINITY
使いつつfind
またはdetect
)reduce
またはinject
)sum
)sum
){ruby: 1993, Elixir: 2012, golang: 2009, C: 1972, PHP: 1995 }
5を年代順に並べ替えよう(sort_by
)[0,"",Object.new,Class,Module,[],{}]
がすべて真偽値として真となるか(all?
6)("Aaaaa".."Zzzzz")
の範囲に'Ateam'が現れるか(any?
)each
をもとにして自分で作ってみよう(暇な人用:車輪の再開発による理解)サンプル
p (1..10).map{|n| n**2}
p (1..10).select{|n| n.even?}
p 5000.upto(Float::INFINITY).detect{|n| n % (13*97) == 0}
p 1.upto(500).reduce{|n,m| n * m}
p (1..500).sum
p (1..500).sum{|n| n % 8}
p ({ruby: 1993, Elixir: 2012, golang: 2009, C: 1972, PHP: 1995 }).sort_by{|lang, year| year }
p [0,"",Object.new,Class,Module,[],{}].all?{|value| value ? true : false } # 真偽値を見たいことを明確にしてるだけ
p ("Aaaaa".."Zzzzz").any?{|text| text == "Ateam"}
今回のまとめ
- ブロックはメソッドの呼び出し方の一つ
- ブロックはよく繰り返し処理で使われるよ
- それをイテレータと呼ぶ
- Enumerableはイテレータを活用するモジュール
- いろんなクラスで使われてる
- 便利だから使おう。きっと使う。
- でもEnumerableのメソッドということに気づかないでいるだろう
- マニア的には内部イテレータによる拡張がEnumerableだよ
- さらにマニア的にはect系と呼んだりする頻出メソッドがあるよ
- 落とし穴がある!
-
find
とfind_all
はRoRで使うと、ActiveRecord
のfind
/find_all
と区別しにくくなる(しかも奴はブロックを受け付けない!)
- RoRの中で
Enumerable#find
/Enumerable#find_all
を使いたいときにはdetect
/select
を使おう
- それをイテレータと呼ぶ
- いろんなクラスで使われてる
- 便利だから使おう。きっと使う。
- でもEnumerableのメソッドということに気づかないでいるだろう
- マニア的には内部イテレータによる拡張がEnumerableだよ
- さらにマニア的にはect系と呼んだりする頻出メソッドがあるよ
-
find
とfind_all
はRoRで使うと、ActiveRecord
のfind
/find_all
と区別しにくくなる(しかも奴はブロックを受け付けない!) - RoRの中で
Enumerable#find
/Enumerable#find_all
を使いたいときにはdetect
/select
を使おう
Author And Source
この問題について(社内ruby勉強会資料 #2), 我々は、より多くの情報をここで見つけました https://qiita.com/sho0211/items/4f1e2bab6478348eb5ed著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .