CodeIQに以下のような問が出題されていた、と最近知りました。
標準出力に
Hello World
と出力するプログラムを作成して下さい。
ただし、数値、文字及び文字列リテラルを解答に含めることはできません。(中略)
言語仕様をフル活用して下さい!
http://codeiq.hatenablog.com/entry/2013/09/25/163547 より抜粋
この問題をCommon Lispで解答してみます。
一行解答
(princ '|Hello World|)
;-> Hello World
シンボルは、数値でも文字でも文字列でもないので、要件は満たしています。
ですが、なんだか安直すぎて、あまりおもしろくありません。
そこで、言語仕様の中に何かいいものはないか、探してみました。
言語仕様を活用した解答
(let ((*print-case* :capitalize))
(princ 'hello)
(princ '| |)
(princ 'world))
;-> Hello World
Common Lispには*print-case*
という大域変数がありました。
この値を変更することにより、シンボルの出力活字ケースを変更することができます。
取り得る値は、キーワードで、:upcase
、:downcase
、:capitalize
のいずれかです。
デフォルト値は:upcase
です。
(let ((*print-case* :downcase))
(princ 'I-AM-A-BIG-MAN))
;-> i-am-a-big-man
言語仕様を活用した、上述の解答でも、やはりシンボルを使用しています。
シンボルの使用は要件に違反していませんが、なんだか(他の言語に対して)ズルっこしているような気分になりました。
そこで、私は「Lispの本質とは何か?」、深く深く自問自答し、ついに次の解答に辿り着きました。
Lispっぽい解答
Lispと言えば、「再帰」と「大量のカッコ」。
これらの概念を高次に融合したLisp的解答が以下のものです!
しかしながら、ここに載せるにはいささか刺激が強すぎますので、アルミホイルキャップをかぶってリンク先のシェルスクリプトを見てみてください。
このシェルスクリプトは、自分自身を読み込み(再帰的!)、カッコのネストの深さ(大量のカッコ!)で文字コードを表しています。
一行目をコメントアウトすれば、CL-REPLから (load "hello-world.lisp")
でも実行できるはずです。
Lispっぽいでしょ。
この文章を書くにあたり、以下のリンク先を参考にさせてもらいました。
athosさんのclojureの解答
深町さんのマクロを使用した解答
スズキさんの解答
HyperSpec: *print-case*