2012-05-13 13 views
6

Uczę się F # i znajduję, że piszę rzeczy, które działają, ale których nie do końca rozumiem. Oto przykładF # wyrażenie lambda z wieloma stwierdzeniami

let processArgs args = 
    match args with 
    | null 
    | [||]   -> [fun() -> getCredentials(); home 20; mentions 20; messages 20] 
    | [|"-h"|] 
    | [|"-?"|]  -> [showHelp] 
    | [|"-reset"|] -> [clearAllSettings] 
    | _    -> [fun() -> printfn "%s" (String.Join(" ", args))] 

[<EntryPoint>] 
    let main (args:string[]) = 
    try 
     let actions = processArgs args 
     List.iter (fun action -> action()) actions 
     0 
    finally 
     Console.ResetColor() 
     Console.CursorVisible <- true 

metod GetCredentials, domu, wspomina, wiadomości, showHelp i clearAllSettings są proste funkcje i robić to, czego oczekują. (Tak, to klient Twittera, nie jest to, że nowe demo 'Hello World'?)

Linia:

[fun() -> getCredentials(); home 20; mentions 20; messages 20] 

działa jak chcę. Wywołuje metodę getCredentials, następnie dom, następnie wspomina, a następnie wiadomości. Z mojej perspektywy średnik działa jak separator instrukcji. Nie widziałem tego wcześniej. Czy to się tutaj dzieje?

Czy istnieje bardziej idiomatyczny sposób pisania tego (innymi słowy, czy doświadczony programista F # rzuciłby się na podłogę śmiejąc się, gdy to zobaczył)?

Dalsze informacje: Moim początkowym zamiarem było posiadanie listy działań, a następnie dodawanie akcji w miarę odkrywania opcji. W języku C# zwykle robię to z Listą < Akcja>(). Średnik zaskoczył mnie, ponieważ początkowo próbowałem napisać jak:

[getCredentials; home 20; mentions 20; messages 20] 

Ale kompilatorowi się to nie podobało.

+1

dobrze, kilka godzin kopania wokół opisie języka ujawnia odpowiedź. Jest to forma składni znana jako pełna składnia. Oto link opisujący to: http://msdn.microsoft.com/en-us/library/dd233199.aspx Nadal zastanawiam się, czy moje podejście do analizowania argumentów wiersza poleceń jest takie, jak robiłby to F # 'ers. –

Odpowiedz

3

Kiedy piszesz:

[fun() -> getCredentials(); home 20; mentions 20; messages 20] 

kompilator tworzy listę tylko jeden element, który jest funkcją typu unit -> unit. S1 ; S2 to skład sekwencji, gdy S1 ma typ unit, a S1 i S2 są wykonywane w kolejności i zwracany jest wynik S2. Zatem, trzy funkcje mają w rzeczywistości podpis int -> unit.

Jeśli chcesz utworzyć listę 4 różnych funkcji, powinno być:

[ getCredentials; // ; is optional 
    fun() -> home 20; 
    fun() -> mentions 20; 
    fun() -> messages 20 ] 

Funkcje te są oddzielone spacją, aby uniknąć nieporozumień korzystania; jako ogranicznik listy i skład sekwencji.

Ponieważ przykład ma wszystkie listy z tylko jednym elementów, to może być w znacznym stopniu uproszczone:

let processArgs = function 
    | [||]   -> getCredentials(); home 20; mentions 20; messages 20 
    | [|"-h"|] 
    | [|"-?"|]  -> showHelp() 
    | [|"-reset"|] -> clearAllSettings() 
    | args   -> printfn "%s" (String.Join(" ", args)) 

[<EntryPoint>] 
let main (args:string[]) = 
    try 
    processArgs args 
    0 
    finally 
    Console.ResetColor() 
    Console.CursorVisible <- true 
+0

Masz rację, proszę pana. Moje idiomy C# stają na przeszkodzie. Dzięki. –

+0

Po prostu drobna korekta, | _ -> ... powinna być | args -> ... – Bernadette

+0

Dzięki @Bernadette, została naprawiona. – pad