2009-06-03 6 views
6

Mam funkcji zadeklarowanej jakoJak mogę rzucić "ciąg" w "opcji <string>"

let GetLength (value : option<string>) = 
    if value.IsSome then value.Value.Length else 0 

I mam zmienną

let a : string = "tom" 

Jak mogę przekazać do funkcji GetLength?

+0

Idiomatically, nie piszesz .IsSome i.Wartość, zamiast tego używasz instrukcji "dopasuj". – Brian

+2

Na podstawie serii dzisiejszych pytań przydatne może być przeczytanie http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!180.entry i http://lorgonblog.spaces.live.com/ blog/cns! 701679AD17B6D310! 181.entry, które zapewniają motywację do opowiadania typu opcji. – Brian

+0

To nie potrwa długo. Dlaczego ktoś miałby żetony typu 18 powyżej 3 linii, skoro można uzyskać to samo, używając 12 żetonów w jednej linii? –

Odpowiedz

8

Nie rzuca się go. Musisz użyć konstruktora Some:

GetLength Some a 
+0

Cóż, to jest głupie. Oczywiście dowolna wartość ciągu będzie spełniać wymagania opcji . Nie powinienem był wyraźnie dokonywać tego nawrócenia. –

+7

@Grauenwolf: może warto poświęcić trochę czasu na naukę pisania idiomatycznego kodu F # przed zbytnią ostrą krytyką. Myślę, że przekonasz się, że chociaż często różni się to od typowego kodu C# lub VB.NET, istnieje powód, dla którego rzeczy zostały zaprojektowane tak, jak są ... – kvb

+1

To niespójne, jeśli nalegasz na myślenie o opcji <'a> jako Nullable , I że już ustaliliśmy, że nie jest. opcja <'a> jest typem definiującym biblioteki F #, kompilator nie traktuje jej jako wyjątku. – Robert

10

Odpowiedź Zaakceptowany nie kompiluje i tworzy ...

GetLength Some a;; 

^^^^^^^^^^^^^^ błąd FS0003: ta wartość nie jest funkcją i nie można jej zastosować

F # myśli, że budujesz funkcję (GetLength Some), aby zastosować ją do wartości a. To dlatego, że jest to język funkcjonalny.

Poprawna forma jest

GetLength (Some a);; 
4

alternatywa do nawiasów:

GetLength <| Some a 

myślę, że ważne jest, aby zająć się tym pytanie:

Dlaczego ktoś miałby typu skłonny 18 tokeny ponad 3 linie, kiedy można uzyskać dokładnie to samo za pomocą 12 tokenów w jednym wierszu?

Pisanie kodu to nie tylko zwięzłość - dotyczy to również czytelności i łatwości konserwacji. Załóżmy, że musisz zająć się sprawą, w której a jest a. Z pasujące do wzorca, można przejść z tego:

let GetLength (value : string option) = 
    match value with 
    | Some s -> s.Length 
    | _ -> 0 

do tego:

let GetLength (value : string option) = 
    match value with 
    | Some s when s <> null -> s.Length 
    | _ -> 0 

Do F # programista, że ​​ich znaczenie jest jasne. Aby rozwiązać implementację wyglądałby mniej więcej tak:

let GetLength (value : option<string>) = 
    if value.IsSome && value.Value <> null then value.Value.Length else 0 

Rezultatem może być taka sama, ale nie jest szczególnie dobrze widoczne na pierwszy rzut oka, co się dzieje.

Jest to dobre, jeśli dopasowywanie wzorów nie współgra z tobą, ale dodatkowy "koszt" w prostym przypadku jest często uzupełniany wiele razy w miarę ewolucji logiki.

2

Aby odpowiedzieć na pytanie ogólne odlewania 'a do option<'a>, jeśli chcesz to zrobić bezpiecznie bez prostu zastosowanie obiektu do konstruktora Some, istnieje prosta funkcja, która będzie używać:

let to_option = function 
    | null -> None 
    | obj -> Some obj 
Powiązane problemy