caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Passing printf format strings to functions
@ 2004-09-14 21:55 Erik de Castro Lopo
  2004-09-14 22:08 ` Micha
  2004-09-15  8:12 ` Jean-Christophe Filliatre
  0 siblings, 2 replies; 5+ messages in thread
From: Erik de Castro Lopo @ 2004-09-14 21:55 UTC (permalink / raw)
  To: caml-list

Hi all,

I've got a little problem which I can't seem to get to the
bottom of. The following code snippet won't compile:


    let rec print_string_pairs (fmt:string) =
        function
            [] -> print_endline ""
        |    a :: b ->
                Printf.printf fmt (fst a) (snd a) ;
                print_string_pairs fmt b
        ;;

    let fmt = Printf.sprintf "      %%%ds  ==  %%s\n" 20 ;;

    print_endline fmt ;;

    let pairs = [ ("a", "b") ; ("c", "d") ; ("e", "f") ] ;;

    print_string_pairs fmt pairs ;;

and it gives me an error (line 5 is the Printf.printf line):

    File "fmt.ml", line 5, characters 18-21:
    This expression has type string but is here used with type
      ('a -> 'b -> 'c, out_channel, unit) format =
        ('a -> 'b -> 'c, out_channel, unit, unit) format4

If I replace "fmt" on that line with

    Printf.printf "%s     %s\n" (fst a) (snd a) ;

there is no problem. I think this is something to do with type
inferencing of format strings but I can't get to the bottom
of it.

Any suggestions?

TIA,
Erik
-- 
+-----------------------------------------------------------+
  Erik de Castro Lopo  nospam@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
"Using Java as a general purpose application development language
is like going big game hunting armed with Nerf weapons."
-- Author Unknown

-------------------
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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Passing printf format strings to functions
  2004-09-14 21:55 [Caml-list] Passing printf format strings to functions Erik de Castro Lopo
@ 2004-09-14 22:08 ` Micha
  2004-09-17 21:32   ` Pierre Weis
  2004-09-15  8:12 ` Jean-Christophe Filliatre
  1 sibling, 1 reply; 5+ messages in thread
From: Micha @ 2004-09-14 22:08 UTC (permalink / raw)
  To: caml-list; +Cc: Erik de Castro Lopo

Hi,

Am Tuesday 14 September 2004 23:55 schrieb Erik de Castro Lopo:
> Hi all,
>     let rec print_string_pairs (fmt:string) =
>         function
>             [] -> print_endline ""
>
>         |    a :: b ->
>
>                 Printf.printf fmt (fst a) (snd a) ;
>                 print_string_pairs fmt b
>         ;;


I think the fmt variable has not to be of type string but of some format type.
there exists a conversion function in Pervasives:

val format_of_string : ('a, 'b, 'c, 'd) format4 -> ('a, 'b, 'c, 'd) format4
  (*format_of_string s returns a format string read from the string literal 
s.*)


 Michael

-------------------
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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Passing printf format strings to functions
  2004-09-14 21:55 [Caml-list] Passing printf format strings to functions Erik de Castro Lopo
  2004-09-14 22:08 ` Micha
@ 2004-09-15  8:12 ` Jean-Christophe Filliatre
  2004-09-15  8:35   ` Erik de Castro Lopo
  1 sibling, 1 reply; 5+ messages in thread
From: Jean-Christophe Filliatre @ 2004-09-15  8:12 UTC (permalink / raw)
  To: Erik de Castro Lopo; +Cc: caml-list


Erik de Castro Lopo writes:
 > 
 > I've got a little problem which I can't seem to get to the
 > bottom of. The following code snippet won't compile:
 > 
 >     let rec print_string_pairs (fmt:string) =
 >         function
 >             [] -> print_endline ""
 >         |    a :: b ->
 >                 Printf.printf fmt (fst a) (snd a) ;
 >                 print_string_pairs fmt b
 >         ;;

A format is not of type "string" but of type "('a,'b,'c) format". Here
is how you can write such a function:

======================================================================
let rec print_string_pairs (fmt:(string->string->'a,'b,'c) format) =
  ...
======================================================================

But the type of fmt can be inferred, thus you can simply write:

======================================================================
let rec print_string_pairs fmt =
  ...
======================================================================

Note that this second version is now polymorphic : it applies to any
format of type ('a -> 'b -> 'c, out_channel, unit) format and a list
of type ('a * 'b) list:

======================================================================
# print_string_pairs "%s->%s\n" [ ("a", "b") ; ("c", "d") ; ("e", "f") ];;
a->b
c->d
e->f

# print_string_pairs "%d->%d\n" [ 1,2; 3,4; 5,6 ];;
1->2
3->4
5->6
======================================================================

 >     let fmt = Printf.sprintf "      %%%ds  ==  %%s\n" 20 ;;
 > 
 >     print_endline fmt ;;
 > 
 >     let pairs = [ ("a", "b") ; ("c", "d") ; ("e", "f") ] ;;
 > 
 >     print_string_pairs fmt pairs ;;

There  is a additional  difficuly here,  because you  want to  build a
format string  dynamically. With the code  above, fmt will  be of type
string, and then cannot  be passed to print_string_pairs. As suggested
by Michael,  you can use format_of_string  to convert a  string into a
format:

======================================================================
# let fmt = format_of_string "%20s == %s\n";;
val fmt : (string -> string -> '_a, '_b, '_c, '_a) format4 = <abstr>
# print_string_pairs fmt [ ("a", "b") ; ("c", "d") ; ("e", "f") ];;
                   a == b
                   c == d
                   e == f
======================================================================

But format_of_string  only applies  to a _constant_  string, not  to a
string built from an evaluation:

======================================================================
# let fmt = format_of_string (Printf.sprintf "      %%%ds  ==  %%s\n" 20) ;;
Characters 27-71:
  let fmt = format_of_string (Printf.sprintf "      %%%ds  ==  %%s\n" 20) ;;
                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This expression has type string but is here used with type
  ('a, 'b, 'c, 'd) format4
======================================================================

Indeed, there is  no static way to check that  the resulting format is
indeed of  type (string->string->'a,'b,'c) format. 

Hope this helps,
-- 
Jean-Christophe

-------------------
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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Passing printf format strings to functions
  2004-09-15  8:12 ` Jean-Christophe Filliatre
@ 2004-09-15  8:35   ` Erik de Castro Lopo
  0 siblings, 0 replies; 5+ messages in thread
From: Erik de Castro Lopo @ 2004-09-15  8:35 UTC (permalink / raw)
  To: caml-list

On Wed, 15 Sep 2004 10:12:28 +0200
Jean-Christophe Filliatre <Jean-Christophe.Filliatre@lri.fr> wrote:

Thanks Jean-Christophe for a very thorough and well explained
response.


> Indeed, there is  no static way to check that  the resulting format is
> indeed of  type (string->string->'a,'b,'c) format. 

Ahh, now I understand. 

With the knowledge you provided and some hacking I did after
I sent the original email, I was able to use a constant format
string like:

    Printf.printf  "    %-*s    %s\n" format_width (fst a) (snd a) ;;

and acheive the result I desired.

Cheers,
Erik
-- 
+-----------------------------------------------------------+
  Erik de Castro Lopo  nospam@mega-nerd.com (Yes it's valid)
+-----------------------------------------------------------+
"The earth is degenerating these days. Bribery and corruption abound.
Children no longer mind parents ...and it is evident that the end of
the world is approaching fast." -- Assyrian Tablet Engraved in 2800 B.C.

-------------------
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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Passing printf format strings to functions
  2004-09-14 22:08 ` Micha
@ 2004-09-17 21:32   ` Pierre Weis
  0 siblings, 0 replies; 5+ messages in thread
From: Pierre Weis @ 2004-09-17 21:32 UTC (permalink / raw)
  To: Micha; +Cc: caml-list, Erik de Castro Lopo

> Hi,
> 
> Am Tuesday 14 September 2004 23:55 schrieb Erik de Castro Lopo:
> > Hi all,
> >     let rec print_string_pairs (fmt:string) =
> >         function
> >             [] -> print_endline ""
> >
> >         |    a :: b ->
> >
> >                 Printf.printf fmt (fst a) (snd a) ;
> >                 print_string_pairs fmt b
> >         ;;
> 
> 
> I think the fmt variable has not to be of type string but of some
> format type.

Exactly. Hence you just have to remove the wrong type constraint
(fmt:string) and simply write fmt, to get it working beautifully:

val print_string_pairs :
  ('a -> 'b -> 'c, out_channel, unit) format -> ('a * 'b) list -> unit

>  there exists a conversion function in Pervasives:
> val format_of_string : ('a, 'b, 'c, 'd) format4 -> ('a, 'b, 'c, 'd) format4
>   (*format_of_string s returns a format string read from the string literal 
> s.*)

In this case I doubt you ever need to use this function: the type-checker
will do the job automatically for you!

For instance:

# print_string_pairs "(%s, %s)";;  
- : (string * string) list -> unit = <fun>

Or even:

# print_string_pairs "(%i, %i)";;
- : (int * int) list -> unit = <fun>

At this point, you should consider renaming your function, given its
highly polymorphic nature, it shoould be promoted to print_pairs ...

Best regards,

-- 
Pierre Weis

INRIA, Projet Cristal, http://pauillac.inria.fr/~weis

-------------------
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


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2004-09-17 21:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-09-14 21:55 [Caml-list] Passing printf format strings to functions Erik de Castro Lopo
2004-09-14 22:08 ` Micha
2004-09-17 21:32   ` Pierre Weis
2004-09-15  8:12 ` Jean-Christophe Filliatre
2004-09-15  8:35   ` Erik de Castro Lopo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).