Ruby中的块和收益 [英] Blocks and yields in Ruby

查看:74
本文介绍了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 may receive a code block in order to perform arbitrary segments of code.

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

When a method expects a block, it invokes it by calling the yield function.

例如,这非常方便,它可以遍历列表或提供自定义算法.

This is very handy, for instance, to iterate over a list or to provide a custom algorithm.

以下面的示例为例:

我将定义一个用名称初始化的Person类,并提供一个do_with_name方法,该方法在被调用时将把name属性传递给接收到的块.

I'm going to define a Person class initialized with a name, and provide a do_with_name method that when invoked, would just pass the name attribute, to the block received.

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

    def do_with_name 
        yield( @name ) 
    end
end

这将允许我们调用该方法并传递任意代码块.

This would allow us to call that method and pass an arbitrary code block.

例如,要打印名称,我们将要做:

For instance, to print the name we would do:

person = Person.new("Oscar")

#invoking the method passing a block
person.do_with_name do |name|
    puts "Hey, his name is #{name}"
end

会打印:

Hey, his name is Oscar

注意,该块接收一个名为name的变量作为参数(注意,您可以随心所欲地将此变量命名为name).当代码调用yield时,它将用@name的值填充此参数.

Notice, the block receives, as a parameter, a variable called name (N.B. you can call this variable anything you like, but it makes sense to call it name). When the code invokes yield it fills this parameter with the value of @name.

yield( @name )

我们可以提供另一个块来执行不同的操作.例如,将名称取反:

We could provide another block to perform a different action. For example, reverse the name:

#variable to hold the name reversed
reversed_name = ""

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

puts reversed_name

=> "racsO"

我们使用了完全相同的方法(do_with_name)-它只是一个不同的块.

We used exactly the same method (do_with_name) - it is just a different block.

这个例子很简单.更有趣的用法是过滤数组中的所有元素:

This example is trivial. More interesting usages are to filter all the elements in an array:

 days = ["monday", "tuesday", "wednesday", "thursday", "friday"]  

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

=> ["tuesday", "thursday"]

或者,我们也可以提供一种自定义排序算法,例如基于字符串大小的

Or, we can also provide a custom sort algorithm, for instance based on the string size:

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

=> ["monday", "friday", "tuesday", "thursday", "wednesday"]

我希望这可以帮助您更好地理解它.

I hope this helps you to understand it better.

顺便说一句,如果该块是可选的,则应这样称呼它:

BTW, if the block is optional you should call it like:

yield(value) if block_given?

如果不是可选的,则只需调用它即可.

If is not optional, just invoke it.

编辑

@hmak为这些示例创建了一个repl.it: https://repl.it/@makstaks/blocksandyieldsrubyexample

@hmak created a repl.it for these examples: https://repl.it/@makstaks/blocksandyieldsrubyexample

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

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