vent
vent

Reputation: 39

Error around string modification and `printf` in OCaml

I want to write a function with input is a List of string, and output is a string. For example : List :

   3   11 12
    15  13 14 15

Output:

(assert
     (and  (= (+ x11 x12) 3)  
            (= (+ x13 x14 x15) 15)
))

The code I wrote:

let print data =
    printf "(assert \n(and ";
    List.iter (fun l ->  
    let str = "(=(+" in 
    str ^ "x" ^(String.concat "x" (List.tl l)) ^ ")" ^ (List.hd l) ^ ")\n";  
    printf str;
    ) data;
    printf "))";
;;

But it didn't work. When compiling, it showed error

Please help me to fix it. Thank you very much

Upvotes: 0

Views: 194

Answers (1)

camlspotter
camlspotter

Reputation: 9030

I see three problems.

Forgot to open Printf module

printf is used without open Printf. Maybe it is done somewhere else, since apparently you did not paste the whole code. Learn to ask good questions.

Typing glitch of printf

printf str is not well-typed in OCaml. This is pretty confusing for newcomers. OCaml's printf tries to mimic C's printf behaviour and for this purpose its typing is a little strange. To tell it in very short but a bit inaccurately, the rule is:

printf must take its format string argument in constant form. Or you are in trouble.

In your code, printf "(assert \n(and " and printf "))" is ok since they get string constants, but printf str is not. It is a variable.

The easy fix is to use print_string instead of printf:

print_string str

should work. printf is tricky but I think I should not go further here. If you want to know more, there are several QAs about OCaml's printf typing in SO, for example: OCaml Printf.sprintf

Wrong "string modification"

Assume that the above typing issue of printf is fixed by replacing it by print_string.

We still get a warning "Warning 10: this expression should have type unit." around the string concatenation str ^ "x" ^.. where the questioner tried modifying str, but this is wrong.

First, note that this expression does not modify the contents of str. It creates a new string by concatenating str and other strings. This new string is not used and just discarded in the code, this is why we get the warning. str is unchanged and therefore the output would be different from what it would be. Warning 10 is a pretty good indication of this sort of bugs and therefore you should not ignore it.

If you want to print the new string you have to give it to print_string (was printf in the original code) You should write:

let str' = str ^ "x" ^(String.concat "x" (List.tl l)) ^ ")" ^ (List.hd l) ^ ")\n" in
print_string str'

or, just

print_string (str ^ "x" ^(String.concat "x" (List.tl l)) ^ ")" ^ (List.hd l) ^ ")\n")

Upvotes: 1

Related Questions