に関して、練習します。
他の言語と比較してRubyのコードブロックの扱いは特徴的で扱い難そうに見えますが、使いこなせればコード量を減らせるし、その結果として可読性も増すので、慣れていきたいです。
def times_n(n) lambda { |x| x * n} # Kernel#lambdaの引数はブロック # lambda do |x| x * n end でもよい(複数行に渉るときなど)。 end times_ten = times_n(10) # nに10を代入 # 生成されたtimes_tenはProcインスタンス p times_ten.class #=> Proc # times_ten = { |x| x * n} はエラー。 # {}でのブロックはメソッドの引数としてのみ渡せる。 # また、ブロック引数はメソッドの最後の引数として定義する。 # ブロックの実行にはcallメソッドを用いる p times_ten.call(5) # ブロック変数xに10が代入される #=> 50
ここで、クラスProcとは
Proc はブロックをコンテキスト(ローカル変数のスコープやスタックフレーム)とともにオブジェクト化した手続きオブジェクトです。
– Rubyリファレンスマニュアル : Proc
続けて、以下も練習してみる。
arr1 = [1, 2, 3, 4, 5] arr2 = arr1.collect(&times_ten) p arr2 #=> [10, 20, 30, 40, 50] p arr2.class #=> Array
ここで、Enumerable#collectは、
collect : 各要素を順番にブロックに渡して評価し、その結果で要素を置き換えます。
Rubyリファレンスマニュアル : collect
ブロックが格納された変数をメソッドの引数として渡すときは「&」をその変数名の前につけます。
仮につけないと以下のようなエラーが出ます。
`collect': wrong number of arguments (1 for 0) (ArgumentError)
最後に、selectメソッドを用い、同時に評価に条件を組み込んでみます。
def times_n(n) lambda { |x| x * n} # lambdaの引数はブロック end times_ten = times_n(10) # nに10を代入 ceiling = 50 arr3 = [1, 25, 50, 55, 30, 100] p arr3.select { |x| x < ceiling } #=> [1, 25, 30] arr4 = [0.1, 2.5, 5, 5.5, 3, 10] p arr4.collect(&amp;times_ten).select { |x| x < ceiling } # -.-; #=> [1.0, 25.0, 30]
arr3の要素が順にブロック変数xに読み込まれます。
select : 各要素に対してブロックを評価した値が真であった要素を全て含む配列を返します。真になる要素がひとつもなかった場合は空の配列を返します。 –
Rubyリファレンスマニュアル : select