2011-10-19 44 views
4

Scala提供的類Option[T]Some[T] extends Option[T]None extends Option[Nothing]一個層次,我發現有用的包裝Java方法調用,可以返回null,除其他事項外:Clojure的序列作爲斯卡拉選項的替代品[T]

val result = Option(someJavaMethodThatReturnsNull()) 

result的行爲類似於零個或一個項目的序列,具體取決於Java方法是返回對象還是nullOption的方法類似於map,filter等,您可以像序列上的那些一樣使用該方法,並返回新序列(Some),如果原始爲Some[T]None(如果原始爲None)。

看來,Clojure的功能seq行爲類似於:(seq x)將一個項目的序列如果x非空或nil如果x爲空。這個值可以傳遞給(map ...)(filter ...)等,就像Scala的Option方法一樣。

我錯過了什麼嗎?這種模式是否有意義?這是一個「尤里卡!」這對於有經驗的Clojure程序員來說顯而易見。

+1

附註:此集合和選項的共享結構(以及更多)在Haskell中通過[Functor]捕獲(http://hackage.haskell.org/packages/archive/base/latest/doc/ html/Data-Functor.html)和[Foldable](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Foldable.html)類。 – qerub

回答

1

如果集合非空,則seq將返回集合的抽象順序視圖。否則爲nil。所以它與你想要的完全無關。但是,如果測試中可以使用nil。例如。

(when-let [thing (.someMethodThatReturnsSomethingOrNil other-thing)] 
    (run-only-when thing is-not-nil-or-false)) 

這是你的意圖嗎?

編輯:請注意假。

+0

但是,對序列進行操作的大多數Clojure函數都接受'nil':'(map nil)'等。在函數的「行尾」,您可能需要測試nil ,但是在一個鏈中如果調用,你可以傳遞前一個函數返回的內容。 – Ralph

+0

但是'seq'不能幫助你,因爲一個任意的對象是不可搜索的。 'map'和朋友的工作水平不同於'Option'的東西。我發現編寫一個函數'nil'-safe比較容易,然後使用' - >'和'comp'。因人而異。 – kotarak

0

(seq x)將返回nil如果xnil或一個空集合。但是,map,filter等將接受nil作爲其收集參數(即,它們不會中斷)並返回空序列。這可能會產生您期望從Scala的Option聲明中得出的結果。

下面將分別返回一個空序列:

(map (fn [x] x) (seq nil)) 
(map (fn [x] x) (seq `())) 
(filter even? (seq nil)) 
(filter even? (seq `())) 
2

你當然可以使用Clojure的序列代表零,一個或多個返回值。

這是一種明智的方法,如果您的功能實際上預計會返回一個集合,那麼這種方法非常地道。

但是我會不是推薦使用序列來模擬選項類型。這可能會混淆你的API的用戶。在Clojure中,如果一個值不可用,正常的和慣用的方法就是返回nil,如果是的話直接返回值。

比較:

(if-let [a (function-that-returns-nil-or-result)] 
    (do-something-with a)) 

有了,如果你使用的序列來模擬一個選項類型,你將需要:

(if-let [a (function-that-returns-a-possibly-empty-sequence)] 
    (do-something-with (first a))) 

我絕對喜歡的第一個選項....我們爲什麼需要或者希望API用戶使用first從序列中解壓縮結果?

在一般情況下,無工作得很好,Clojure中(比其他語言更好),因爲:

  • 所有的庫函數解釋零作爲空序列,所以你不太可能碰到NullPointerExceptions的。
  • nil也被認爲是「虛假的」,所以可以在布爾操作中方便地使用。