Как проверить, является ли значение нулевым или нет в F # - PullRequest
0 голосов
/ 28 июня 2018

Используя этот код в качестве примера, как я могу проверить, является ли ввод нулевым или нет? Подобный код вызывает исключение нулевой ссылки

let private Method ( str:string) : string = 
    let a = str
    a.[a.Length-1] 

1 Ответ

0 голосов
/ 14 июля 2018

Несмотря на то, что isNull - очень простой ответ, он вполне оправдан, я подумал, что было бы интересно поиграть с несколькими другими, потому что F # - это весело :)

Сначала давайте настроим небольшую функцию для быстрого тестирования результатов

open System

let test f a = 
    try 
        printfn "Input %A, output %A" a (f a)
        printfn "Input %A, output %A" "" (f "")
        printfn "Input %A, output %A" null (f null)
    with
    | :? Exception as ex -> printfn "%s" ex.Message

Наша первая функция - просто установить базовый уровень.
Выдает исключение

//string -> string
let getLast1 ( s:string) : string = s.[s.Length-1] |> string

printfn "=== getLast1 ==="
test getLast1 "bing"

=== getLast1 ===
Вход «bing», выход «g»
Индекс находился за пределами массива.

Следующий проверяет значение с помощью if и возвращает пустую строку, если не является допустимым значением.
Возвращает пустую строку

//string -> string
let getLast2 ( s:string) : string = 
    if (String.IsNullOrEmpty s) then "" 
    else s.[s.Length-1] |> string

printfn "=== getLast2 ==="
test getLast2 "bing"

=== getLast2 ===
Вход «bing», выход «g»
Вход "", выход ""
Вход, выход ""

По крайней мере, сейчас выполняются все пути.

Давайте попробуем более функциональный подход:
Возвращает option с использованием сопоставления с шаблоном

//string -> string option
let getLast3 (s:string) =
    match s with
    | null -> None
    | _ ->
        match (s.ToCharArray()) with
        | [||] -> None
        | [|x|] -> Some x
        | xs -> Array.tryLast xs
    |> Option.map string

printfn "=== getLast3 ==="
test getLast3 "bing"

=== getLast3 ===
Вход "Бинг", вывод Некоторые "г"
Ввод "", вывод // обратите внимание, что на самом деле None здесь.
Ввод , вывод // обратите внимание, что здесь None.

Это работает, но это не самая простая функция для чтения. Это не так уж плохо, но что, если мы попытаемся сломать это.

Составная функция

//'a -> 'a option
let sanitize x = if (isNull x) then None else Some(x)
//string -> char[]
let toCharArray (s:string) = s.ToCharArray()
//'a[] option -> 'a option
let last xs = 
    xs |> Option.map Array.tryLast //tryLast returns an 'a option
    |> Option.flatten // turns 'a option option to a' option

Теперь, когда у нас есть строительные блоки, мы можем создать нашу новую последнюю функцию:

//string -> string option
let getLast4 s =
    s |> sanitize
    |> Option.map toCharArray 
    |> last
    |> Option.map string

printfn "=== getLast4 ==="
test getLast4 "bing"

=== getLast4 ===
Вход "bing", вывод Some "g"
Ввод "", вывод // обратите внимание, что здесь на самом деле None.
Ввод, вывод // обратите внимание, что на самом деле None здесь.

Если честно, getLast2, наверное, хорошо. Если бы я обнаружил, что проверяю пустую строку, я бы предпочел вернуть Some или None из if. Я просто хотел показать, как отойти от null и использовать встроенные функции Array.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...