[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Format strings are wrong
On Dec 28, 2003, at 9:34 PM, Alex Shinn wrote:
Personally I think there are a lot of things that should be done
different from CL FORMAT, including the already discussed ~P and ~C.
That doesn't make FORMAT a bad thing either.
That doesn't make a modified CL FORMAT a good thing, either. The basic
concept
remains the same, and there are people who don't like that basic
concept.
Formatter procedures can work any way you like; all you need is to
pass some different WRITE-CHAR procedure, which allows for even more
expressiveness. For instance, you could use SHIFT & RESET to generate
a stream from FORMATTER:
(reset
(format FORMATTER
(lambda (char) (shift k (stream-cons char (k)))))
stream-null)
You can do this with CL format too.
Pray demonstrate. (Assume the existence of SHIFT & RESET in CL.)
Or just FORMATTER.
?
To avoid
confusion in the discussion, can you use a different name than format?
fmt works, as does funcall (since that's what it is).
How about LAMBDA-FORMAT?
If we cared that much about conciseness, we'd all be using Perl or
GOO. But we don't care _that_ much.
It has it's place though, and if in a quick script I can save typing
four lines by writing a single short format I will.
Sure, it has its place. I use CL-style FORMAT in lots of quick hacks,
debug
messages, and things like that. But I never go beyond SRFI 28 in those
quite
limited circumstances, and anyways, for a good formatting SRFI, I'd
prefer to
have a good formatting mechanism (even if it be not LAMBDA-FORMAT; I
merely
offer LAMBDA-FORMAT as a potential alternative) to a misshapen
derivative of
CL-style FORMAT, just as I'd rather have a good fluid variable system,
even if
it be something I don't believe is optimal -- SRFI 39 --, than have a
bad, but
historically motivated and occasionally convenient for quick hacks,
FLUID-LET
mechanism based on DYNAMIC-WIND + SET!.
In a larger
application I'm more likely to want to use a (localized) format rule
which I will grab from a config file. As such, I generally consider
(begin
(display ...)
(write ...)
(display ...)
(newline))
to be bad style in both cases.
But is CL FORMAT good style? In config file formatting things, I'd
imagine
that string interpolation would be more useful and clearer than either
one.
and not only lets you re-use the format string in parts of
your program, it lets you easily change it at runtime
The same can be said about formatter procedures.
You can only choose from pre-defined formatter procedures, that's a
whole world of difference.
I'm sorry, but I don't understand how you draw this conclusion, or how
it's any
different from CL FORMAT. Could you elaborate, please?
But what you're really doing there is just creating a very limited
language for formatting; it's equivalent to having a very limited
EVAL. Why not use EVAL? You could even write an incredibly simple
EVAL that supports only LAMBDA, function application, and the built-in
formatters.
Because eval is evil.
Oh, please. In most circumstances, yes, EVAL is evil, but when you
actually
are _evaluating_language_, there's no reason to consider it evil; it's
exactly
what you're doing, whatever name it have.
Because restricted languages are easier to
verify
and easier to optimize.
Let me quote myself:
You could even write an incredibly simple
EVAL that supports only LAMBDA, function application, and the built-in
formatters.
That looks to me like a restricted language that's pretty damn easy to
verify.
Formatter procedures can easily be arbitrarily nested however you
like.
As can format strings, as can format lists.
Right. So you while LAMBDA-FORMAT has no advantage here, neither does
CL
FORMAT.
And you don't need to remember obscure formatting directive syntax
with obscure single-character main names and strange syntax to go
around it (SRFI 29's ~@*, anyone?).
So use longer names. There's no reason format has to use ~X instead of
~NAME~. Or some combination of both styles.
Er, please tell me how these differ significantly:
(format #t
"~STRING~ my-local-variable = ~WRITE~; other-variable =
~WRITE~~NEWLINE~"
debug-header
my-local-variable
other-variable)
(format/port (sequence-formatter debug-header " my-local-variable = "
(write-formatter my-local-variable)
"; other-variable = " (write-formatter other-variable)
(char-formatter #\newline)))
(Yes, that would require a trivial change to SEQUENCE-FORMATTER for
implicitly
creating string formatters given string arguments.)
Much of your argument has been about conciseness; by extending the
names of
the formatting routines, you're going to lose a lot of that.