内容 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11

官方 Ruby 常见问题解答

如果您希望报告此常见问题解答中的错误或提出改进建议,请访问我们的 GitHub 仓库 并开启一个 issue 或 pull request。

其他特性

a ? b : c 是什么意思?

这是一个所谓的“三元运算符”,与 if a then b else c end 的含义相同。

如何计算文件中的行数?

以下代码可能会给出最快的结果。

File.readlines("example").size  # => 3

MatchData#beginMatchData#end 返回什么?

它们与 $~ 一起工作,并返回原始字符串中匹配数据的起始索引和结束索引。请参阅 制表符扩展 中的示例。

如何对数组中的元素求和?

本节或其部分内容可能已过时或需要确认。

与其解决特定的问题,不如解决一般情况。我们要做的第一件事是生成一个方法,该方法将迭代一个 Enumerable 对象并收集单个结果。Smalltalk 将该方法称为 inject,所以我们也这样称呼它

module Enumerable

  # inject(n) {|n, i| ...}
  def inject(n)
    each {|i| n = yield(n, i) }

    n
  end
end

请注意,我们是如何将该方法添加到 Enumerable 中的。这意味着任何包含 Enumerable 的东西现在都可以使用 inject。但是我们如何使用它呢?它接受一个参数 n 和一个块。对于被枚举的内容中的每个元素,它都会调用该块,传入 n 和元素本身。块的结果被赋值回 n。因此,要定义 sum,我们可以这样写

module Enumerable
  def sum
    inject(0) {|n, i| n + i }
  end
end

[1,3,5,7,9].sum  # => 25
(1..100).sum     # => 5050

如何使用延续?

本节或其部分内容可能已过时或需要确认。

Ruby 的延续允许您创建一个表示 Ruby 程序中某个位置的对象,然后随时返回到该位置(即使它显然已超出范围)。延续可用于实现复杂的控制结构,但通常更适合用来迷惑人们。

[ruby-talk:4482] 中,Jim Weirich 发布了以下延续示例

# --------------------------------------------------------------------
# Simple Producer/Consumer
# --------------------------------------------------------------------
# Connect a simple counting task and a printing task together using
# continuations.
#
# Usage:  count(limit)

def count_task(count, consumer)
  (1..count).each do |i|
    callcc {|cc| consumer.call cc, i }
  end
  nil
end

def print_task()
  producer, i = callcc { |cc| return cc }
  print "#{i} "
  callcc { |cc| producer.call }
end

def count(limit)
  count_task(limit, print_task())
  print "\n"
end
# --------------------------------------------------------------------
# Filtering Out Multiples of a Given Number
# --------------------------------------------------------------------
# Create a filter that is both a consumer and producer. Insert it
# between the counting task and the printing task.
#
# Usage:  omit(2, limit)

def filter_task(factor, consumer)
  producer, i = callcc { |cc| return cc }
  if (i%factor) != 0 then
    callcc { |cc| consumer.call cc, i }
  end
  producer.call
end

def omit(factor, limit)
  printer = print_task()
  filter = filter_task(factor, printer)
  count_task(limit, filter)
  print "\n"
end
# --------------------------------------------------------------------
# Prime Number Generator
# --------------------------------------------------------------------
# Create a prime number generator. When a new prime number is
# discovered, dynamically add a new multiple filter to the chain of
# producers and consumers.
#
# Usage:  primes(limit)

def prime_task(consumer)
  producer, i = callcc { |cc| return cc }
  if i >= 2 then
    callcc { |cc| consumer.call cc, i }
    consumer = filter_task(i, consumer)
  end
  producer.call
end

def primes(limit)
  printer = print_task()
  primes = prime_task(printer)
  count_task(limit, primes)
  print "\n"
end