简体   繁体   中英

F# Code Execution Order

another noob question regarding F#.

If I have the following code...

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

The output is as follows...

c
a
Example 1
b
Example 2
Example 3

What seems unusual here is the order that the code is executing in. In a previous question Brian mentioned something about expressions, I was hoping someone could explain this a bit more. It almost seems like the compiler is intelligently pre-executing things to calculate values... but I don't know?

ExeA and ExeC aren't functions, but single values. The compiler ensures that values initialise in the order in which they're declared in the source file, so what's happening here is:

  1. ExeC initialises
  2. ExeA initialises
  3. Example 1 is printed, using ExeA 's initialised value
  4. The ExeB function is called as normal
  5. Example 3 is printed, using ExeC 's initialised value

If you want ExeA and ExeC to be truly lazy -- that is, to control when their side effects run -- you could turn them into functions that accept 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 ())

As a follow up to Tim's answer, I thought you might appreciate some further insight into what you've stumbled upon. In your example, ExeC and ExeA take advantage of the functional style of organizing code through lexical scoping and closures. Let me demonstrate a more powerful example.

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

    //...

Here again timesPieDiv4 is not a function, but does have a body which contains a series of sub calculations which are not exposed to the rest of the calc function. In a language like C#, you have two options neither of which appeals to me. The first option is to simply declare pie and pieDiv4 within the main body of calc , but then it's less clear how they are being used and you dirty your variable space. The other option is to factor those sub calculations out into a separate private helper function. But I dislike such functions, because with many it becomes hard to analyze your complex algorithms since you are constantly darting around looking up various implementation pieces. Plus it's a lot of boiler plate code and value passing. That's why F# functions are "public" by default, lexical scoping and closures allow you to hierarchically organize "private" functions and values within your public facing functions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM