一个“小”ocaml printf 问题。 Printf 模块中有一个 printf 可以在 utop 甚至 ocaml (解释器)和 ocamlc (编译器)中工作 Stdio模块中有printf。仅适用于 utop 和 ocaml(解释器),但不适用于编译代码。
当我用以下代码编译代码时:
camlopt -I
ocamlfind query stdio -o penelem penelem.ml
Printf.printf 版本工作正常,但 Stdio.printf 版本失败并显示:
Error: This expression has type string but an expression was expected of type ('a -> 'b, Stdio.Out_channel.t, Base.unit) Base.format Base.format is abstract because no corresponding cmi file was found in path.
据称 Printf.printf 在某些时候已被弃用,取而代之的是 Stdio.printf(根据编译器消息)。所以我假设他们最终试图将每个人都转移到 Stdio.printf 上。 如果有人广泛使用 Stdio.printf,我一直在思考复杂的类型错误,但仍然对该函数的确切语句构造感到困惑。进一步的例子将不胜感激。为什么 Stdio.printf 文档中没有任何好的内容?看例子比认真思考更容易!
这是来自 ocaml 入门课程的简单代码:
open Stdio
(* open Printf *)
let rec sum lst =
match lst with
| [] -> 0
| h :: t -> h + sum t ;;
let numbers = [2; 8; 4; 5; 9] ;;
let result = sum numbers ;;
let () = Stdio.printf "About to print some numbers ...\n" ;;
let () = Stdio.printf "Sum = %d\n%!" result ;;
let name = "Alice" in printf "Hello, %s\n%!" name
let rec print_list lst =
match lst with
| [] -> printf "\n" ;
| head :: tail ->
printf "%d " head ;
print_list tail ;;
let () = print_list numbers ;;
在Stdio.printf和Printf.printf之间来回切换 在每个语句后放置一个双分号以隔离它们。
从 Stdio.printf 和 Printf.print 中,我期望解释和编译的代码具有相同的输出。 该异常是预期的并且是示例的一部分。
#use "penelem.ml" ;;
val numbers : int/2 list/2 = [1; 8; 2; 5]
val words : string/2 list/2 = ["ocean"; "water"; "sea"]
val before_last : 'a list/2 -> 'a = <fun>
penultimate element of numbers is: 2
penultimate element of words is: water
Penultimate element of [1,2] is 1
Exception: (Failure "Singleton List -> No Penultimate Element").
Raised at Stdlib.failwith in file "stdlib.ml", line 29, characters 17-33
Called from penum in file "penelem.ml", line 35, characters 12-27
Called from Topeval.load_lambda in file "toplevel/byte/topeval.ml", line 89, characters 4-14
当然,Stdio.printf 给出了类型错误消息,而不是预期的输出。
首先,标准库中的
Printf
模块根本没有被弃用。您所提到的消息可能只是对 base
有意见的 Printf
替代标准库。
其次,示例中的类型错误是由于误用
ocamlopt
造成的:直接调用 -I ...
时,所有传递依赖项都必须包含在 ocamlopt
中,如类型错误消息的最后部分所述
Base.format is abstract because no corresponding cmi file was found in path.
第三,如果您对为 OCaml 编写构建系统不感兴趣,我建议您使用
dune
(或至少 ocamlfind ocamlopt -package
)来编译您的程序。