То, что вы пытаетесь сделать, называется шаблоном равенства, и оно не предоставляется Objective Caml. Объективные паттерны Камла являются статичными и чисто структурными. То есть, соответствует ли значение шаблону, зависит исключительно от структуры значения и способом, который определяется во время компиляции. Например, (_, _)::tail
- это шаблон, который соответствует любому непустому списку, чья голова является парой. (identifier, value)::tail
соответствует точно таким же значениям; единственное отличие состоит в том, что последний связывает еще два имени identifier
и value
.
Хотя в некоторых языках существуют шаблоны равенства, существуют нетривиальные практические соображения, которые делают их проблематичными. Какое равенство? Физическое равенство (==
в Окамле), структурное равенство (=
в Окамле) или какое-то пользовательское равенство, зависящее от типа? Кроме того, в Ocaml есть четкое синтаксическое указание того, какие имена являются связующими и какие имена относятся к ранее связанным значениям: любой строчный идентификатор в шаблоне является связующим. Эти две причины объясняют, почему в Ocaml не используются шаблоны равенства. Идиоматический способ выражения шаблона равенства в Ocaml стоит на страже. Таким образом, сразу становится ясно, что сопоставление не является структурным, что identifier
не связано этим сопоставлением с образцом и какое равенство используется. Что касается уродливости, это в глазах смотрящего - как обычный программист на Ocaml, я нахожу паттерны равенства некрасивыми (по причинам выше).
match bindings with
| (id, value)::tail when id = identifier -> value
| (_, _)::tail -> getValue identifier tail
| [] -> -1
В F # у вас есть еще одна возможность: активные шаблоны , которые позволяют предварительно определять охрану, касающуюся одного сайта в шаблоне.