Ostatnio uczyłem się F # i pochodzę z imperatywu (C++/C#). Jako ćwiczenie pracowałem nad funkcjami, które mogą robić rzeczy z macierzami, takimi jak dodawanie, mnożenie, uzyskiwanie wyznaczników itp. Wszystko idzie dobrze w tym względzie, ale uważam, że być może nie podejmuję najlepszych decyzji, jeśli chodzi o obsługę Nieprawidłowe wejścia, na przykład:F #: Some, None lub Exception?
// I want to multiply two matrices
let mult m1 m2 =
let sizeOK = validateDims m1 m2
// Here is where I am running to conceptual trouble:
// In a C# world, I would throw an exception.
if !sizeOK then
raise (InvalidOperationException("bad dimensions!")
else
doWork m1 m2
Więc choć to technicznie działa, czy jest to właściwe dla języka funkcjonalnego? Czy jest to w duchu programowania funkcjonalnego? Czy miałoby to więcej sensu przepisywać ją jako:
let mult m1 m2 =
let sizeOK = validateDims m1 m2
if !sizeOK then
None
else
Some doWork m1 m2
W tym przypadku Wracam opcję, która dodaje dodatkową warstwę wokół matrycy, ale mogę też korzystać z wyników czynności, nawet w braku przypadki (brak) z dopasowaniem wzorców itp. w pewnym późniejszym punkcie programu. Czy istnieje najlepsza praktyka dla tego typu scenariuszy? Co zrobiłby funkcjonalny programista?
Uważam, że ten ostatni jest bardziej "w duchu" PR. Możesz zajrzeć do monady Maybe, a także do jednego wspólnego podejścia do obsługi złych danych wejściowych. –
Jak powiedział Pad w swojej odpowiedzi, często implementuję dwie funkcje, jedną, która rzuca na błędy i identyczną funkcję-try, która zwraca opcję/wybór zamiast rzucania. następnie używam tego, który sprawia, że mój ostatni kod wygląda najładniej :) dla łatwiejszej obsługi opcji/wyboru, możesz przeczytać "programowanie zorientowane na kolej": http://fsharpforfunandprofit.com/posts/recipe-part2/ – stmax