簡體   English   中英

F#代碼執行順序

[英]F# Code Execution Order

關於F#的另一個noob問題。

如果我有以下代碼......

let ExeC =
    printfn "c"
    3

let ExeB b = 
    printfn "b"
    2

let ExeA = 
    printfn "a"
    1

printfn "Example %d " ExeA
printfn "Example %d " (ExeB 1)
printfn "Example %d " ExeC

輸出如下......

c
a
Example 1
b
Example 2
Example 3

這里看起來很不尋常的是代碼執行的順序。在上一個問題中,Brian提到了一些關於表達式的問題,我希望有人可以解釋一下這個問題。 幾乎看起來編譯器是智能地預先執行事物來計算值...但我不知道?

ExeAExeC不是函數,而是單個值。 編譯器確保值按照在源文件中聲明的順序初始化,因此這里發生的是:

  1. ExeC初始化
  2. ExeA初始化
  3. 使用ExeA的初始值打印Example 1
  4. ExeB函數被正常調用
  5. 使用ExeC的初始值打印Example 3

如果你想讓ExeAExeC真正變得懶惰 - 也就是說,控制它們的副作用何時運行 - 你可以把它們變成接受unit函數:

let ExeC () =
    printfn "c"
    3

let ExeB b = 
    printfn "b"
    2

let ExeA () = 
    printfn "a"
    1

printfn "Example %d " (ExeA ())
printfn "Example %d " (ExeB 1)
printfn "Example %d " (ExeC ())

作為Tim回答的后續內容,我想你可能會對你偶然發現的事情有所了解。 在您的示例中,ExeC和ExeA利用通過詞法作用域和閉包來組織代碼的功能樣式。 讓我展示一個更有力的例子。

let calc n =
    //...
    let timesPieDiv4 = 
        let pie = 3.14
        let pieDiv4 = pie/4.
        n * pieDiv4

    //...

在這里, timesPieDiv4不是一個函數,但它的主體包含一系列子計算,這些子計算不會暴露給其余的calc函數。 在像C#這樣的語言中,你有兩種選擇,它們都不吸引我。 第一個選項是簡單地在calc主體中聲明piepieDiv4 ,但是它們不太清楚它們是如何被使用的並且你弄臟你的變量空間。 另一種選擇是將這些子計算分解為一個單獨的私有輔助函數。 但是我不喜歡這樣的功能,因為很多人很難分析你的復雜算法,因為你總是在尋找各種實現部分。 此外,它還有很多鍋爐板代碼和價值傳遞。 這就是為什么F#函數默認是“公共”的,詞法作用域和閉包允許您在面向公眾的函數中分層組織“私有”函數和值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM