William Bland ([info]abstractstuff) wrote,
@ 2007-07-25 09:08:00
Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Entry tags:clutu, computers, lisp

FORMAT is awesome
I love Common Lisp's FORMAT.

Here's a snippet of code from the crossword site I've been working on. This gets invoked after you press the "check" button and clutu has identified any words that are filled-in wrong:

(push (list "clutu"
	    (if wrong
		(format nil "~{~#[~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~} ~[is~:;are~] wrong"
			(reverse wrong)
			(1- (length wrong)))
		"everything is ok"))
      (chat-of game))


It produces output (in the chat pane) like "clutu: 13 across and 4 down are wrong".

I think I started by grabbing an example from Peter's book.

Format is one of the things that looked scary when I first came to Common Lisp, but now I hate to do without when I'm using some lesser language.


(Post a new comment)

?!?
(Anonymous)
2007-07-25 07:32 pm UTC (link)
What on earth is that format string? It has all this complexity and code around it to catch most of the cases it deals with.

(Reply to this)(Thread)

Re: ?!?
[info]abstractstuff
2007-07-25 08:27 pm UTC (link)
Turns out it's actually almost verbatim from Peter's book, where he describes pretty clearly what each bit does:

From

http://gigamonkeys.com/book/a-few-format-recipes.html#iteration

We end up with:

(defparameter *english-list*
"~{~#[~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~}")


My version just has the "is/are" piece tacked on at the end.

(Reply to this)(Parent)

just my 2 cents
[info]laurent_atl
2007-07-25 07:36 pm UTC (link)
i am not sure you will be able to convince many people that constructs like ~a~:;~@{~a~#[~;, are awesome

(Reply to this)(Thread)

Re: just my 2 cents
(Anonymous)
2007-07-25 07:42 pm UTC (link)
well...

});for(;i<l;i++){ isn't that awesome either... to take a random snippet of characters from bits and pieces of distinct syntactic forms in another language...

(Reply to this)(Parent)

also...
(Anonymous)
2007-07-25 07:38 pm UTC (link)
it's done better in the language specification :)

Section 22.3.7.2:

(setq foo "Items:~#[ none~; ~S~; ~S and ~S~
~:;~@{~#[~; and~] ~S~^ ,~}~].")
(format nil foo) => "Items: none."
(format nil foo 'foo) => "Items: FOO."
(format nil foo 'foo 'bar) => "Items: FOO and BAR."
(format nil foo 'foo 'bar 'baz) => "Items: FOO, BAR, and BAZ."
(format nil foo 'foo 'bar 'baz 'quux) => "Items: FOO, BAR, BAZ, and QUUX."


A few tweaks to that and you're all set.

the is/are part is better done as ~:*~#[is~:;are~] and then you don't even need to pass the second arg to the function.

(Reply to this)(Thread)

yes quite conscice
(Anonymous)
2007-07-26 02:12 am UTC (link)
format str = "Items: " ++ format' (words str) ++ "."
where format' str = case str of
[] -> "none"
[x] -> x
(x:xs) -> x ++ ", " ++ format' xs

--haskell.

(Reply to this)(Parent)

yes quite concise
(Anonymous)
2007-07-26 02:13 am UTC (link)
format str = "Items: " ++ format' (words str) ++ "."
where format' str = case str of
[] -> "none"
[x] -> x
(x:xs) -> x ++ ", " ++ format' xs

--haskell.

(Reply to this)(Parent)(Thread)

Re: yes quite concise
(Anonymous)
2007-07-26 03:15 am UTC (link)
Well, that's not quite the same. Just for grins, can you show how you'd emit the same output as the lisp which would be:

()        -> "Everything is ok"
(x)       -> "x is wrong"
(x y)     -> "x and y are wrong"
(x y z)   -> "x, y, and z are wrong"
(x y z a) -> "x, y, z, and a are wrong"


etc.

-Peter

-Peter

(Reply to this)(Parent)

Re: yes quite concise
(Anonymous)
2007-07-31 09:37 pm UTC (link)
Not only is that not equivalent, it's longer than the way after getting rid of the excess code.

(Reply to this)(Parent)


(Anonymous)
2007-07-26 03:09 am UTC (link)
Seems like you can replace the whole IF expression with this:

(format t "~{~#[Everything is ok~;~a~;~a and ~a~:;~@{~#[~;and ~a~:;~a, ~]~}~]~:}~:*~1{~#[~; is wrong~:; are wrong~]~}" (reverse wrong))

-Peter

(Reply to this)(Thread)


[info]abstractstuff
2007-07-26 09:30 pm UTC (link)
Even better, thanks Peter.

(Reply to this)(Parent)


Create an Account
Forgot your login?
Login w/ OpenID
English • Español • Deutsch • Русский…