2017-04-12 48 views
0

我想打印一个Ruby的功能,只接受正奇数n个红宝石的单行和警告:“没有别的抢救也没用”

def triangle(n, chars) 
    puts "#{n} must be odd and positive" if n % 2 == 0 || n < 0 else (n + 1).times { |i| puts chars * i } 
end 

一个基本的三角纹问题是这样的函数不仅接受奇数,而且接受正数n。 triangle(3, '#')将打印

# 
    ## 
    ### 

但 '三角(4, '#')' 也能正常工作

# 
    ## 
    ### 
    #### 

看来我如果声明不能正常工作,我得到警告else without rescue is useless。为什么以及如何解决这个问题?

+0

如果您需要使用尾部'if'或'unless'子句,请尽量保持简单。例如:'next if(...)'很好,但是更长的值得使用块类型。 – tadman

回答

5

Ruby将您的代码解释为两个单独的语句。

puts "#{n} must be odd and positive" if n % 2 == 0 || n < 0 

else (n + 1).times { |i| puts chars * i } 

elseif没有关联。我猜,Ruby是在绝望中将其解释为begin/rescue/else condition的一部分。为什么它不是一个语法错误,我不知道,但它解释为没有begin块,这在技术上是“成功”的,所以else总是运行。

do this if that这样的条件语句仅用于覆盖简单语句的简单条件。尝试在其他条件下楔入是正确的。相反,使用正常条件。

def triangle(n, chars) 
    if n % 2 == 0 || n < 0 
     puts "#{n} must be odd and positive"  
    else 
     (n + 1).times { |i| puts chars * i } 
    end 
end 

在一般情况下,完全由立即采取错误条件的护理避免else。它避免了在else块中嵌套大部分功能。这对于更长的功能更重要,但这是一个很好的习惯。

def triangle(n, chars) 
    if n % 2 == 0 || n < 0 
     puts "#{n} must be odd and positive" 
     return nil 
    end 

    (n + 1).times { |i| puts chars * i } 
end 

最后,错误应该用异常处理,而不是打印错误消息。打电话者可以捕获和处理例外情况,打印的错误消息很难捕捉并冒泡给用户。如果不加以处理,例外情况会中止该计划;如果用户忘记处理错误,程序将停止,他们会知道修复它。打印的错误消息只是让程序向前推进,可以忽略,导致进一步的问题。

也可以对异常进行分类,以便调用者弄清楚发生了什么样的错误并采取适当的行动。

def triangle(n, chars) 
    if n % 2 == 0 || n < 0 
     raise ArgumentError, "#{n} must be odd and positive" 
    end 

    (n + 1).times { |i| puts chars * i } 
end 
+0

你可以改变这个返回放置等等等等条件,因为放置返回零任何方式 – engineersmnky

+0

@engineersmnky我会毫不犹豫地这样做。我怀疑大多数人知道'puts'返回的是什么(我会假设一个布尔值)。它也将两个不相关的陈述聚集在一起,仅仅是因为人们碰巧返回了所需的价值;我们没有返回'puts'的结果,读者会问为什么。为了清晰起见,应在适当的地方使用垂直空格。 – Schwern

+0

对于每个人而言,我倾向于尽可能使用单一的防守条款,而不是明确的提前回报。似乎更符合风格规范(我的意见)。无论哪种方式,我同意ArgumentError在其他实现,因为它更明确和信息性 – engineersmnky

2

问题似乎是流量控制与输出的逻辑混淆。这将做你想要的,我认为:

def triangle(n, chars) 
    if (n % 2 == 0) || (n < 0) 
    puts "#{n} must be odd and positive" 
    else 
    (n + 1).times { |i| puts chars * i } 
    end 
end 
+1

更何况这是一个更容易阅读。 – Schwern

+0

这是对原始代码的巨大改进。 – tadman

0

作为一个更优雅的实现让我们这一步和处理突发参数

def triangle(n, chars='#') 
    raise(ArgumentError, "{n} must be odd and positive") unless n.to_i.odd? && n.to_i > 0 
    1.upto(n.to_i) { |i| chars.to_s * i} 
end 

现在,这将处理该响应to_i任何n和响应to_s任何chars。例如'13',['x','x',1]仍然是有效的参数,即使它们构成了一个奇怪的三角形。

Ruby以这种方式非常支持鸭子打字,它使您的代码更少的类型特定。