ruby - ruby 中的 spaceship <=> 运算符如何抛出异常?

标签 ruby exception

我有以下代码:

def sort_descending _objects, field
  _objects.sort { |b,a| a.send(field) <=> b.send(field) }
end

a.send(field) 返回一个 Stringb.send(field) 返回一个 Integer,然后抛出一个 ArgumentError。我试图通过以下方式捕获此异常:

def sort_descending _objects, field
  _objects.sort { |b,a| safe_compare(a,b,field) }
end

def safe_compare a, b, field
   a.send(field) <=> b.send(field)
rescue
   a.send(field).to_s <=> b.send(field).to_s
end

但这也会抛出一个ArgumentError。我不知道为什么。谁能解释这种按排序抛出异常的行为?

虽然这个解决方法有效,但它看起来很丑

def sort_ascending _objects, field
  _objects.sort do |a,b|
    safe_compare(a,field,b) <=> safe_compare(b,field,a)
  end
end

def safe_compare a, field, b
  _a,_b = a.send(field), b.send(field)
  _a.class == _b.class ? _a : _a.to_s
end

要重现的代码是 here .

最佳答案

Can anybody explain this?

是的,<=>() 方法不会引发异常。看一看:

def sort_descending _objects, field
  _objects.sort {|b,a| safe_compare(a,b,field) }
end

def safe_compare a, b, field
  a.send(field) <=> b.send(field)
rescue 
  puts 'in rescue clause'   #Let's trace the flow of execution
  a.send(field).to_s <=> b.send(field).to_s
end

class Dog
  def greet
    "hello"
  end
end

class Cat
  def greet
    10
  end
end

d = Dog.new
c = Cat.new

p d.send("greet")
p c.send("greet")

p safe_compare(d, c, "greet")

--output:--
"hello"
10
nil

请注意,rescue 子句中的 puts 语句没有输出。

来自 ruby​​ 字符串文档:

string <=> other_string → -1, 0, +1 or nil

nil is returned if the two values are incomparable.

这一行:

a.send(field) <=> b.send(field)

相当于:

a.send(field).<=>( b.send(field) )

如果 a.send(field) 返回一个字符串,那么一个字符串正在调用 <=>() 方法。 Numeric 类还定义了 <=>() 方法,因此如果 a.send(field) 返回一个数字,那么一个数字正在调用 <=>() 方法。如果两个对象不可比较,则 String#<=> 和 Numeric#<=> 都返回 nil——它们不会抛出异常。其他类对 <=>() 方法有类似的定义。

因此,在您的 safe_compare 方法中不会引发任何 ArgumentError。但是,nil 不是排序 block 的有效返回值,因此 sort() 会引发 ArgumentError。

你需要做这样的事情:

def sort_descending _objects, field
  _objects.sort { |b,a| safe_compare a, b, field }
end

def safe_compare a, b, field
  result = a.send(field) <=> b.send(field)
  result ||= a.send(field).to_s <=> b.send(field).to_s
end

关于ruby - ruby 中的 spaceship <=> 运算符如何抛出异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18346352/

相关文章:

java - Java 中不受支持的 major.minor 52.0 异常

java - 无法将 IMAPInputStream 转换为 Multipart

ruby-on-rails - hash.delete_if { |键,值| true } 不删除...为什么?

ruby-on-rails - 更改设置的 AR Mailer?

ruby - 使 Spring gem 与 SimpleCov 一起工作

ruby - 在 OSX 上的 Chrome 中使用 WATIR 自动上传文件

Java 文件 IO - 文件必须有空行才能被正确读取

c++ - OpenEXR + OpenGL 未处理的异常

java - java中无法捕获异常

ruby - ruby 中的数组和范围有什么区别?