Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: Xavier Leroy <xavier.leroy@inria.fr>
To: Sylvain LE GALL <sylvain.le-gall@polytechnique.org>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] Printf and format
Date: Sun, 6 Jul 2003 12:35:46 +0200	[thread overview]
Message-ID: <20030706123545.A227@pauillac.inria.fr> (raw)
In-Reply-To: <20030705120714.GA8202@gallu>; from sylvain.le-gall@polytechnique.org on Sat, Jul 05, 2003 at 02:07:14PM +0200

> Is there a way to transform string to ( 'a, out_channel, unit, unit)
> format. I need this function to use it with something like :
> 
> Printf.printf (my_fun "X, Y") "coucou";;

No, not in a type-safe manner.  The type of a format string depends on
the "%" specifiers found in the string itself, and OCaml can't infer
or check types at run-time.

However, for the purpose of internationalization, the following
operation suffices: given a (compile-time constant) format and a
(dynamically computed) string, check that the string can be viewed as
a format with the same format type as the constant format, and return
the string as a format.  

In OCaml 3.06, this can be done as follows:

  let re_fmt =
    Str.regexp "%[#0-9.*+ -]*[lnL]?[sScCdioxXunfeEgGFbBatn[]"

  let string_of_format (s : ('a, 'b, 'c) format) = (Obj.magic s : string)

  let extract_formats s =
    List.fold_right
      (fun part accu ->
        match part with Str.Text _ -> accu | Str.Delim d -> d :: accu)
      (Str.full_split re_fmt s) []

  let conv_format (src: ('a, 'b, 'c) format) (dst: string) =
    if extract_formats (string_of_format src) = extract_formats dst
    then (Obj.magic dst : ('a, 'b, 'c) format)
    else failwith "conv_format"

Remark 1: yes, there's a lot of "Obj.magic" in this code, and yes,
this is a deadly sin, but in this particular instance it is all
type-safe nonetheless.

Remark 2: the matching of the two formats can be relaxed, e.g.
the code above will not allow the conversion of "%6d" into "%8x",
although both formats have the same type.  This is left as an exercise
for the reader.  But for internationalization purposes, I doubt
you need that additional flexibility.

Then, assuming you have a function "gettext : string -> string" to translate
strings according to the user-selected language, you can extend it to
formats as follows:

  let getformat f = conv_format f (gettext (string_of_format f))

and use it with printf functions like this:

  printf (getformat "My name is %s and I'm %d years old") "Bob" 12

> you read my mind. Indeed, the question concern an internationalization
> module ( let's call libgettext-ocaml ). It is basically a binding of
> gettext. 

I hope the above is enough to get you off the ground.

- Xavier Leroy

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


      reply	other threads:[~2003-07-06 10:35 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-07-03 16:38 Sylvain LE GALL
2003-07-05 10:26 ` Pierre Weis
2003-07-05 12:07   ` Sylvain LE GALL
2003-07-06 10:35     ` Xavier Leroy [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030706123545.A227@pauillac.inria.fr \
    --to=xavier.leroy@inria.fr \
    --cc=caml-list@inria.fr \
    --cc=sylvain.le-gall@polytechnique.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox