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

时间:2022-06-08 14:03:54

I'll try to be concise this time around! I'm still working Project Euler, this time back to #2. My real issue here is I'm terrible with Ruby. When I run the following code

这次我尽量简明扼要!我还在做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

My interpreter kicks out the following output:

我的翻译输出如下:

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

I'm reading why's (Poignant) Guide to Ruby, and I'm pretty sure I have the pipe syntax correct for the Do. Could someone point out what I'm doing wrong here? I've tried messing around in a lot of different ways and am coming up short handed

我正在阅读《为什么是Ruby》(心酸的)指南,我很确定我的管道语法是正确的。有人能指出我做错了什么吗?我试过用很多不同的方式来胡闹,但我做不到

4 个解决方案

#1


6  

while (x >= 4_000_000)
    foo
end

You don't even have to pass in x, because it's accessible in the scope of the enclosing block.

甚至不需要传入x,因为它在封闭块的范围内是可访问的。

#2


6  

while does not take a block. Remove the do |x| part.

而不是一个街区。删除do |x|部分。

#3


4  

while is not a method that takes a block, it is a ruby looping statement. It considers the part between the while and do (or newline) to be the logical test and the part between the do (or newline) and end keyword to be the loop body.

虽然它不是一个获取块的方法,但它是一个ruby循环语句。它认为while和do(或换行)之间的部分是逻辑测试,而do(或换行)和end关键字之间的部分是循环主体。

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

Contrast this with something like the Array's each method which takes in a block. Here the each method calls your block for each element of the array (passed into the block as x)

将它与数组的每个方法(每个方法接受一个块)进行对比。这里,每个方法为数组的每个元素调用您的块(以x的形式传入块中)

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

You accidentally combined the two, asking the while loop to call your code block with the loop counter to be passed in as x. That is not how while works... hence the parsing exception.

您不小心将两者结合在一起,要求while循环调用您的代码块,并将循环计数器作为x传入。因此,解析例外。

#4


2  

What an interesting question! It inspired me to take a shot at the problem, too. Here's my solution.

一个有趣的问题!这也激发了我对这个问题的思考。这是我的解决方案。

First, some preparatory work:

首先,一些准备工作:

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

Now an Enumerator which generates an infinite sequence of Fibonacci Numbers:

现在,一个枚举器生成一个无限的斐波那契数序列:

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

And the nice thing is that we can now directly express the original problem statement in code:

好在我们现在可以直接用代码表达出原来的问题语句:

Find the sum of all the even-valued terms in the sequence which do not exceed four million.

求序列中不超过400万的偶数项的和。

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

I think that this is a much more Rubyish way to solve the problem. You write in your question that you are terrible with Ruby. But that's not actually the problem. The real problem is that you are good with C! In other words, the real problem is that you simply aren't writing Ruby, you are writing C with Ruby syntax.

我认为这是解决问题的一种更冷酷的方式。你在问题中写到你对Ruby很不好。但这并不是真正的问题。真正的问题是你对C很在行!换句话说,真正的问题是,您根本没有编写Ruby,而是用Ruby语法编写C。

Two good examples are:

两个很好的例子是:

y % 2 == 0

and

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

The Ruby way to write these would be

编写这些代码的Ruby方法是

y.even?

and

x, y = y, x

#1


6  

while (x >= 4_000_000)
    foo
end

You don't even have to pass in x, because it's accessible in the scope of the enclosing block.

甚至不需要传入x,因为它在封闭块的范围内是可访问的。

#2


6  

while does not take a block. Remove the do |x| part.

而不是一个街区。删除do |x|部分。

#3


4  

while is not a method that takes a block, it is a ruby looping statement. It considers the part between the while and do (or newline) to be the logical test and the part between the do (or newline) and end keyword to be the loop body.

虽然它不是一个获取块的方法,但它是一个ruby循环语句。它认为while和do(或换行)之间的部分是逻辑测试,而do(或换行)和end关键字之间的部分是循环主体。

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

Contrast this with something like the Array's each method which takes in a block. Here the each method calls your block for each element of the array (passed into the block as x)

将它与数组的每个方法(每个方法接受一个块)进行对比。这里,每个方法为数组的每个元素调用您的块(以x的形式传入块中)

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

You accidentally combined the two, asking the while loop to call your code block with the loop counter to be passed in as x. That is not how while works... hence the parsing exception.

您不小心将两者结合在一起,要求while循环调用您的代码块,并将循环计数器作为x传入。因此,解析例外。

#4


2  

What an interesting question! It inspired me to take a shot at the problem, too. Here's my solution.

一个有趣的问题!这也激发了我对这个问题的思考。这是我的解决方案。

First, some preparatory work:

首先,一些准备工作:

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

Now an Enumerator which generates an infinite sequence of Fibonacci Numbers:

现在,一个枚举器生成一个无限的斐波那契数序列:

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

And the nice thing is that we can now directly express the original problem statement in code:

好在我们现在可以直接用代码表达出原来的问题语句:

Find the sum of all the even-valued terms in the sequence which do not exceed four million.

求序列中不超过400万的偶数项的和。

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

I think that this is a much more Rubyish way to solve the problem. You write in your question that you are terrible with Ruby. But that's not actually the problem. The real problem is that you are good with C! In other words, the real problem is that you simply aren't writing Ruby, you are writing C with Ruby syntax.

我认为这是解决问题的一种更冷酷的方式。你在问题中写到你对Ruby很不好。但这并不是真正的问题。真正的问题是你对C很在行!换句话说,真正的问题是,您根本没有编写Ruby,而是用Ruby语法编写C。

Two good examples are:

两个很好的例子是:

y % 2 == 0

and

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

The Ruby way to write these would be

编写这些代码的Ruby方法是

y.even?

and

x, y = y, x