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

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

ただいまの
回答率

90.33%

  • Ruby

    8195questions

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

  • Ruby on Rails

    7675questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 343

dongw

score 110

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

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

def with_current_time(&x)
  x.call(Time.now)
end


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/06 14:33

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

    キャンセル

  • 2017/10/06 21:35

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

    キャンセル

  • 2017/10/07 03:05

    yield Time.nowは
    yieldに引数としてTime.nowが与えらている状態と考えyield(Time.now)となっている。
    それを簡略化してyield Time.nowという記述になっていると考え書きましたが間違っていますか?

    確かに
    > メソッド内のyield(Time.now)でyieldを呼び出し。ここでのyield は now.year
    という文は何か理解しづらい文になっていました。
    「yield」が渡されたブロックを実行するもの、ということであればブロックの部分のnow.yearがyieldで実行されるということで大丈夫でしょうか?

    キャンセル

  • 2017/10/07 09:07

    > yieldに引数としてTime.nowが与えらている状態と考えyield(Time.now)となっている。

    yieldはメソッドじゃ無いので、引数とか言いません。また、括弧も関係ないです。
    if a
    に対して、「if に引数としてaが与えられている」という表現がおかしいのと同じおかしさを感じます。

    > 「yield」が渡されたブロックを実行するもの、ということであればブロックの部分のnow.yearがyieldで実行されるということで大丈夫でしょうか?

    そうですね。do |now| now.year end というブロックをyieldします。
    yieldの意味は辞書を引きましたか?

    キャンセル

  • 2017/10/10 12:17

    返信遅れました。
    yieldの意味を調べました。
    取って代わる、譲る、生み出す、とありました。そのまま考えるとyieldにブロックを譲るとかそんな感じでしょうか?

    > yieldはメソッドじゃ無いので、引数とか言いません。また、括弧も関係ないです。
    ここは自分の認識違いのようですね・・・
    maisumakunさんの回答で
    > yield 引数とすると、ブロックに対して引数が渡されます。そして、それを受けとるのが、ブロック側での|引数|です。
    とありますが、これも誤りということでしょうか?

    実行結果としては yield Time.now の一行が呼び出された時に、
    | now | now.year endというブロックが
    | Time.now | Time.now..year end
    と、実際はnowという引数がTime.nowに置き換わって実行される、という結果でしっくり来る気がしますが、こういうことでしょうか?

    キャンセル

  • 2017/10/10 15:06

    > | Time.now | Time.now..year end

    now = Time.now
    now.year
    の方が近いです。

    キャンセル

  • 2017/10/12 17:00

    返信ありがとうございます。
    ここでのnowは仮引数ででしたので説明頂いた方が近いですね。

    だいぶ理解してきました。ありがとうございます。
    yieldの引数の件について引っかかっているのですが、どういう見解でしょうか?

    キャンセル

  • 2017/10/14 08:30

    > yieldはメソッドじゃ無いので、引数とか言いません。また、括弧も関係ないです。
    のことでしょうか?

    これは、
    > yieldに引数としてTime.nowが与えらている状態と考えyield(Time.now)となっている。
    で、括弧の有無が意味があるかのような記述に対してです。「括弧を付ければ引数という」という風に思ってらっしゃるのかと思いました。

    yieldの値は、そのままブロック引数に渡されるので、yieldの値を引数とは言わないというのはちょっと言い過ぎだったように思います。

    キャンセル

  • 2017/10/17 12:20

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

    キャンセル

0

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/06 14:33

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

    キャンセル

同じタグがついた質問を見る

  • Ruby

    8195questions

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

  • Ruby on Rails

    7675questions

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