我想比较一个 case 语句的多个变量,目前正在考虑为 Array 覆盖 case 等于运算符 (===) 是最好的方法。这是最好的方法吗?
这是一个示例用例:
def deposit_apr deposit,apr
# deposit: can be nil or 2 length Array of [nil or Float, String]
# apr: can be nil or Float
case [deposit,apr]
when [[Float,String],Float]
puts "#{deposit[0]} #{deposit[1]}, #{apr*100.0}% APR"
when [[nil,String],Float]
puts "#{apr*100.0}% APR on deposits greater than 100 #{deposit[1]}"
when [[Float,String],nil]
puts "#{deposit[0]} #{deposit[1]}"
else
puts 'N/A'
end
end
唯一的问题是 Array case equals operator 不对 Array 的元素应用 case equal。
ruby-1.9.2-p0 > deposit_apr([656.00,'rupees'],0.065)
N/A
如果我覆盖它会,但我不确定如果我这样做会破坏什么:
class Array
def ===(other)
result = true
self.zip(other) {|bp,ap| result &&= bp === ap}
result
end
end
现在,一切正常:
ruby-1.9.2-p0 > deposit_apr([656.00,'rupees'],0.065)
656.0 rupees, 6.5% APR
我错过了什么吗?
最佳答案
我发现这个问题是因为我想运行一个 case
关于多个变量的陈述,但是通过以下内容得出的结论是,需要比较多个变量可能表明需要采用不同的方法。 (我带着这个结论回到我自己的代码,发现即使是一个 Hash 也在帮助我写出更容易理解的代码。)
今天使用的 gem "no monkey patching" as a selling point .覆盖运算符可能不是正确的方法。 Monkey 补丁非常适合实验,但也很容易出错。
此外,还有很多类型检查。在为 Duck Typing 设计的语言中,这清楚地表明需要一种不同的方法。例如,如果我传入整数值而不是 float ,会发生什么情况?我们会得到一个“N/A”,即使这不太可能是我们正在寻找的。p>
您会注意到问题中给出的示例难以阅读。我们应该能够找到一种方法向读者(以及作者,当他们在几个月后再次访问代码并且不得不弄清楚到底发生了什么时)更清楚地表示这种逻辑。
最后,由于有多个数字具有关联逻辑,因此似乎至少有一个 value object。 - 要写入的类 ( Deposit
)。
为了清洁起见,我假设一个 nil
APR 可视为 0.0% APR。
class Deposit
def initialize(amount, unit='USD', options={})
@amount = amount.to_f # `nil` => 0.0
@unit = unit.to_s # Example assumes unit is always present
@apr = options.fetch(:apr, 0.0).to_f # `apr: nil` => 0.0
end
end
一旦我们有了 Deposit 对象,我们就可以实现打印逻辑而不需要 case
完全没有陈述。
class Deposit
# ... lines omitted
def to_s
string = "#{@amount} #{@unit}"
string << ", #{@apr * 100.0}% APR" if @apr > 0.0
string
end
end
d = Deposit.new(656.00, 'rupees', apr: 0.065)
d.to_s
# => "656.0 rupees, 6.5% APR"
e = Deposit.new(100, 'USD', apr: nil)
e.to_s
# => "100.0 USD"
f = Deposit.new(100, 'USD')
f.to_s
# => "100.0 USD"
结论:如果您在案例陈述中比较多个变量,请将其用作气味来暗示更深层次的设计问题。多变量 case
s 可能表示有一个对象要创建。
关于使用数组的具有多个变量的 Ruby case 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4838808/