2016-11-28 14 views
14

Tak, jestem doświadczonym programistą OOP (głównie C++), właśnie teraz zaczynam zanurzać palce w programowaniu funkcjonalnym. Z mojego rozumienia, w paradygmacie czysto funkcjonalnym, funkcje nie powinny mieć warunków warunkowych i powinny być w miarę możliwości rozkładane za pomocą curry. Czy ktoś mógłby mi podać "czystą" funkcjonalną wersję poniższego przykładu? Najlepiej używać każdej ścisłej techniki, która byłaby częścią paradygmatu funkcjonalnego:Programowanie czysto funkcjonalne

let rec greatestCommonFactor a b = 
    if a = 0 then b 
    elif a < b then greatestCommonFactor a (b - a) 
    else greatestCommonFactor (a - b) b 
+2

Witamy w przepełnieniu stosu! I gratuluję wyraźnego przeczytania [Centrum pomocy] (http://stackoverflow.com/help) przed zadaniem pytania: to było doskonałe pierwsze pytanie. Jasne, zwięzłe, z dokładnie niezbędnymi szczegółami i bez garstki obcojęzycznych słów. Zrobiłbym twoje pytanie 5 razy, gdybym mógł. Dobra robota! – rmunn

Odpowiedz

16

Podana funkcja przykładowa jest już czysto funkcjonalna. Kiedy mówimy o czystości funkcji, to o czym właśnie mówimy, jest właściwością funkcji będących referentially transparent.

Wyrażenie jest referencyjnie przezroczyste, jeśli można je zastąpić jego wartością bez wpływu na działanie programu. Aby podać prosty przykład, wyobraźmy sobie funkcję:

let add2 x = x + 2 

Teraz nigdzie, że wartość add2 2 pojawia się w naszym programie, możemy podstawić wartość 4 bez zmiany zachowania programu.

Wyobraźmy sobie teraz, że możemy dodać kilka dodatkowych zachowanie się funkcji, która drukuje do konsoli:

let add2Print x = 
    printfn "%d" x 
    x + 2 

Chociaż wynik funkcji jest taka sama jak wcześniej, nie możemy już wykonać zmiany wartości z wartością 4 bez zmiany zachowania naszego programu, ponieważ nasza funkcja ma dodatkowy efekt uboczny drukowania na konsoli.

Ta funkcja nie jest już przejrzysta, a zatem nie jest funkcją czysto referencyjną.


let rec greatestCommonFactor a b = 
    if a = 0 then b 
    elif a < b then greatestCommonFactor a (b - a) 
    else greatestCommonFactor (a - b) b 

Patrząc na tej funkcji, które zostały dostarczonej żadne skutki uboczne są zaangażowane w jego realizację. Zawsze otrzymamy tę samą wartość wyjściową dla danych wejść a i b, dlatego jest to już czysta funkcja.

Dla jasności, nie ma absolutnie żadnego problemu z funkcjami zawierającymi warunki warunkowe w programowaniu funkcjonalnym. Często jednak stosujemy wyrażenia dopasowujące, a nie wyrażenia if/elif/else, ale w przykładzie, który opisałeś, jest to czysto stylistyczne. Alternatywnym wyrażeniem funkcji przy użyciu dopasowania do wzorca jest:

let rec greatestCommonFactor a b = 
    match a with 
    |0 -> b 
    |a' when a' < b -> greatestCommonFactor a' (b - a') 
    |a' -> greatestCommonFactor (a' - b) b 
+2

Więc warunki nie mają znaczenia? Miałem wrażenie, że eliminacja czynników warunkujących była preferowana w paradygmacie funkcjonalnym. Takie jak używanie lambdas na ich miejscu. – Zach

+4

@Zach Niektóre języki funkcjonalne mają tendencję do stosowania stylów zwięzłych, ale nadal istnieją warunkowe. Nawet Haskell ma słowo kluczowe 'if', chociaż, podobnie jak w F #, używałbyś dopasowywania wzorców bardziej niż' if' i 'then'. –

+5

@Zach Nie, warunkowe absolutnie nie mają znaczenia. Często warunkowania w programowaniu funkcjonalnym są obsługiwane poprzez dopasowywanie wzorców, a nie przez wyrażenia 'if/elif/else', ale w przypadku, który tu przedstawiłeś, jest to czysta stylistyka. – TheInnerLight

Powiązane problemy