On Dec 27, 2003, at 11:37 PM, Alex Shinn wrote: > The SRFI process isn't just about porting, but also standardizing > libraries. One of the primary motivations of SRFI-1 was that all > Schemes provided varying levels of add-on list utilities with > incompatible API's. It's also about getting together and producing something _better_ than what J. Random Schemer or Common Lisper thought up a while ago. Remember FLUID-LET? -- there was once a SRFI about it, but it was ditched because there were several arguments about why it was a bad idea, and better ideas. (Actually, I disagree with the design of SRFI 39 (parameters), too, which could be considered to be one of those better ideas, but that's a different story and not really relevant here.) Likewise, if there are good arguments against format strings, and there are good alternative ideas, why should you let yourself be held down by the old and historically motivated idea? I don't claim that LAMBDA: The Ultimate Formatter is necessarily the best idea -- just as I don't think SRFI 39 is the best idea in the related set of ideas regarding fluid variables --, but I think it's a better idea nevertheless. > In this case almost all Schemes at least support > SRFI-28, and many support some or all of the full Common-Lisp format, > so it is definitely something people find useful and should be > standardized. Many people feel SRFI-48 doesn't go far enough, so > there will likely be at least one more format SRFI. Perhaps that will > explicitly make the individual formatting procedures accessible as > they are in Dirk Lutzebaeck's implementation, which would give you the > option of using both styles. Of course, and FLUID-LET is easily implemented and available in lots of places. But that does not make it a _good_ thing. Likewise, formatting strings are easily implemented and available in lots of places; indeed, there are portable implementations for full Common Lisp FORMAT. But CL FORMAT isn't necessarily a good thing. >> Possibly something along the lines of simply adopting the notion that: >> (str-fmt ....) [or (string ...) be extended] to accept mixed string, >> symbol, >> character and numerical arguments, and produces a string resulting >> from the >> concatenation of its argument's string equivalences > > Probably best not to overload string, especially in light of recent > discussions as to just what a character is. Also, the procedure > should definitely output to a port, not a string. But even using a > port this becomes inefficient if you inline write's: > > (define (write-to-string x) (with-output-to-string (cut write x))) > (fmt #t "list: " (write-to-string ls) #\newline) > > and likewise for performing different number->string conversions in > the middle of a format. 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) (Assuming the continuations that SHIFT lets you nab are n-ary. It may also be better to use BSHIFT & BRESET, but that's diverging from this SRFI.) This doesn't force you to cons up intermediate strings or even intermediate output ports with a specialized character writer. (One might debate about the efficiency of SHIFT & RESET, which I don't want to right now, as it's utterly beside the point.) > You really have to break it apart as: > > (display "list: ") > (write ls) > (newline) > > which when compared with > > (format #t "list: ~S\n" ls) > > looks clumsy and verbose, especially when you have many of these > throughout a program almost tripling the number of lines, and > especially when you have to wrap them in begins. Format is very > concise If we cared that much about conciseness, we'd all be using Perl or GOO. But we don't care _that_ much. > 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. > (even in an > eval-less Scheme) and lets you load it from things like config files. 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. > Consider the log files of a server that need to produce customizable > output, like this from my httpd.conf: > > LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" > \"%{User-Agent}i\" %T %v" full > > Or consider the Emacs mode-line-format string which lets you customize > (again at runtime) what appears in your mode-line. Of course, Emacs > allows nested lists as the format, which may be a consideration for > future format SRFIs rather than consider introducing artificial > nesting with ~<...~> etc. Formatter procedures can easily be arbitrarily nested however you like. > By keeping the logic in one place format is also much better suited to > things like i18n, and can provide more efficient control over > columnating and padding. 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?). Column & padding control are especially easy when you've got full Scheme at your fingertips with which to write formatting routines. It would be trivial to write a FORMAT/PADDING routine that would keep track of the columns that the sub-formatters write. > All around, format is more consice [sic], more efficient, and more > flexible > than the alternatives. That doesn't mean we couldn't use some more > functional interfaces, but they will likely not replace format. Concise [sic], I concede; but do you really want _that_ much conciseness? I'd say no, or, as I said, we'd all be using Perl or GOO. (OK, that's a bit of an overstatement, but you get the idea.) > -- > Alex >