Ruby 中的块和产量 [英] Blocks and yields in Ruby

查看:31
本文介绍了Ruby 中的块和产量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试了解块和 yield 以及它们在 Ruby 中的工作原理.

I am trying to understand blocks and yield and how they work in Ruby.

如何使用yield?我看过的许多 Rails 应用程序都以一种奇怪的方式使用 yield.

How is yield used? Many of the Rails applications I've looked at use yield in a weird way.

有人可以向我解释或告诉我去哪里理解他们吗?

Can someone explain to me or show me where to go to understand them?

推荐答案

是的,一开始有点不解.

Yes, it is a bit puzzling at first.

在 Ruby 中,方法可以接收代码块以执行任意代码段.

In Ruby, methods can receive a code block in order to perform arbitrary segments of code.

当一个方法需要一个块时,您可以通过调用 yield 函数来调用它.

When a method expects a block, you can invoke it by calling the yield function.

示例:

Person 为例,一个具有 name 属性和一个 do_with_name 方法的类.当该方法被调用时,它会将 name 属性传递给块.

Take Person, a class with a name attribute and a do_with_name method. When the method is invoked it will pass the name attribute to the block.

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

现在您可以调用此方法并传递任意代码块.

Now you can invoke this method and pass an arbitrary code block.

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 的值作为参数传递.

Notice the block receives as a parameter a variable called value. When the code invokes yield it passes as argument the value of @name.

yield( @name )

可以用不同的块调用相同的方法.

The same method can be invoked with a different block.

例如反转名称:

reversed_name = ""

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

puts reversed_name

=> "racsO"

其他更有趣的现实生活示例:

Other more interesting real life examples:

过滤数组中的元素:

 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"]

如果块是可选的,您可以使用:

If the block is optional you can use:

yield(value) if block_given?

如果不是可选的,就调用它.

If is not optional, just invoke it.

您可以在您的计算机上使用 irb (交互式 Ruby Shell)

You can try these examples on your computer with irb (Interactive Ruby Shell)

以下是复制/粘贴就绪形式的所有示例:

Here are all the examples in a copy/paste ready form:

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

这篇关于Ruby 中的块和产量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆