アラフォーがお金持ちになるためエンジニア目指すブログ

お金も根性も学歴もないアラフォーまきのがエンジニアになってお金持ち目指すよ!

Rubyの勉強中知ったことめも2

どうも、アラフォーまきのです。

今日はメソッドのことでメモをしておきます。

 

 

ちなみに今使ってる教科書はこちら。

ところどころの表現がゆるくて面白い(笑)

 

ハマった部分

今回課題でもらった部分は、教科書「たのしいRuby」でいう7章の「メソッド」なんですが、メンターさんがくれた問題集ではこんな問題があったんです。

 

f:id:MmRevorution:20180923103243p:plain

 

ここでどハマりです。時間にして5h以上考えたよね(笑)

 

実装したい内容

ここで実装したいのは「fruit : true」のものだけ抽出するって処理だなってことはわかったんですよね。

だから「returnすればいいのか」と単純に発想してこんなコードを書いたんです。

 

f:id:MmRevorution:20180923104325p:plain

 

このコードの問題点

  • whileの書き方がよくない

while index < 4」ってなってるけど、これ配列の要素が増えたらダメじゃんねという。

要素が増えてもOKなように書くほうがいいですよね。

実は前回の授業でどう書くといいか教わったのに、すっかりメモを忘れてしまったので、あとで「index < 配列名.size」だと教わり直しました!

 

  • retrunしたら処理が終わることを忘れてる

ターミナルにある通り、リンゴしか出てない。

retrunって、値を返すだけじゃなくてその時点で処理終了だから、後にいくら書いても処理されないんだった。

だからその後の「index += 1」も無駄になってるし。

 

次にやってみたこと

returnでは処理が終了しちゃう。

要素にはリンゴの他にもアイテムがある。

ならputsにしたらいいじゃないと発想したまきのはこんなコードを書きました。

f:id:MmRevorution:20180923105537p:plain

このコードの問題点

  • まだwhileが直ってない

前述通り、メモし忘れてる上考え方も理解してなかったので思い出せず。

ネットで調べてもそれらしいものを見つけることができなくて、とりあえず放置になってました(笑)

 

  • 定義する中でputsは不要だということに気が付いていない

呼び出しの時にputsするから、定義としてのputsはいらないんですよね。

だけど「retrunではリンゴだけで処理が終了する」という事実にとらわれて、すっかり見落としてますね。

 

そして、一見想定通りに出たように見えたけれど、無駄な空白(あとでnilだとわかる)が出力されてますねー。

 

次にしたこと

さあどんどん動きが怪しくなってまいりました(笑)

ここでまきのは、繰り返し処理を他のやり方にしたらどうなる?など色々やり始めてさらにドツボにハマりました。

 

eachやらforやら試したり、いやelseでfalseだった時の処理を書いてみるかとか、配列やハッシュ、ifなどについてめっちゃ調べたりとにかく迷走しました(笑)

 

そしてついに時間が勿体無い!と諦めがついてメンターさんへ泣きついたのでした。

ただこの時、私はメンターさんにコードを見せたのと「変な1行が出る」ということだけを伝えていました。

 

メンターさんからのヒント1 「putsをpで見てみてごらん」 

実は相談前にpにしてみたつもりでした。

でも、ifの中だけpにして、最後の22行目をputsのままにしていたから、結局pでみられてなかったっていうね(恥)

 

さて、ちゃんとpに置き換えてみてみたところ、無駄な空白がnilだと判明。

でも…このnilは一体何に対してでてるんだ?

 

だってリンゴとミカンの要素は出てるんだよ?

ってことはlist配列の中はさらえてるってことじゃん。

 

一応fruit : falseの時に no って出力するように追加してみたら…

ーーーーーーーーーーーーーーーーーーー

{:name=>"リンゴ", :fruit=>true}
no
{:name=>"ミカン", :fruit=>true}
no
nil

ーーーーーーーーーーーーーーーーーーー

って出力。

やっぱりlist配列はちゃんとさらえてる。

 

じゃあこのnilは一体何に対してでてるんだ??

そういえば、さっきeachにした時、リンゴとミカンが出た後でリストの中身全部でてたな…。

f:id:MmRevorution:20180923111801p:plain

 

ってことは、最後にメソッドを呼び出した時にlistの中身をまるまるだしちゃってて、find_fruitsが仕事してないってことだな?そうだな?

 

…えぇ?なんでー??

 

メンターさんからのヒント2 「このfind_fruitsは何を返すんだい?」

 

何って、fruit : trueの要素だよね?え?ちがうの?

いやそうだよね。

 

だって実行結果例にリンゴとミカンの要素だけがでてたもんね。

その2つの共通点ってfruit : trueってことだもんね。

 

えぇ…つまり、そこはあってるけれど…?

 

という思考回路で、ヒント1ヒント2をひたすら考えていたら21時から23時半まで潰しました(笑)

 

教科書読んでもネットで調べてもだんだん頭に入らなくなってきて、ついに23時半一旦区切って寝ました(笑)

 

メンターさんからのヒント3 「このメソッドの仕事」

今朝、もう一度メンターさんへこれまでの試行錯誤と考え方をお伝えしてどうしても解決しないと泣きつくと…。

 

「このメソッドの仕事は、fruit : trueを返すということだけ。大事なのはそれ以外の仕事をさせないということ。あと明示的にreturnを書いて値を返すことができるからそれを使ってごらん」と。

 

え!retrunでよかったの!?

でもリンゴで終わっちゃうのになあ…。

 

でも確かに前回の授業でメソッドには決まった仕事のみさせて責務をはっきりさせてあげることが大事って言われてたな…。

 

えっと、retrunはそこで試合終了だから、

試合終了になってもいいようにすればいいのか。

 

ってことは…!?

 

そして…

こうなりました

f:id:MmRevorution:20180923113617p:plain

 

試しにlist配列の中にたまごだとかfalseになる要素増やしたりして試したけど、ちゃんとリンゴとミカンだけの要素がでました!

 

ちなみに、繰り返し処理がいつのまにかeachになってますが、メンターさんからちゃんとwhileの時のかっこいい書き方「i  < 配列名.size」ってのを教わりました!

 

なのになぜeach(笑)

 

そしてメンターさんにおみせしたところ

「パーフェクト!!」と!

 

 

「returnは処理が終わる」という側面にだけとらわれて時間を無駄にした例でした(笑)

 

メソッド定義の中で新たな配列を作るなんていう発想も自体なかったよー!

なるほどー!

いやー超楽しかった!(笑)

 

プログラミング楽しいから、やるかどうか悩んでるんならやってみて欲しいなー!

本当めっちゃ楽しいから!

 

確かに合う合わないはあるけども、それもやってみなきゃわからないからね!