Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: CPS version of sprintf #3321

Closed
vicuna opened this issue Apr 30, 2002 · 3 comments
Closed

Feature Request: CPS version of sprintf #3321

vicuna opened this issue Apr 30, 2002 · 3 comments

Comments

@vicuna
Copy link

vicuna commented Apr 30, 2002

Original bug ID: 1131
Reporter: administrator
Status: closed
Resolution: fixed
Priority: normal
Severity: feature
Category: ~DO NOT USE (was: OCaml general)

Bug description

Full_Name: Chris Quinn
Version:
OS:
Submission from: 212.42.169.63 (212.42.169.63)

It would be nice to have the ability to create functions akin to Printf.sprintf
which take multiple arguments, and do something with the resulting string.
The only way to do it is by making sprintf the result, ie:
let f (fmt: ('a,unit,string)) =
... do anything ...
in Printf.sprintf fmt

but then there is no access to the string it eventually produces!
The situation in which I have found a need is in interfacing to a C library
which has its version of printf for its own particular sort of channel type.
I guess this applies just as well to caml based libraries which have functions
that do arbitrary things with the conversion result.

I would like to propose adding a function to the Printf module that
is a very minor variation on sprintf which accepts a continuation for the
string result.
Since the work of format conversion is of course done in caml , that leaves
little
to do for any C-lib based version, but there's no harm in that.

I tested the function below to see if it actually invoked the continuation
on partial applications. It did not - as required.

let cprintf : (string -> 'b) -> ('a, unit, unit) format -> 'a = fun f fmt ->
let fmt = (Obj.magic fmt : string) in
let len = String.length fmt in
let dest = Buffer.create (len + 16) in
let rec doprn i =
if i >= len then begin
let res = Buffer.contents dest in
Buffer.clear dest; (* just in case sprintf is partially applied *)
-> (Obj.magic f res)
end else
...... unchanged

@vicuna
Copy link
Author

vicuna commented Apr 30, 2002

Comment author: administrator

It would be nice to have the ability to create functions akin to
Printf.sprintf
which take multiple arguments, and do something with the resulting string.

This is already done in the current working version of ocaml, although not
exactly with the same type that you are suggesting:

val kprintf : (string -> string) -> ('a, unit, string) format -> 'a
(** [kprintf k format arguments] is the same as [sprintf format arguments],
except that the resulting string is passed as argument to [k]; the
result of [k] is then returned as the result of [kprintf]. *)

Thanks for the suggestion,

-- Damien

@vicuna
Copy link
Author

vicuna commented Apr 30, 2002

Comment author: administrator

Damien Doligez wrote:

This is already done in the current working version of ocaml, although not
exactly with the same type that you are suggesting:

val kprintf : (string -> string) -> ('a, unit, string) format -> 'a
(** [kprintf k format arguments] is the same as [sprintf format arguments],
except that the resulting string is passed as argument to [k]; the
result of [k] is then returned as the result of [kprintf]. *)

Maybe one day I will come up with an original idea!
This does help me in that I no longer need
a separate copy of printf.ml, but it means any function
I create utilising kprintf will return a string, even if
it is side effecting. No choice! Is there any reason why the
continuation cannot be a general consumer of arbitrary
return type?

A slight amendment to the type I proposed (I think the
3rd arg to the format constructor is meant to reflect
the overall return type?)val kprintf : (string -> 'a) -> ('b, unit, 'a) format -> 'b

Cheers,
chris

@vicuna
Copy link
Author

vicuna commented Apr 30, 2002

Comment author: administrator

val kprintf : (string -> 'a) -> ('b, unit, 'a) format -> 'b

This is exactly what I tried at first, but it doesn't work with %a
and %t formats: the typing of these formats is not general enough
to support this version.

Consider this piece of code: kprintf outfun "%a" fmtfun argument
The typing of formats constrains the result of fmtfun to be the same
as 'a (the final result of kprintf). But the result of fmtfun has to be
a string (because kprintf is in fact sprintf in disguise) so 'a has to
be string.

The proper solution would be to add a fourth argument to the "format"
type constructor, but the current solution is good enough and does not
break compatibility with previous versions.

-- Damien

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant