質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

2回答

2293閲覧

Rubyのyieldの挙動が理解できていません。

dongw

総合スコア119

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2017/10/04 08:51

編集2017/10/05 10:34

Rubyのyieldの挙動が理解できていません。

以下がサンプルコードになります。

def with_current_time yield Time.now end with_current_time do |now| now.year end

このコードを動かすと
2017と表示されます。

with_current_time do |now| now.year end

でメソッドを呼び出し。
yieldでブロックの中を呼び出す。
つまりブロックの中 = now.year を呼び出しているのだと考えました。
しかしyieldでnow.yearを呼び出してもエラーになると思います。
yieldの後にTime.nowが関連しているのでしょうか?
そのまま見たままだと、

yieldでnow.yearを呼び出し。
その後に続くTime.nowを呼び出し。
に受け取れます。
しかし挙動的にはTime.now.yearですよね?
何故でしょうか?

また呼び出す側としても

with_current_time do |now| now.year end

となっており |now|
が付いているのは何故でしょうか?

array.each do |array1| puts array1 end

となって配列の中身が一つづつ格納されている使い方は分かるのですが、
今回の||の使い方は分かりませんでした。合わせて教えて頂けるとありがたいです。

def with_current_time
yield Time.now
end

with_current_time do |now|
now.year
end

お二方回答ありがとうございます。
最初に勘違いしていたのは
yield Time.nowは yield(Time.now)という形だったのですね。

呼び出し順としては

with_current_time do |now| now.year end

で、now.yearをブロックとしてメソッド(with_current_time)に渡す。
メソッド内のyield(Time.now)でyieldを呼び出し。
ここでのyield は now.year
引数で渡ってきたTime.nowは

with_current_time do |now| now.year end

|now|が受け取る。
つまりnowはTime.nowになっている。
繋げてメソッドを読んで
Time.now.year

ということで間違いないでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

yieldというのは、引数として渡されたブロックを呼び出す命令です。

Ruby

1def with_current_time(&x) 2 x.call(Time.now) 3end

と同等なので、こちらで考えた方が理解しやすいかと思います。

投稿2017/10/04 13:41

otn

総合スコア84505

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dongw

2017/10/06 05:33

回答ありがとうございました。 yieldがこちらの記述を省略した形ということですね。 質問に追記をしたのですが、こちらが合っているかどうか確認していただければありがたいです。
otn

2017/10/06 12:35

> yield Time.nowは yield(Time.now)という形だったのですね。 という意味がわからない文もあり、合っているのかどうか分かりません。 少なくとも、 > メソッド内のyield(Time.now)でyieldを呼び出し。ここでのyield は now.year はおかしいです。 yieldという言葉の意味がわからなければ、英和辞書で調べましょう。
dongw

2017/10/06 18:05

yield Time.nowは yieldに引数としてTime.nowが与えらている状態と考えyield(Time.now)となっている。 それを簡略化してyield Time.nowという記述になっていると考え書きましたが間違っていますか? 確かに > メソッド内のyield(Time.now)でyieldを呼び出し。ここでのyield は now.year という文は何か理解しづらい文になっていました。 「yield」が渡されたブロックを実行するもの、ということであればブロックの部分のnow.yearがyieldで実行されるということで大丈夫でしょうか?
otn

2017/10/07 00:07

> yieldに引数としてTime.nowが与えらている状態と考えyield(Time.now)となっている。 yieldはメソッドじゃ無いので、引数とか言いません。また、括弧も関係ないです。 if a に対して、「if に引数としてaが与えられている」という表現がおかしいのと同じおかしさを感じます。 > 「yield」が渡されたブロックを実行するもの、ということであればブロックの部分のnow.yearがyieldで実行されるということで大丈夫でしょうか? そうですね。do |now| now.year end というブロックをyieldします。 yieldの意味は辞書を引きましたか?
dongw

2017/10/10 03:17

返信遅れました。 yieldの意味を調べました。 取って代わる、譲る、生み出す、とありました。そのまま考えるとyieldにブロックを譲るとかそんな感じでしょうか? > yieldはメソッドじゃ無いので、引数とか言いません。また、括弧も関係ないです。 ここは自分の認識違いのようですね・・・ maisumakunさんの回答で > yield 引数とすると、ブロックに対して引数が渡されます。そして、それを受けとるのが、ブロック側での|引数|です。 とありますが、これも誤りということでしょうか? 実行結果としては yield Time.now の一行が呼び出された時に、 | now | now.year endというブロックが | Time.now | Time.now..year end と、実際はnowという引数がTime.nowに置き換わって実行される、という結果でしっくり来る気がしますが、こういうことでしょうか?
otn

2017/10/10 06:06

> | Time.now | Time.now..year end now = Time.now now.year の方が近いです。
dongw

2017/10/12 08:00

返信ありがとうございます。 ここでのnowは仮引数ででしたので説明頂いた方が近いですね。 だいぶ理解してきました。ありがとうございます。 yieldの引数の件について引っかかっているのですが、どういう見解でしょうか?
otn

2017/10/13 23:30

> yieldはメソッドじゃ無いので、引数とか言いません。また、括弧も関係ないです。 のことでしょうか? これは、 > yieldに引数としてTime.nowが与えらている状態と考えyield(Time.now)となっている。 で、括弧の有無が意味があるかのような記述に対してです。「括弧を付ければ引数という」という風に思ってらっしゃるのかと思いました。 yieldの値は、そのままブロック引数に渡されるので、yieldの値を引数とは言わないというのはちょっと言い過ぎだったように思います。
dongw

2017/10/17 03:20

返信ありがとうございます。 確かに括弧の有無で引数があるかないか、と取られてしまう発言をしていました。 こちらは認識を再確認しました。 yieldの値がそのままブロック引数に渡されるということで納得出来ました。 長々とお付き合い頂きありがとうございました。
guest

0

yield 引数とすると、ブロックに対して引数が渡されます。そして、それを受けとるのが、ブロック側での|引数|です。

メソッドを呼ぶときの引数と、メソッド側での引数が関係ないのと同様、ブロックで受け取る|引数|も、ブロックをyieldする側の値とは別な名前で受け取れます。

投稿2017/10/04 09:10

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dongw

2017/10/06 05:33

回答ありがとうございます。 yield(引数)ということは気付きませんでした。 質問に追記だけしましたので、そちらに関して合ってるかどうか返信いただければありがたいです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問