Ruby中的那些管道符号是什么?


72

Ruby中的管道符号是什么?

我正在学习Ruby和RoR,它们来自PHP和Java背景,但是我不断遇到这样的代码:

def new 
  @post = Post.new

  respond_to do |format|
    format.html # new.html.erb
    format.xml { render :xml => @post }
  end
end

|format|做什么?这些管道符号在PHP / Java中的等效语法是什么?

Answers:


54

它们是产生给块的变量。

def this_method_takes_a_block
  yield(5)
end

this_method_takes_a_block do |num|
  puts num
end

输出“ 5”。一个更神秘的例子:

def this_silly_method_too(num)
  yield(num + 5)
end

this_silly_method_too(3) do |wtf|
  puts wtf + 1
end

输出为“ 9”。


哪里wtf当去|wtf|块结束?
ThorSummoner

它的作用域是该块,因此在它之外不可用。换句话说:它消失了。
八月Lilleaas 2015

1
如果可变吗?必须如此,否则我不知道Vagrantfile如何将它们用作配置方法。
ThorSummoner

不知道我是否理解你的问题。它只是对对象的命名引用。
2015

可变意味着您可以持久地更改命名引用,而不是不能更改的不可变,例如,如果您要保留更改,则必须重新分配变量值。
ThorSummoner 2015年

34

一开始这对我来说也很奇怪,但是我希望这个解释/ walkthru能对您有所帮助。

该文档以一种很好的方式触及了这个主题-如果我的回答没有帮助,我相信他们的指南会有用。

首先,通过键入irbshell并点击来启动Interactive Ruby解释器Enter

输入类似:

the_numbers = ['ett','tva','tre','fyra','fem'] # congratulations! You now know how to count to five in Swedish.

只是为了让我们有一个数组可以玩。然后我们创建循环:

the_numbers.each do |linustorvalds|
    puts linustorvalds
end

它将输出所有数字,并用换行符分隔。

在其他语言中,您必须编写如下内容:

for (i = 0; i < the_numbers.length; i++) {
    linustorvalds = the_numbers[i]
    print linustorvalds;
}

要注意的重要事项是,|thing_inside_the_pipes|只要您一直使用它,它就可以是任何东西。并且了解到我们正在谈论的是循环,直到后来我才意识到这一点。


7
在某些“其他语言”(Python)中,您编写了for linustorvalds in the_numbers do print linustorvalds。也许更直观。
史蒂夫·贝内特

3
完全正确。之所以选择C风格的语法,是因为我怀疑有更多的人熟悉红宝石,但是我希望他们也阅读您的评论。
马丁·约瑟夫森

谢谢。“其他语言”部分帮助我了解了发生了什么。+1。
rayryeng

7
@names.each do |name|
  puts "Hello #{name}!"
end

http://www.ruby-lang.org/en/documentation/quickstart/4/伴随着这样的解释:

each是接受一个代码块然后运行的代码用于在列表中的每个元素块的方法,和之间的位doend就是这样一个块。块就像一个匿名函数或lambda。管道字符之间的变量是此块的参数。

此处发生的是,对于列表中的每个条目,name都绑定到该列表元素,然后puts "Hello #{name}!"使用该名称运行表达式。


6

do到的代码end定义了一个Ruby块。该字format是该块的参数。该块与方法调用一起传递,被调用的方法可以yield向该块赋值。

有关详细信息,请参见Ruby上的任何文本,这是Ruby的核心功能,您将一直看到它。


1
不,do和end之间的代码是红宝石块。竖线之间的术语是该块的参数。
抢劫

IIRC,管道语法是从Smalltalk借用的。
约翰·托普利

是的,除了Smalltalk仅使用了一个管道。
Chuck

3

Java中的等效内容将类似于

// Prior definitions

interface RespondToHandler
{
    public void doFormatting(FormatThingummy format);
}

void respondTo(RespondToHandler)
{
    // ...
}

// Equivalent of your quoted code

respondTo(new RespondToHandler(){
    public void doFormatting(FormatThingummy format)
    {
        format.html();
        format.xml();
    }
});

布伦特(Brent),如果您的意思是,那么Java版本冗长冗长-是的,我同意。但是话又说回来,这是Java中不太习惯的构造。Ruby一直使用它,而Java则更少。
乔恩·布莱特

format.html(); format.xml(); 部分可能更像是switch语句,因为您将打开请求的格式。
jonnii

一个更干净的示例是JavaScript中的等效构造:我发现Java缺少真正的functor支持确实很烦人。根本就不难使用它们-除非您通过Java中的匿名类学习它们!
Reid Rankin


1

如果需要,使其更加清晰:

管道棒本质上是一个新变量,用于保存从方法调用之前生成的值。类似于:

方法的原始定义:

def example_method_a(argumentPassedIn)
     yield(argumentPassedIn + 200)
end

使用方法:

example_method_a(100) do |newVariable|
    puts newVariable;
end

几乎与编写此代码相同:

newVariable = example_method_a(100) 
puts newVariable

在这里,newVariable = 200 + 100 = 300:D!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.