2009-10-11 81 views
1

我正在寫一個庫來人性化Ruby中的字節(例如,將字節數1025轉換爲字符串1.1K),並且我被卡在設計的一個元素上。如何驗證傳遞給Ruby中某個方法的函數?

該計劃將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]的價值,但我無法弄清楚如何驗證它要麼ceilfloor。因爲我不能在此獲得一個句柄,我已經結束了做以下,這感覺很笨拙:

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拉姆達包含方法偷看了一招,我會喜歡聽它。 (我也很高興聽到任何其他設計建議。)謝謝。

回答

7

沒有理由讓用戶傳遞,如果你打算是嚴厲的關於他們所允許通過的方法(你知道有是other rounding schemes除了天花板和地板,對吧?)

如果你想限制用戶天花板和地板,只是讓他們通過在符號:ceiling:floor一種更靈活的設計是允許的方法取接收單個參數的塊,要舍入的數字。然後用戶可以使用他們喜歡的任何舍入算法,包括自定義算法。

順便說一下,Numeric#humanize屬於這種monkeypatches的類別,這樣一個流行的名稱,你很可能會遇到命名空間碰撞(併產生微妙的錯誤)在除了一個小的個人項目之外的任何東西。

+0

這很有趣:你看到(可能是正確的),因爲我是'嚴酷',實際上是我想要小心。我想阻止用戶(說),傳遞一些毫無意義或有害的方法的其餘部分。我喜歡接受一個街區的想法。我會玩這個和符號,看看對我有意義。至於名字,如果你有更好的主意,我願意接受建議。我認爲'人性化'(它很明顯)的好處也是一個缺點。 – Telemachus 2009-10-11 23:07:49

+0

一般而言,我不主張向Ruby內置類添加方法。有很多選擇,例如在一個可包含的模塊('humanize_number(42.3)')中創建一個實用方法,或者創建一個使用委託的包裝類('n = HumaneNumber.new(42.3); n.to_s' )。 – Avdi 2009-10-11 23:43:54

+0

我非常喜歡Ruby的初學者,但我認爲這是語言的強項之一,它的內置類對這類事物開放。 (介紹性書籍肯定會用它來宣傳它。)我並不是非常不贊同,實用方法也很好 - 實際上這是我的第一個想法。我決定擴展'Numeric'對於Ruby更具慣用。再次感謝您的反饋。 – Telemachus 2009-10-12 00:04:36

2

爲什麼要傳遞函數指針而不是布爾值?這樣你就避免了必須驗證函數的問題。

+0

我沒有想到它,但如果我將它放在兩個選項上,這是一個好主意。 – Telemachus 2009-10-11 22:56:02

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 
+0

我一直試圖使用符號和失敗。 'send'方法是我錯過的。謝謝。 (爲了記錄,我打電話給拉姆達 - 稍後在經過私人工作人員方法驗證後。) – Telemachus 2009-10-11 23:04:45

相關問題