4

I need to convert from a string to a format. I'm given an array of formats, and I would like access each format and use sprintf on them.

e.g.

let errors = [| "format 1"; "format 2"; ... ; "format 512" |]
let code_to_string (error_code : int) :(string) = sprintf errors.(error_code)

I saw this question. According to the best answer, different strings produce formats of different types, which is why this:

let errors = [| format_of_string "format 1"; 
                format_of_string "format 2"; 
                ...
                format_of_string "format 512" |]

doesn't work.

Is there a way to store all formats as strings, and then convert them when needed? Or would I have to write a function for each of the strings? e.g.

let error1 = sprintf "format 1" args
let error2 = sprintf "format 1" args
...
let error512 = sprintf "format 512" args
Community
  • 1
  • 1
laifs
  • 197
  • 1
  • 2
  • 11

1 Answers1

3

You can convert arbitrary statically unknown values of type string into values of type format6 using Scanf.format_from_string. But, of course, you need to know the type of the format (and they all should unify).

Here is the motivating example:

# let fmt = Scanf.format_from_string "Hello: %d" "%d";;
val fmt : (int -> '_a, '_b, '_c, '_d, '_d, '_a) format6 = <abstr>
# Printf.printf fmt 12;;
Hello: 12- : unit = ()

P.S. And here is a more extreme use of this feature.

Community
  • 1
  • 1
ivg
  • 34,431
  • 2
  • 35
  • 63
  • so their types must all be equal right? e.g. for an array: `[| "format 1"; "format 2"; ... ; "format 512" |]` "format 1" to "format 512" must produce the same type when converted through `format_from_string`. – laifs Aug 14 '15 at 00:12
  • After playing with it, I found the same problem. I cannot store strings, and then convert them to formats. e.g. `let s = "string";format_of_string s;` doesn't work. However, what does work is to store them into the array as `format6` elements. This means that I had to unify them all in type by adding missing arguments. Problem is, if you have a format with 5 inputs, you have to know which of the 5 inputs are meant to be used, so it's an ugly solution. – laifs Aug 14 '15 at 00:32
  • 1
    you should use `Scanf.format_from_string` it will work with any string. If format doesn't match it will fail in runtime. But indeed you need to know the type of a format, the only thing that may vary between different formats is the actual text. – ivg Aug 14 '15 at 16:07
  • But I cant seem to give it stored strings. e.g. `let s = "hello %s";;Printf.sprintf (Scanf.format_from_string s) "world";;` gives me a type error. I am using independent function for each string format now, since stored strings and typed string (i.e. "strings like this") seem to be processed differently by printf. – laifs Aug 14 '15 at 19:33
  • Ooh, I seem to understand it better now. Scanf.format_of_string requires you to specify where to place the format string. i.e. `Printf.sprintf (Scanf.format_from_string s "%s") "world";;` That's much easier to understand now. Though, I would still need to know the type of the format when calling it, this clears things up a lot. Thanks. – laifs Aug 14 '15 at 20:01