Here's an idea.

Tyson Richard DOWD trd at cs.mu.oz.au
Thu Sep 4 21:47:33 AEST 1997


Anyone interested in having something like this added to the standard
library? I was just trying it out for novelty value, but it's actually
quite usable, which was a little unexpected.

%----------------------------------------------------------------------------

%
% A cute use of heterogenous lists, dynamic type-checking (using
% univ_to_type) and overloading of '.'.
%
% Instead of
%
% 	string__format("%d %d %f %s\n", [i(3), i(4), f(2.5), s("foo")], Str) 
%
% we can can do 
%
% 	sprintf("%d %d %f %s\n", [3, 4, 2.5, "foo"], Str) 
%
% In fact, there's no need for string__poly_type (although this code
% just converts to it for simplicity).
%
% Unfortunately, overloading '.' like this causes problems - even
% [1,2,3] has two possible types. So you should put the '.' function
% in a module, then "use" it instead of "importing" it, and put a module
% qualifier before the list, eg:
%
% 	sprintf("%d %d %f %s\n", modulename:[3, 4, 2.5, "foo"], Str) 
%
% Of course this removes some of the terseness of the code, but there's
% still a lot less parentheses to type...

:- module sprintf.

:- interface.

:- import_module io.

:- pred main(io__state, io__state).
:- mode main(di, uo) is det.

%----------------------------------------------------------------------------

:- implementation.

:- import_module require, string, list, std_util.

main -->
	{ sprintf("%d %f %s %c\n", [20, 5.3, "foo", 'c'], Str) },
	io__write_string(Str),
		% And if you're going to use lists in the same
		% namespace, you'll need to do something list this...
	io__write(list:[1,2,3]), 
	io__nl.


%----------------------------------------------------------------------------

	% Build a list of univs.

:- func sprintf:'.'(T, list(univ)) = (list(univ)).
:- mode sprintf:'.'(in, in) = (out) is det.

'.'(A, Xs) = list:'.'(univ(A),Xs).

	% Use string__format to format the string.

:- pred sprintf__sprintf(string, list(univ), string).
:- mode sprintf__sprintf(in, in, out) is det.

sprintf__sprintf(FormatStr, UnivList, FinalStr) :-
	list__map(sprintf__univ_to_string_poly, UnivList, PolyList),
	string__format(FormatStr, PolyList, FinalStr).

	% Convert a univ to a string_poly.

:- pred sprintf__univ_to_string_poly(univ, string__poly_type).
:- mode sprintf__univ_to_string_poly(in, out) is det.

sprintf__univ_to_string_poly(Univ, Poly) :-
	( univ_to_type(Univ, Float) ->
		Poly = f(Float)
	; univ_to_type(Univ, Int) ->
		Poly = i(Int)
	; univ_to_type(Univ, String) ->
		Poly = s(String)
	; univ_to_type(Univ, Char) ->
		Poly = c(Char)
	;
		error("unable to convert univ to string__poly_type")
	).

-- 
       Tyson Dowd           #          Another great idea from the 
                            #            people who brought you
      trd at .cs.mu.oz.au      #               Beer Milkshakes!
http://www.cs.mu.oz.au/~trd #	         Confidence --- Red Dwarf



More information about the developers mailing list