Railsでの製作Tips

Rubyのメソッドの引数について

投稿日:2016年3月11日 更新日:

HackerRank

HackerRank.comは、オンラインでプログラミングの課題を解くサイト.
インドの人が多いからインドのサイトではないかと思う.
だいぶ前からあったような記憶だけど、今回、規約改定のメールが来たことがきっかけで、チャレンジしてみた.
分野(Domain)には、アルゴリズム・AIといった理論から、Java・Python・Rubyといった言語、データベースやSQL・シェルスクリプトもある.
Rubyの課題はすべて終えたので、備忘のためにメモをしておく.
(そのため、間違い・勘違いがあるかも.)

メソッドの引数

メソッドの書き方は

公式の文法によると

文法を眺めると、次のことがわかる.

  • 引数はデフォルト値をとることができること

  • *でrest_argsをとれること

  • キーワード引数をとれること

  • **でkwrest(キーワードrest?)をとれること

  • &でブロック引数を取れること(実はプロック)

デフォルト値

=で引数にデフォルト値を定めることができる.
基本的に、メソッド呼び出し時には、定義した引数と同数の値が与えられないとエラー(ArgumentError: wrong number of arguments (0 for N))になる.
けど、デフォルト値を定めたときはエラーにならず、デフォルト値が使われる.
ただし、n番目の引数にデフォルト値を定めたときは、n+i番目以降の引数もデフォルト値を定めるか、後で出てくる可変長引数を定める必要がある.

*をつけた可変長引数(rest引数)

引数に*をつけると、呼び出し時に余った実引数をまとめて配列にしてくれる.
ただ、1つのメソッドに1つしか定義できない.

キーワード引数

Ruby2.0からの機能.
引数を、(key: ‘デフォルト値’)の形で定めることができる.
キーワード引数は、呼び出し時に順不同で与えてもよいし、与えなくてもよい(デフォルト値が使われる).
ハッシュにして、まとめて実引数にすることもできる.
ただ、定めてないキーを渡すとエラーになる.

**をつけたkwrest引数

**をつけた引数は、定められていないキーワード引数の形をまとめてハッシュとして引き取ってくれる.
単に**だけでも使える.その場合は単に他のキーワードは無視される.
正式名称がわからない.
エラーを起こさせないように使うほかは、黒魔術用に使われている気がする.

ブロック引数

ブロックは、do .. endや{..}で表現される無名関数みたいなもので、その結果をメソッドに与えることができる.
ブロック引数は特に定めてなくても、与えることができる.

yield

与えられたブロックを実行するにはyieldと唱える.
ブロック引数に変数を与えることもできる.

使いみちとすると、再帰的な処理に使うのかな.HackerRankの出題でも意図が不明とみんな言ってた.

block_given?

block_given?でブロックが与えられているかどうか判別できる.

Proc

実は、メソッドにブロックが与えられたとき、Procオブジェクトとして取り扱われている.
Procは手続きオブジェクトと呼ばれていて、手続きを意味するprocedureの略だけど、BlockとProcで韻を踏んでいるのがミソ(参照).
そのメリットの第1は、メソッドだけではメソッドを戻り値としたりできないけど、Procを使えばメソッドからメソッドみたいなものを渡すことができるようになること.これを使えば、プログラムの表現の幅が広がる.
また、第2は、状態を持った関数(クロージャという)としての機能が得られること。(参照)

Procを制する者がRubyを制す(嘘)

&をつけたproc引数

&をつけた引数はProc.newで生成されたそれと同じように振る舞う.
なので、文法だとblock_argとしているけど、ブロックではなく実はプロック.

引数としてとったprocは、メソッド内のcallで呼び出すことができる.

Symbol#to_proc、Method#to_procとの組み合わせ

Symbol#to_procというのは、シンボルと同名のメソッドを返すProc

そこで、ブロックを与えるべきところを、&をつけてProcであることを明示してSymbol#to_procを与えると、各レシーバに対してシンボル名と同名のメソッドを実行することができる.

さらに、&を前置したとき、to_procは省略できる.

これは、次のブロックを与えたときと同じ結果になるけど、sなどを2度書かなくてよい分スマート.

Rubyで “&” を使うと幸せになれるらしいよ (*´Д`)ノ

上の書き方は、各レシーバのメソッドを実行することができるけど、各レシーバを引数に取る場合は次のようにMethod#to_procを使って書ける.

これは、次のブロックを与えた時と同じ.

methodはObjectのメソッド(つまり、すべてのクラスの根源なのでどんなオブジェクトに対しても使える)で、対象をMethodオブジェクトに変換する.
Methodオブジェクトが何かはともかく、Methodオブジェクトもto_procを持っているので、&で呼び出せば暗黙的にProcとして扱われる.

Rubyでメタプログラミング ~暗黙的に呼ばれるto_procメソッド

Closures

クロージャは状態を持った関数で、変数のように代入やメソッドへの受け渡しができるもの.
たぶん関数型言語発祥の考え方.
RubyでのブロックやProc(lambdaも)はクロージャにあたる(らしい).

リンク先の例がわかりやすいので引用した.

lambda

lambdaは無名関数でProc由来のオブジェクトなんだけど、Proc.newでできる無名関数みたいなものがフワッとしているのに対して、厳密な感じ.
Rubyの ブロック、Proc.new、lambdaの違い
Ruby1.9からは->でも書ける.

引数の取り方が、普通のブロックと違って|a,b|ではないので注意.

Partial Programing

ラムダを使うと、汎用的な処理を使い回すことができる.
例えば、1次関数の一般的なものを作って、a,bの値によって使い回すには

代入の仕方が、Rubyで直感的じゃないので注意.

currying

curryメソッドを使っても同じようなことができる.
カリー化

これは説明を読むより、実例をみたほうが理解しやすい.

知って得する21のRubyのトリビアな記法 4. 関数部分適用
Procオブジェクト

遅延評価との組み合わせ

遅延評価については、無限リストを map 可能にする Enumerable#lazy
ラムダでも、Enumerable#lazyを組み合わせると便利かも.

これはhackerrankの例

HackerRankの攻略

たぶん英語力を別にすればRubyの課題は高校生くらいであれば解ける問題だと思う(デジタルネイティブならもっと早いかも).
周辺問題のヒントを書いておく.

初期値の処理

rubyでは、STDINではいる初期値をgetsで取れる.
HackerRankでは、問題で定められた数だけ、getsを実行しないと初期値が取れない.
次に、初期値が、”8 9¥n”というようなStringで入ってくるので、これをまず処理しないと始まらない.
こういう場合、gets.split.map(&:to_i)すれば、[8,9]と処理しやすい形で取り出せる.
((&:to_i)は、{|x|x.to_i}と同じ)
HackerRankでもいくつかの事例で同じような初期処理が書いてある.

とりあえず標準出力

Run Codeでとりあえず実行.Submit Codeで最終提出.(もちろん通らなかったらやり直せる.)
なので、おそれずRun Codeして試してみるのがよい.
pなどを使えばOutputに表示されるので、値を出しまくる.

ほかのテストケースもパスしないといけない

問題に過剰適応したプログラムを書いても、汎用性がないとほかのテストケースが通らない.
ちゃんと汎用性をもった、プログラムを書かないとクリアできない.
なお、テストケースは、サイト内で稼げるhackosという通貨(?)で購入することができる.

Discussionを参照

ほんとに困ったら、Discussionを読めばヒントがあったりする.

プログラム初学者向けではない

高校生くらいで解けるといいながら、指導者がプログラム初学者にHackerRankの課題を解かせるのはおすすめできない.
プログラム自体が嫌いになってしまうかも.
Rubyには豊富なRubyGemsというライブラリ集があるのだから、これを利用することからはじめて、万能感や楽しさを味わってから、Gemの中身を読んだりするようになってから挑戦しても遅くはないと思う.

-Railsでの製作Tips
-,

執筆者:

関連記事

RailsのフォームにjQuery UIのSliderを使う

By: woodleywonderworks – CC BY 2.0 目次1 jQuery UI Slider2 ライブラリを読み込む3 コード4 できた jQuery UI Slider …

Pryの関係gemが最初からいろいろはいったjazz_fingersを試してみた

By: george ruiz – CC BY 2.0 目次1 jazz_fingersのインストール2 インストールされるGem3 Pry4 awesome_print5 hirb6 p …

Selenium IDEからRubyのテストケースを書き出す

By: Kenny Louie – CC BY 2.0 目次1 Selenium IDE2 Selenium IDEのインストール3 Selenium IDEの立ち上げ方4 はじめてのSe …

Railsでdate_fieldにjquery uiのdatepickerを使おうとしたらchromeのdatepickerとかち合ってしまったとき

By: Randy Heinitz – CC BY 2.0 text_fieldにしとけば、jQuery UI datepickerは使える. [crayon-58b3ca2c91d5c6 …

Rails5でAjax処理をActionCableを使ってリアルタイム同期化

By: Mike Johnston – CC BY 2.0 目次1 はじめに2 サンプル掲示板3 ActionCableでリアルタイム化4 チャンネルを購読して、ストリームで分配する5 c …