为什么这段代码会返回未定义的方法' length'对于nil :: NilClass?

时间:2015-08-02 04:12:42

标签: ruby block

我的方法应该接受一个块并用它来比较排序中的两个元素。它的工作方式如下:

bubble_sort_by(["hi","hello","hey"]) do |left,right|
  left.length - right.length
end
# => ["hi", "hey", "hello"]

这是我的方法:

def bubble_sort_by (arr)
  i = 1
  until i == arr.length
    if yield > 0
      x = arr[i]
      arr[i] = arr[i-1]
      arr[i-1] = x
      i -= 1
      p arr #Check State
    else i += 1
      p arr #Check state
    end
  end
  arr
end

我不明白为什么它不起作用。当我在不使用块的情况下比较数组的元素时,它可以工作。我刚刚将基于索引的比较与yield交换,以便为块修改它。我想它超出了数组的范围并返回nil。有人可以告诉我代码中断的地方吗?

2 个答案:

答案 0 :(得分:1)

你得到的是零错误,因为左和右都是零。

原因是因为你正在产生一个带有两个参数的块,但是你没有通过yield语句提供这些参数。

您的假设是基础的,您的错误不是因为超出了数组的范围。虽然如果你避免错误就会发生这种情况。

答案 1 :(得分:1)

您收到undefined method 'length' for nil:NilClass,因为您的函数未将任何参数传递给yield。相反,yield语句正在尝试评估nil参数上的块,从left.length给出错误。

这是我在irb中运行代码时得到的结果:

irb(main):001:0> require './ex.rb'
=> true
irb(main):002:0> bubble_sort_by(["hi","hello","hey"]) do |left,right|
irb(main):003:1*   left.length - right.length
irb(main):004:1> end
NoMethodError: undefined method `length' for nil:NilClass
    from (irb):3:in `block in irb_binding'
    from /Users/amar/Downloads/ex.rb:4:in `bubble_sort_by'
    from (irb):2
    from /Users/amar/.rubies/ruby-2.2.2/bin/irb:11:in `<main>'

我修改了您的if条件以修复yield

if (yield arr[i-1], arr[i]) > 0

我得到了这个输出,我相信这就是你想要的:

irb(main):001:0> require './ex.rb'
=> true
irb(main):002:0> bubble_sort_by(["hi","hello","hey"]) do |left,right|
irb(main):003:1*   left.length - right.length
irb(main):004:1> end
["hi", "hello", "hey"]
["hi", "hey", "hello"]
["hi", "hey", "hello"]
["hi", "hey", "hello"]
=> ["hi", "hey", "hello"]

因此,总而言之,请记住在使用yield时传递您的参数。快乐的编码!