formatってすげええええぇぇぇぇ
久々のLispの話題。 Common Lispのformatミニ言語の凄さに驚愕する。
SLIMEで使えるformatのcheat sheetってあるかな??
(format nil "~{~a~^, ~}" '(1 2 3)) ; => "1, 2, 3" Floating numbers (format nil "~$" pi) ; => "3.14" (format nil "~@$" pi) ; => "+3.14" (format nil "~5$" pi) ; => "3.14159" (format nil "~v$" 3 pi) ; => "3.142" (format nil "~$" pi) ; => "3.14" (format nil "~2,4$" pi) ; => "0003.14" (format nil "~2,4@$" pi) ; => "+0003.14" (format nil "~#$" pi) ; => "3.1" (format nil "~,5f" pi) ; => "3.142" (format nil "~f" pi) ; => "3.141592653589793" (format nil "~,4f" pi) ; => "3.1416" (format nil "~e" pi) ; => "3.141592653589793d+0" (format nil "~@e" pi) ; => "+3.141592653589793d+0" (format nil "~,4e" pi) ; => "3.1416d+0" Integers (format nil "~d" 1000000) ; => "1000000" (format nil "~:d" 1000000) ; => "1,000,000" (format nil "~@d" 1000000) ; => "+1000000" (format nil "~:@d" 1000000) ; => "+1,000,000" (format nil "~@:d" 1000000) ; => "+1,000,000" (format nil "~12d" 1000000) ; => " 1000000" (format nil "~12,'0d" 1000000) ; => "000001000000" (format nil "~12,'Xd" 1000000) ; => "XXXXX1000000" (format nil "~4,'0d-~2,'0d-~2,'0d" 2005 6 10) ; => "2005-06-10" (format nil "~:d" 100000000) ; => "100,000,000" 3番目のパラメータは桁の間に入れる文字、4番目は入れる間隔 (format nil "~,,'.,4:d" 100000000) ; => "1.0000.0000" 日本人には4桁ごとにコンマを入れると読みやすいよね (format nil "~,,,4:d" 100000000) ; => "1,0000,0000" (format nil "~d = 0x~x, 0~o, 0b~b" 255 255 255 255) ; => "255 = 0xFF, 0377, 0b11111111" (format nil "~r" 1234) ; => "one thousand two hundred thirty-four" (format nil "~:r" 1234) ; => "one thousand two hundred thirty-fourth" Roman numeral (format nil "~@r" 1234) ; => "MCCXXXIV" old-style Roman numeral (format nil "~:@r" 1234) ; => "MCCXXXIIII" plural (s) (format nil "file~p" 1) ; => "file" (format nil "file~p" 10) ; => "files" (format nil "file~p" 0) ; => "files" ありゃ?不規則変化には対応していない。 (format nil "child~p" 10) ; => "childs" 直前のdirectiveにかかる (format nil "~r file~:p" 10) ; => "ten files" plural (y/ies) (format nil "~r famil~:@p" 10) ; => "ten families" (format nil "The value is: ~a" 10) ; => "The value is: 10" (format nil "The value is: ~a" "foo") ; => "The value is: foo" (format nil "The value is: ~a" (list 1 2 3)) ; => "The value is: (1 2 3)" (format nil "The value is: ~s" "foo") ; => "The value is: \"foo\"" (char-code (elt (format nil "~%") 0)) ; => 10 ~% newline, ~& fresh line (list (format nil "~~") (format nil "~10~")) ; => ("~" "~~~~~~~~~~") ~:c スペースなどを言葉で表記 ~@c S式表記 (format nil "~c/~:c/~@c/~S" #\a #\a #\a #\a) ; => "a/a/#\\a/#\\a" (format nil "~c/~:c/~@c/~S" #\Space #\Space #\Space #\Space) ; => " /Space/#\\ /#\\ " ~:@c for lisp machines (format nil "~:@c" (code-char 0)) ; => "Nul" downcase (format nil "~(~a~)" "tHe Quick BROWN foX") ==> "the quick brown fox" capitalize (format nil "~@(~a~)" "tHe Quick BROWN foX") ==> "The quick brown fox" capitalize words (format nil "~:(~a~)" "tHe Quick BROWN foX") ==> "The Quick Brown Fox" upcase (format nil "~:@(~a~)" "tHe Quick BROWN foX") ==> "THE QUICK BROWN FOX" ~[ ~] conditional formatting (format nil "~[cero~;uno~;dos~]" 0) ; => "cero" (format nil "~[cero~;uno~;dos~]" 1) ; => "uno" (format nil "~[cero~;uno~;dos~]" 2) ; => "dos" (format nil "~[cero~;uno~;dos~]" 3) ; => "" 0 1 2 ~:; default clause (format nil "~[cero~;uno~;dos~:;mucho~]" 3) ; => "mucho" (format nil "~[cero~;uno~;dos~:;mucho~]" 100) ; => "mucho" 0 1 2 else a prefix parameter of # will be evaluated as the number of remaining format arguments. (defparameter *list-etc* "~#[NONE~;~a~;~a and ~a~:;~a, ~a~]~#[~; and ~a~:;, ~a, etc~].") 0 1 2 else 0 1 else (format nil *list-etc*) ; => "NONE." (format nil *list-etc* 'a) ; => "A." (format nil *list-etc* 'a 'b) ; => "A and B." (format nil *list-etc* 'a 'b 'c) ; => "A, B and C." (format nil *list-etc* 'a 'b 'c 'd) ; => "A, B, C, etc." (format nil *list-etc* 'a 'b 'c 'd 'e) ; => "A, B, C, etc." ~:[nil~;otherwise~] (let ((test-result nil)) (format nil "~:[FAIL~;pass~]" test-result)) ; => "FAIL" (let ((test-result 999)) (format nil "~:[FAIL~;pass~]" test-result)) ; => "pass" ~@[if TRUE~] (format nil "~@[x = ~a ~]~@[y = ~a~]" 10 20) ; => "x = 10 y = 20" (format nil "~@[x = ~a ~]~@[y = ~a~]" 10 nil) ; => "x = 10 " (format nil "~@[x = ~a ~]~@[y = ~a~]" nil 20) ; => "y = 20" (format nil "~@[x = ~a ~]~@[y = ~a~]" nil nil) ; => "" ~{ ~} iteration (format nil "~{~a, ~}" (list 1 2 3)) ; => "1, 2, 3, " ~^ stop iteration on last element (format nil "~{~a~^, ~}" (list 1 2 3)) ; => "1, 2, 3" ~@{ ~} (format nil "~@{~a~^, ~}" 1 2 3) ; => "1, 2, 3" ~{ ~} 中の#はリストの残り要素を参照する (format nil "~{~a~#[~;, and ~:;, ~]~}" (list 1 2 3)) ; => "1, 2, and 3" (format nil "~{~a~#[~;, and ~:;, ~]~}" (list 1 2)) ; => "1, and 2" (defparameter *english-list* "~{~#[~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~}") 0 1 2 3+ (format nil *english-list* '()) ; => "" (format nil *english-list* '(1)) ; => "1" (format nil *english-list* '(1 2)) ; => "1 and 2" (format nil *english-list* '(1 2 3)) ; => "1, 2, and 3" (format nil *english-list* '(1 2 3 4)) ; => "1, 2, 3, and 4" ~: do iteration at least once (defparameter *english-list* "~{~#[<empty>~;~a~;~a and ~a~:;~@{~a~#[~;, and ~:;, ~]~}~]~:}") (format nil *english-list* '()) ; => "<empty>" (format nil *english-list* '(1 2 3 4)) ; => "1, 2, 3, and 4" ~* skip an argument (format nil "~a, ~*~a" 1 2 3) ; => "1, 3" ~:* reuse an argument (format nil "~r ~:*(~d)" 1) ; => "one (1)" (format nil "I saw ~r el~:*~[ves~;f~:;ves~]." 0) ; => "I saw zero elves." (format nil "I saw ~r el~:*~[ves~;f~:;ves~]." 1) ; => "I saw one elf." (format nil "I saw ~r el~:*~[ves~;f~:;ves~]." 2) ; => "I saw two elves." (format nil "I saw ~[no~:;~:*~r~] el~:*~[ves~;f~:;ves~]." 0) ; => "I saw no elves." ~{の中では~*や~:*はリストの要素を前後する。 (format nil "~{~s~*~^ ~}" '(:a 10 :b 20)) ; => ":A :B" ~2* 2つ飛ばす (format nil "~a~2*~a" 1 2 3 4) ; => "14" ~2:* 2つ前 (format nil "~a~a~a~a~2:*~a" 1 2 3 4) ; => "12343" ~2@* 2番目(0-origin) (format nil "~a~2@*~a" 1 2 3 4) ; => "13"