块做什么?

时间:2014-02-28 11:20:33

标签: ruby

如果有人可以为我开灯,或者在PHP风格的代码中展示一个等效的(如果存在的话),我真的很喜欢它。

这段代码:

require 'sqlite3'
SQLite3::Database.new("metadata.db").execute("SELECT * from BOOKS") do |row|
        puts row
end

使用execute方法发出SQL查询。它正在循环,但在什么?在该查询的返回值?你可以将一个代码块附加到任何表达式,它将在其返回值上工作吗?似乎循环没有连接到任何东西,|row|无处可见。

为了比较,在PHP中访问数据库我会写

$db = new mysqli('details');
$results = $db->query("SELECT * FROM books");
while ($row = $results->fetch()) {
    echo $row[0];
}

表示创建数据库,将查询结果存储为results,然后启动一个循环,其中该结果的每一行都变成一个数组,用数组表示法访问。这不是Rubyists会这样做的吗?这是怎么回事?

3 个答案:

答案 0 :(得分:1)

  

它正在循环,但是在什么?在该查询的返回值上?

右。在您的示例中,row是由

生成的任何内容

SQLite3::Database.new("metadata.db").execute("SELECT * from BOOKS")

在这种情况下row可以合理地调用它,因为您在块中执行的任何操作都将基于db中的那一行,但您可以选择将此“块参数”调用为您想要的任何内容。

  

这是在Ruby中发生的事情,您可以立即将代码块附加到任何表达式,并且它将对其返回值起作用吗?

不是,不。有一些方法采用块参数 - each就是一个很好的例子。

如果您在动物医院收集了一些猫科动物,那么您可以遍历它们并对每只猫进行操作,因为each采用了一个块参数。

#pretend these cats are objects and not just a string name
cats = [ "mrs. muffin face", "princess cupcake", "deathlord 666", ...]

cats.each do |cat|
  #do stuff with each cat here.  print their name, find their shoe size, etc
end

块是一个非常基本的ruby概念,因此可能值得更多地了解它们 - this answer链接到Why's (poignant) guide to ruby这通常是一个很好的基本参考。我还建议Eloquent Ruby获取更完整的Ruby示例。

答案 1 :(得分:0)

您似乎假设某个块是循环结果的东西,但这不一定正确。 Ruby中的一个块与参数相反。在执行main方法之前评估参数,而不预先评估块。是否要评估该块,在要评估的绑定范围,评估的时间以及评估的次数,所有这些都取决于主要方法。 | |中的块变量是主方法传递给块的参数。通常,main方法在没有块的情况下返回的值的元素会一个接一个地传递,这是您想到的情况,但情况并非总是如此。

答案 2 :(得分:0)

以下是如何在Ruby中编写execute

class SQLite3::Database
  def execute(query_str)
    results = db.query(query_str)
    while (row = results.fetch)
      yield row
    end
  end
end

(假设db.queryresults.fetch正如您对PHP所期望的那样工作)。正如您所看到的,除了奇怪的yield之外,这几乎与您习惯使用的PHP相同。当方法遍历结果的行时,yield将每一行传递给块。

这可以让你专注于重要的事情(如何处理每一行),同时隐藏偶然的细节(比如迭代result变量)。