tl;dr

Нужно ли мне реализовать каждую вспомогательную функцию, как показано ниже?

let splitToTuple2 str =
    совпадение str.Split() с
    | [| a; b |] -> a, b
    | _ -> failwith "размер должен быть 2"

let splitToTuple3 str =
    match str.Split() with
    | [| a; b; c |] -> a, b, c
    | _ -> failwith "size must be 3"

let splitToTuple4 str =
    match str.Split() with
    | [| a; b; c; d |] -> a, b, c, d
    | _ -> failwith "размер должен быть 4"

мотивация

Количество слов известно заранее.

let str = "first second third" // каждое слово разделяется пробелом

Этого достаточно, чтобы сделать то, что мне нужно.

let arr = str.Split()
let a = arr.[0] // "первый"
let b = arr.[1] // "второй"
let c = arr.[2] // "третий"

Как бы то ни было, я бы хотел делать это одним кликом.

let [| a; b; c |] = str.Split() // ПРЕДУПРЕЖДЕНИЕ: Неполное совпадение шаблонов в этом выражении.

#nowarn "25" является неблагоприятным, поскольку влияет на весь файл.

В данном случае мне нужно разделить строку на string * string * string * string, чтобы избежать предупреждения.

let a, b, c = str |> splitToTuple3

Нужно ли мне реализовать каждую вспомогательную функцию, как указано в начале?

topica

Ответов: 1

Ответы (1)

В общем случае да, в вашем случае необходимо создать три отдельные функции, поскольку каждая функция возвращает различный тип данных - кортеж из двух, трех или четырех элементов. Вы можете рассмотреть возможность создания дискриминированного объединения, чтобы охватить все случаи, для которых требуется только одна функция, как, например

module Split = 
    
    let split (str:string) = str.Split() 

    type SplitterTuple<'t> =
    | Two of 't * 't
    | Three of 't * 't * 't
    | Four of 't * 't * 't * 't

    let getTuple<'t> (l : 't array) : SplitterTuple<'t> = 
        match l with
        | [|a; b; c; d|] -> Four (a, b, c, d)
        | [|a; b; c|]  -> Three (a, b, c)
        | [|a; b|] -> Two (a, b)
        | _ -> failwith "Incompatible list"

Это позволяет вам создать потребительскую функцию, которая использует результат getTuple. Обратите внимание, что эта функция возвращает единицу для всех случаев.

let displayResult = function
    | Two(a, b) -> printfn "two elements: %A" (a, b)
    | Three(a, b, c) -> printfn "three elements: %A" (a, b, c)
    | Four(a, b, c, d) -> printfn "four elements: %A" (a, b, c, d)

Возможно, вам стоит рассмотреть возможность использования типа записи вместо кортежа, так как это может быть проще в обработке.

//test code
    let t1 = "first" |> split |> getTuple |> displayResult //fails
    let t2 = "first second" |> split |> getTuple |> displayResult
    let t3 = "first second third" |> split |> getTuple |> displayResult
    let t4 = "first second third fourth" |> split |> getTuple |> displayResult
    let t5 = "first second third fourth fifth" |> split |> getTuple  |> displayResult //fails

2022 WebDevInsider