我正在尝试编写一个计算列表大小的代码。
以下是我所做的:
let rec l = function
| [] -> 0
| t::q -> 1 + l q
print_int(l ([1;2;3;4]))
问题是它在说我:
It is applied to too many arguments; maybe you forgot a `;'.
当我在;;
定义的末尾放置双分号l
时效果很好,但我已经读过如果你不是;;
根本没用在REPL编码,所以在这里我不明白为什么它给了我这个错误。
答案 0 :(得分:1)
以下
print_int(l [1;2;3;4])
是一个顶级表达。这种表达需要以;;
:
;; print_int(l [1;2;3;4])
另一个选择是使这个顶层表达式与
绑定let () = print_int(l [1;2;3;4])
答案 1 :(得分:1)
解析代码时,解析器会前进,直到达到l q
。此时可能会有更多的参数应该应用于函数l。所以解析器继续运行,它找到的下一个东西是值print_int。 l的另一个论点。这会给你错误。
解析器无法知道您已完成函数l的代码。在顶层,特殊标记;;
用于告诉解析器输入已完成,它现在应该评估代码。之后,它再次开始削减剩余的输入。
现在为什么编译后的代码也没有';;'令牌?
仅仅因为它不需要。在编译的代码中,行print_int(l [1;2;3;4])
不是有效输入。那将是你想要执行的语句,而函数式语言则没有这样的东西。相反,print_int(l [1;2;3;4])
是一个表达式,在这种情况下返回一个值,(),你必须告诉编译器该如何处理该值。 let () =
告诉编译器将它与()匹配。 let ...
也告诉编译器前一个let rec l ...
已经完成。因此,不需要特殊的;;
令牌。
或者以这种方式考虑:如果您的输入不以let开头,则在顶层有一个隐式let _ =
。这样,您只需键入一些表达式并查看其评估结果,而无需每次都键入let _ =
。 ';;'令牌仍然意味着“现在评估”,但仍然需要。