Ruby中的语法错误,Do中的意外管道字符

时间:2010-07-10 04:57:49

标签: ruby

这次我会尽量简明扼要!我还在使用Project Euler,这次回到#2。我真正的问题是我对Ruby很糟糕。当我运行以下代码时

x = 1
y = 2
sum = 2
while x >= 4_000_000 do |x|

  sum += y if y % 2 == 0

  z = x + y

  x = x ^ y   # xor magic
  y = x ^ y   # xor magic
  x = x ^ y   # xor magic

  y = z 
end

p sum

我的翻译推出了以下输出:

/Users/Andy/Documents/Programming/Ruby/ProjectEuler/P2.rb:4: syntax error, unexpected '|'
while x >= 4_000_000 do |x|
                         ^

我正在阅读why's (Poignant) Guide to Ruby,我很确定我的管道语法是正确的。有人能指出我在这里做错了什么吗?我已经尝试过很多不同的方式搞砸了,我很快就出现了。

4 个答案:

答案 0 :(得分:6)

while (x >= 4_000_000)
    foo
end

您甚至不必传递x,因为它可以在封闭块的范围内访问。

答案 1 :(得分:6)

while不会阻止。删除do |x|部分。

答案 2 :(得分:4)

while不是一个接受块的方法,它是一个ruby循环语句。它认为whiledo(或换行符)之间的部分是逻辑测试,而do(或换行符)和end关键字之间的部分是循环体。< / p>

while x < 10 do x += 1; puts x; end
while x < 10
  x += 1
  puts x
end

将此与诸如Array的each方法之类的内容进行对比,该方法包含一个块。这里每个方法为数组的每个元素调用块(作为x传递到块中)

[1,2,3].each do |x|  
  puts x
end

你不小心将两者组合在一起,要求while循环用循环计数器调用你的代码块作为x传入。这不是如何工作...因此解析异常。

答案 3 :(得分:2)

多么有趣的问题!它激发了我对这个问题的关注。这是我的解决方案。

首先,做一些准备工作:

class Enumerator
  def lazy_select
    Enumerator.new do |y|
      each do |el|
        y.yield(el) if yield el
      end
    end
  end

  alias_method :lazy_find_all, :lazy_select
end

module Enumerable
  def sum
    reduce(:+)
  end
end

module Math
  ROOT5 = Math.sqrt(5)
  PHI = 0.5 + ROOT5/2

  def self.fibonacci(n)
    Integer(0.5 + PHI**n/ROOT5)
  end
end

class Integer
  def fibonacci
    Math.fibonacci(self)
  end
end

现在Enumerator生成一个无限的斐波纳契数列:

fibs = Enumerator.new do |y|
  n = -1
  loop do
    y.yield (n += 1).fibonacci
  end
end

好消息是我们现在可以直接在代码中表达原始问题陈述:

  

找出序列中所有偶数值的总和,不超过四百万。

puts fibs.lazy_find_all(&:even?).take_while {|n| n <= 4_000_000 }.sum

我认为这是解决问题的一种更加Ruby的方式。你在问题中写道,你对Ruby很糟糕。但这实际上不是问题所在。 真正的问题是你对C很好!换句话说,真正的问题是你只是不编写Ruby,而是用Ruby语法编写C语言。

两个很好的例子是:

y % 2 == 0

x = x ^ y
y = x ^ y
x = x ^ y

Ruby写这些的方法是

y.even?

x, y = y, x