我正在编写一个库来对Ruby中的字节进行人性化处理(例如,将字节数1025转换为字符串1.1K),而且我仍然停留在设计的一个元素上。
计划是使用Numeric
方法扩展humanize
,该方法在数字上调用时返回人性化的字符串。在查看Number::Bytes::Human(我喜欢的Perl模块)的源代码后,我决定为该方法添加两个选项:一个使用1000个字节块,另一个使用floor
默认舍入函数比ceil
。
为了最大限度地灵活,方法的定义使用参数的哈希,以便用户可以更改其中一个或两个选项。如果未传递任何参数,则使用默认哈希。这给了我这样的东西:
def humanize(params = {})
params = {:block => 1024, :r_func => lambda }.merge params
# yada yada
end
理想情况下,我想让用户将函数作为params[:r_func]
的值传递,但我无法弄清楚如何验证它是ceil
还是floor
。因为我无法理解这一点,所以我最终做了以下事情,感觉非常笨拙:
def humanize(params = {})
params = {:block => 1024, :r_func => 'ceil' }.merge params
if params[:r_func].eql? 'ceil'
params[:r_func] = lambda { |x| x.ceil }
elsif params[:r_func].eql? 'floor'
params[:r_func] = lambda { |x| x.floor }
else
raise BadRound, "Rounding method must be 'ceil' or 'floor'."
end
# blah blah blah
end
如果有人知道偷看Ruby lambda包含的方法的技巧,我很乐意听到它。 (我也很高兴听到任何其他设计建议。)谢谢。
答案 0 :(得分:7)
没有理由让用户通过一个方法,如果你将成为他们被允许传递的严厉(你知道除了天花板和地板之外还有other rounding schemes,对吗?)
如果您想将用户限制在天花板和地板上,只需允许它们传递符号:ceiling
或:floor
。更灵活的设计是允许该方法采用一个块接收一个参数,要舍入的数字。然后用户可以使用他们喜欢的任何舍入算法,包括自定义算法。
顺便说一下,Numeric#humanize
属于那种具有如此流行名称的monkeypatches类别,除了一个小的个人项目之外,你可能会遇到名称空间冲突(并产生微妙的错误)。
答案 1 :(得分:3)
如果你不打算实际调用这个东西,我没有看到调用者传递lambda的任何意义。把它变成符号,你可以做类似的事情:
raise BadRound, "Rounding method must be :ceil or :floor." unless [:ceil, :floor].include? params[:r_func]
op = lambda {|x| x.send params[:r_func]}
# blah blah blah
答案 2 :(得分:2)
为什么让它们传递函数指针而不是布尔值?这样就可以避免必须验证函数的问题。