我可以在 Ruby 的下一行放一个 if/unless 子句吗?

Can I put an if/unless clause on the next line in Ruby?

在 Perl 中,我经常发现自己使用以下模式:

croak "incompatible object given: $object"
    unless $object->isa('ExampleObject') and $object->can('foo');

我试图将其翻译成 Ruby,如下所示:

raise ArgumentError, "incompatible object given: #{object.inspect}"
    unless object.is_a?(ExampleObject) and object.respond_to?(:foo)

但这不起作用,因为 Ruby 将 unless 解释为新语句的开始。据我了解,我可以在第一行的末尾放一个反斜杠,但那样看起来很难看,而且感觉不对。我也可以使用常规的 unless condition raise error end 结构,但我更喜欢原始形式的样式。 Ruby?

这不是真正的解决方案,我在阅读问题时马虎。 OP 想要一个没有反斜杠的解决方案。

你应该可以做到这一点:

raise ArgumentError, "incompatible object given: #{object.inspect}" \
  unless object.is_a?(ExampleObject) and object.respond_to?(:foo)

\ 个字符告诉 ruby 继续阅读,就好像没有换行符一样。

据我所知,除了 \ 别无他法,否则,如您所说,Ruby 认为这是一个新声明。

请记住,风格指南和约定因语言而异。在 Ruby 中,我不希望在其代码之后的一行中出现 if/unless 语句。事实上,我什至不喜欢把 if/unless 放在一行的末尾,因为它会将读取方向从 If this, then that 反转为 that, if this (then what? Ah, I need to read back again),尤其是当条件比 raise 'foo' if bar.empty? 更复杂时.

在 Perl 和其他语言中,虽然这可能有所不同,因为您有其他约定、风格指南和这个 ;-thingy ;)

Can I put an if/unless clause on the next line in Ruby?

你不能。从通常不相关的 final draft of ISO Ruby 第 107 页(PDF 第 127 页)开始,但像这样的基本内容是相关的,它也使我们不必阅读 parse.y:

unless-modifier-statement ::
    statement [no line-terminator here] unless expression

这很清楚。它与您的 Perl 示例没有比以下更相似的了:

raise ArgumentError, "incompatible object given: #{object.inspect}" unless
  object.is_a?(ExampleObject) and object.respond_to?(:foo)`

或:

raise ArgumentError, "incompatible object given: #{object.inspect}" \
  unless object.is_a?(ExampleObject) and object.respond_to?(:foo)

就像你觉得在末尾加反斜杠强制单行语句是错误的一样,当超出单行时使用单行语句也是错误的。