Сопоставление тестовых шаблонов типа F #: разложение объектов кортежа

#f# #tuples #pattern-matching #decomposition

#f# #Кортежи #сопоставление с шаблоном #разложение

Вопрос:

Просто любопытно, почему я не могу этого сделать:

 let myFn (data : obj) =
    match data with
    | :? (string * string) as (s1, s2) -> sprintf "(%s, %s)" s1 s2 |> Some
    | :? (string * string * int) as (s1, s2, i) -> sprintf "(%s, %s, %d)" s1 s2 i |> Some
    | _ -> None
  

Как так получилось?

Комментарии:

1. Это было бы неплохо. Жаль, что это не поддерживается.

2. Хотя это можно было бы предложить в github.com/fsharp/fslang-suggestions , Я думаю, что это плохая идея, так как это побудило бы людей писать подобный код. Этого кода следует избегать, поскольку он требует использования obj и сопоставления типов. F # следует использовать типобезопасным способом, а использование obj и понижение значения отвлекает от этого.

Ответ №1:

См. Спецификацию F #, раздел 7.3 «Как шаблоны»

Шаблон as имеет вид pat as ident

Это означает, что вам нужно использовать идентификатор после as :

 let myFn (data : obj) =
    match data with
    | :? (string * string)       as s1s2  -> let (s1, s2)    = s1s2  in sprintf "(%s, %s)" s1 s2 |> Some
    | :? (string * string * int) as s1s2i -> let (s1, s2, i) = s1s2i in sprintf "(%s, %s, %i)" s1 s2 i |> Some
    | _ -> None
  

Комментарии:

1. Я знаю, что говорится в спецификации. Я искал более техническое объяснение того, почему деконструкция кортежа после «as» не поддерживается, тем более, что большинство пользователей интуитивно понимают этот язык.

2. Технических ограничений нет, кроме того, что функция не реализована. Есть и другие места, где деконструкция не поддерживается, например, в параметре «this» членов, который является местом, где вы часто хотите деконструировать. Все это можно добавить в язык после отправки предложения и получения его одобрения.