2010-07-03 15 views
8

kolejne pytanie typu noob dotyczące F #.F # Zamówienie wykonania kodu

Jeśli mam następujący kod ...

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 

Wyjście jest następujący ...

c 
a 
Example 1 
b 
Example 2 
Example 3 

Co wydaje się niezwykły tu jest porządek, że kod jest wykonywany w. W poprzednie pytanie, które Brian wspominał o wyrażeniach, miałem nadzieję, że ktoś mógłby wyjaśnić to nieco więcej. Wygląda na to, że kompilator inteligentnie wykonuje zadania, aby obliczyć wartości ... ale nie wiem?

Odpowiedz

13

ExeA i ExeC nie są funkcjami, ale pojedynczymi wartościami. Kompilator gwarantuje, że wartości inicjalizacji w kolejności, w jakiej są one zadeklarowane w pliku źródłowym, więc to, co się tutaj dzieje jest:

  1. ExeC Zainicjowanie
  2. ExeA inicjalizuje
  3. Example 1 jest drukowany przy użyciu ExeA „s inicjalizowany wartością
  4. funkcja ExeB nazywa się normalnym
  5. Example 3 jest drukowany za pomocą ExeC „s zainicjowane wartości

Jeśli chcesz ExeA i ExeC być naprawdę leniwy - to znaczy, aby kontrolować, kiedy uruchomić ich skutki uboczne - można włączyć je do funkcji, które akceptują 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()) 
3

W następstwie aż do odpowiedzi Tima, myślałem, że możesz docenić głębszy wgląd w to, na co natknąłeś się. W twoim przykładzie ExeC i ExeA wykorzystują funkcjonalny styl organizowania kodu poprzez leksykalne zakresy i zamknięcia. Pozwól mi zademonstrować mocniejszy przykład.

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

    //... 

Tu znowu timesPieDiv4 nie jest funkcją, ale ma korpus, który zawiera szereg obliczeń cząstkowych, które nie są narażone na resztę funkcji calc. W języku takim jak C# masz dwie opcje, z których żadna nie przemawia do mnie. Pierwszą opcją jest po prostu zadeklarowanie pie i pieDiv4 w obrębie głównej treści calc, ale wtedy jest mniej jasne, w jaki sposób są one używane i brudne zmienne miejsce. Inną opcją jest uwzględnienie tych podliczeń w oddzielnej prywatnej funkcji pomocniczej. Ale nie lubię takich funkcji, ponieważ z wieloma trudniej jest analizować złożone algorytmy, ponieważ ciągle przeglądasz różne elementy implementacji. Plus to dużo kodu płyty kotła i wartości przechodzących. Właśnie dlatego funkcje F # są domyślnie "publiczne", zakresy leksykalne i zamknięcia pozwalają hierarchicznie organizować "prywatne" funkcje i wartości w publicznych funkcjach.

+0

Dziękuję Stephenowi - doceń dalsze opracowanie! –