这是我的代码:
type noeud = Lettre of (char * bool * arbre_lex)
and arbre_lex = noeud list
exception Deja_defini of string
let rec ajoute mot arbre n =
if existe mot arbre then raise (Deja_defini mot) else
match arbre with
| [] ->
begin
if n+1 = String.length mot then [ Lettre( mot.[n] , true , [] ) ]
else [ Lettre ( mot.[n] , false, ajoute mot arbre (n+1) ) ]
end
| head::tail ->
begin
match head with
| Lettre (mot.[n], b, a) -> (*line 19, source of error*)
begin
if n+1 = String.length mot then [ Lettre ( mot.[n] , true , a ) ]::tail
else [ Lettre ( mot.[n] , b , ajoute mot a (n+1) ) ]::tail
end
| Lettre (_, b, a) -> ajoute mot tail n
end
编译时,出现以下错误:
$ocamlc -o main *.ml
File "main.ml", line 19, characters 21-22:
Error: Syntax error: ')' expected
File "main.ml", line 19, characters 17-18:
Error: This '(' might be unmatched
现在,我知道我可以改进代码,并且可以在第一个匹配项中包含第二个匹配项,但是,我特别想找到错误的来源。我做了很多尝试,但似乎都没有改变错误。
因此随时发布改进,但是我最感兴趣的是我如何运行此确切的代码来避免将来发生错误
答案 0 :(得分:2)
箭头左侧的语法结构不是普通表达式,而是一种模式。为了方便起见,它看起来很像一个表达式,但是其行为却大不相同。它也是纯粹的编译时构造。
例如,像a
中的模式Lettre (_, b, a)
不会求值a
,也不会将a
位置的值与该值匹配名为a
的现有绑定。取而代之的是,它将创建一个名为a
的新绑定,该绑定引用a
位置处的值,并隐藏该名称之前的所有绑定。
因此,例如,如果您要匹配的值为Lettre ('a', true, [])
,则a
将在箭头的右侧引用值[]
。并且b
将指向true
。
除了将值绑定到模式中的名称的便捷语法之外,不允许模式中的运行时值还允许编译器保证模式匹配的穷尽性并在编译时对其进行优化。如果在模式中允许运行时值,则始终必须提供通配符模式以捕获其余的可能性,因为您将无法在编译时知道哪些可能性在运行时可能匹配。
我希望您现在明白为什么在模式中不允许使用mot.[n]
之类的表达式,甚至不允许绑定mot.[n]
值的名称。
但是,有一个与模式分开的结构,允许在模式匹配中使用运行时条件,称为“保护”或“何时”子句。使用您的示例:
match head with
| Lettre (ch, b, a) when ch = mot.[n] -> ...
这确实需要用通配符代替ch
的情况来涵盖警卫不匹配的所有情况。但是既然你已经拥有了,那你就应该很好。