let rec matchs str currList =
    match currList with 
    | [] -> []
    | (str, _) as hd :: tl -> hd :: matchs str tl
    | _::tl -> matchs str tl

У меня здесь есть моя функция, и когда я пытаюсь выполнить ее с помощью этой строки:

matchs "A" [("A",5); ("BB",6); ("AA",9); ("A",0)];;

Это данный вывод

val it : (string * int) list = [("A", 5); ("BB", 6); ("AA", 9); ("A", 0)]

Я не понимаю, почему он не дает мне только кортежи, соответствующие "A"

В конце концов я бы хотел, чтобы мой результат был

val it : int list = [0; 5]
1
tofokevin 12 Фев 2021 в 21:43

1 ответ

Лучший ответ

TL; DR: вы не можете сопоставить содержимое переменной, только литералы и конструкторы (ну и активные шаблоны).


Этот случай совпадения:

| (str, _) as hd :: tl -> 

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

Вот упрощенная версия этой проблемы:

let x = 42
let y = 5

match y with
| x -> printfn "%d" x
| _ -> printfn "not equal to x"

Этот код выведет «5», а не «42». И вы получите предупреждение компилятора о том, что второй случай совпадения никогда не будет достигнут.


Если вам нужны только кортежи с первым компонентом str, вы можете использовать защиту when с вашим шаблоном:

| (s, _) as hd :: tl when s == str -> 
4
Fyodor Soikin 12 Фев 2021 в 19:23