Monday 29 January 2007

Format

Format is one of those features in Common Lisp that people seem to have a love/hate relationship with, the other being loop. Both have their own mini languages that are not especially lispy. I'm still not too sure where I stand in this debate but being able to say things like this is still pretty incredible.




(defun print-diamond (str x &optional c a (max (1+ x)) (star "*"))
(format str "~&~[~:;~:*~vT~v@{~A ~:*~}~3@*~v,v/print-diamond/~:*~v[~:;~@*~vT~v@{~A ~:*~}~%~]~]"
x (- max x) star max star (1- x)))


Now for an explanation of that format string.
Bear with me this is hairy.


  • ~& : Conditional newline (insert newline if we aren't at the start of a line)

  • ~[ : Process the nth clause (seperated by ~:). ~:; specifies a default clause. This consumes the argument x. This directive causes print-diamond to stop processing when x is zero.

    • ~:* : Backup 1 argument (unconsumes the argument x)

    • ~vT : Insert arg number of spaces (this reconsumes the first argument ie. x)

    • ~v@{ : Iterate v times, v is (- max x).

      • ~A : Print 1 element

      • ~:* : Backup 1 element (The effects of the last 3 directives is to print star (- max x) times)

    • ~} : End loop

    • ~3@ : Move to the 3rd argument (star)

    • ~v,v/print-diamond/ : The recursive call. invoke print-diamond again with max, star and (1- x), This is equivalent to calling (print-diamond stream (1- x) nil nil max star)

    • ~:* : Backup 1 argument (unconsumes (1- x))

    • ~v[ : Conditional processing based (1- x).

      • ~@* : Go to the start of the argument list.

      • ~vT : Insert arg number of spaces (this consumes the first argument again)

      • ~v@{ : Iterate v times, v is (- max x).

        • ~A : Print 1 element

        • ~:* : Backup 1 element (The effects of the last 3 directives is to print star (- max x) times)

      • ~} : End loop

      • ~% : Insert a new line

    • ~] : End conditional processing

  • ~] End conditional processing




Whew, brain freeze.

now we can do (print-diamond t 10)

*
* *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * *
* * * * * * * * * *
* * * * * * * * *
* * * * * * * *
* * * * * * *
* * * * * *
* * * * *
* * * *
* * *
* *
*

No comments: