A 'small' ocaml printf issue. There is a printf in module Printf that works in utop and even ocaml (interpreter) and with ocamlc (compiled) There is printf in module Stdio. that only works in utop and ocaml (interpreter) but not in compiled code.
When I compile the code with this: camlopt -I
ocamlfind query stdio -o penelem penelem.ml
The Printf.printf version works just fine but the Stdio.printf version fails with:
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.
Supposedly Printf.printf is being deprecated at some point in favor of Stdio.printf (according to compiler messages). So I'm assuming they're trying to move everybody over to Stdio.printf eventually. If anybody has used Stdio.printf extensively I have been thinking over the complicated type errors but am still stymied as to the exact statement construction for this function. Further examples would be appreciated. Why aren't there any good ones in the Stdio.printf documentation? Seeing an example is easier than thinking too hard about it!
Here is the simple code from an ocaml intro course:
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 ;;
Switched back and forth between Stdio.printf and Printf.printf Put a double semicolon after every statement to isolate them.
From Stdio.printf and Printf.print I was expecting the same output from interpreted and compiled code. The exception is expected and is part of the example.
#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
Of course Stdio.printf gave a type error message instead of the expected output.
First, the
Printf
module from the standard library is not getting deprecated at all. The message that you are alluding at is probably just thebase
alternative standard library being opinionated aboutPrintf
.Second, the type error in your example is due to a misuse of
ocamlopt
: all transitive dependencies must be included with-I ...
when callingocamlopt
directly as explained by the last part of the type error messageIndeed, since you are not including the
base
library cmis, the compiler can only make the hypothesis that theBase.format
type is abstract.Third, I would advise you to use
dune
(or at the very leastocamlfind ocamlopt -package
) to compile your programs if your objective is not to write build systems for OCaml:would work, or just
with a dune file with the right dependencies.