1. ホーム
  2. ルビー

[解決済み】Rubyのブロックとイールド

2022-04-14 06:19:17

質問

ブロックを理解しようとしているのですが yield と、それらがRubyでどのように動作するのかを説明します。

はどのように yield を使用していますか?私が見てきた多くのRailsアプリケーションでは yield を変な意味で使っています。

誰か説明してくれるか、どこをどうすれば理解できるかを教えてください。

どのように解決するのですか?

そうですね、最初はちょっと戸惑いますね。

Rubyでは、メソッドは任意のコードのセグメントを実行するために、コードブロックを受け取ることができます。

メソッドがブロックを期待する場合、そのブロックを呼び出すために yield 関数を使用します。

取る Person を持つクラスは name 属性と do_with_name メソッドを使用します。このメソッドが呼び出されたとき name 属性をブロックに追加します。

class Person 
    def initialize( name ) 
         @name = name
    end

    def do_with_name   # expects a block
        yield( @name ) # invoke the block and pass the `@name` attribute
    end
end

さて、このメソッドを呼び出して、任意のコードブロックを渡すことができます。

person = Person.new("Oscar")

# Invoking the method passing a block to print the value
person.do_with_name do |value|
    puts "Got: #{value}"
end

印刷されるでしょう。

Got: Oscar

このブロックは、パラメータとして value . このコードで yield の値を引数として渡します。 @name .

yield( @name )

同じメソッドを別のブロックで呼び出すことができます。

例えば、名前を反転させるなど。

reversed_name = ""

# Invoke the method passing a different block
person.do_with_name do |value| 
    reversed_name = value.reverse
end

puts reversed_name

=> "racsO"

その他、もっと面白い実例を紹介します。

配列の要素をフィルタリングする。

 days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]  

 # Select those which start with 'T' 
 days.select do | item |
     item.match /^T/
 end

=> ["Tuesday", "Thursday"]

または名前の長さでソートする。

 days.sort do |x,y|
    x.size <=> y.size
 end

=> ["Monday", "Friday", "Tuesday", "Thursday", "Wednesday"]

ブロックがオプションである場合は使用できます。

yield(value) if block_given?

オプションでない場合は、そのまま起動します。

これらの例をコンピュータ上で試すには irb ( 対話型Rubyシェル )

ここに、コピー&ペースト可能なフォームのすべての例があります。

class Person 
    def initialize( name ) 
         @name = name
    end

    def do_with_name   # expects a block
        yield( @name ) # invoke the block and pass the `@name` attribute
    end
end


person = Person.new("Oscar")

# Invoking the method passing a block to print the value
person.do_with_name do |value|
    puts "Got: #{value}"
end


reversed_name = ""

# Invoke the method passing a different block
person.do_with_name do |value| 
    reversed_name = value.reverse
end

puts reversed_name



# Filter elements in an array:    
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]  

# Select those which start with 'T' 
days.select do | item |
    item.match /^T/
end



# Sort by name length:     
days.sort do |x,y|
   x.size <=> y.size
end