2009-05-18 104 views
6

我剛剛發現了一些我在F#中稱爲怪癖的東西,並且想知道它是通過設計還是錯誤,以及它是否是通過設計,爲什麼如此。 .. 如果您編寫任何範圍表達式,其中第一項大於第二項,則返回的序列爲空。看反射鏡表明這是設計,但我無法真正找到它必須如此的理由。 一個例子重現它是:範圍A到B,其中A> B在F#


[1..10] |> List.length 
[10..1] |> List.length 

第一個將打印出10,而第二打印出0 試驗是在F#CTP 1.9.6.2製成。

編輯:謝謝你建議說明範圍,但仍然有一個案例(這是什麼啓發我問這個問題),這將不會被覆蓋。如果A和B是變量,而且沒有一個比其他變量總是大,但是它們總是不同的呢? 考慮到範圍表達式似乎在編譯時無論如何都得到了優化,那麼在A和B是否允許負步驟的情況下,確定步驟(未明確指定)的代碼是否有很好的理由?

+1

與一些可能感興趣的代碼稍有關聯的問題http://stackoverflow.com/questions/377078/f-floating-point-ranges-are-experimental-and-may-be-deprecated – Benjol 2009-05-19 07:37:10

回答

10

正如其他的答案建議,你可以做

[10 .. -1 .. 1] |> List.iter (printfn "%A") 

例如

[start .. step .. stop] 
+0

感謝您的支持,但您能否看到/評論/回答我的編輯?在此先感謝 – em70 2009-05-18 17:54:37

1

範圍一般表示(以支持他們的語言和框架)是這樣的:

low_value <to> high_value

你可以給一個很好的理由,爲什麼一個範圍應該是能夠表達不同?由於您要求的範圍是從較高的數字到較低的數字,因此得出的範圍不會有成員嗎?

+0

其中A和B是可變的,在我看來,這是一個足夠好的情況... – em70 2009-05-18 17:49:22

2

在haskell中,您可以編寫[10, 9 .. 1]。也許它在F#中的作用是一樣的(我還沒有嘗試過)?

編輯:

看來,F#的語法是不同的,可能像[10..-1..1]

3

什麼 「應該」 發生的,當然,主觀的。我腦海中的正常範圍表示法將[x..y]定義爲所有大於或等於x且小於或等於y的元素的集合;一個空集如果y < x。在這種情況下,我們需要呼籲F#規範。

範圍表達式expr1 .. expr2被計算爲對重載操作符(..)的調用,其默認綁定在Microsoft.FSharp.Core.Operators中定義。這將爲給定start(expr1)和finish(expr2)值之間的值範圍生成一個IEnumerable < _>,使用1的增量。操作符需要存在靜態成員(..)(長名稱GetRange)在具有適當簽名的靜態類型的expr1上。

範圍表達式expr1 .. expr2 .. expr3被評估爲對重載操作符(.. ..)的調用,其默認綁定在Microsoft.FSharp.Core.Operators中定義。這將使用expr2的增量爲給定start(expr1)和finish(expr3)值之間的值範圍生成IEnumerable < _>。該運算符需要在靜態類型expr1上存在一個靜態成員(..)(長名稱GetRange)並帶有適當的簽名。

該標準似乎沒有定義..運營商(至少,我可以找到)。但是你應該能夠改變你感興趣的類型的綁定,以任何你喜歡的方式行事(包括如果x> y倒計數)。

3

亞當賴特 - 但是,你應該能夠 更改類型綁定你 有意以任何方式你喜歡 的行爲(包括倒計時,如果x> Y)。

以亞當的建議爲代碼:

let (..) a b = 
    if a < b then seq { a .. b } 
      else seq { a .. -1 .. b } 

printfn "%A" (seq { 1 .. 10 }) 
printfn "%A" (seq { 10 .. 1 }) 

這適用於INT範圍。查看(..)的源代碼:您可以使用它來處理其他類型的範圍,但不知道如何爲特定類型獲取-1的正確值。

相關問題