男は男らしく

(単なる余興で冗談です)
Maximaを通じてLISPの柔軟性を感じることができました。となると私にとって、LISPの欠点は、ただ2点。

  1. 関数型なのに関数に見えなくてリストに見える。しかも(で始まって、女々しい。
  2. UNIXのコマンドと同じくらい、関数名に省略形が多い。

結局、この2点が最初の大きな障壁となって、LISPプログラマ人口を増えなくしているように思えます。2点目の課題は時間をかけて解決するしないですが、1点目はプリプロセッサで解決可能と思って、なぜかMaximaで作りました。題して、「男は男らしく、関数は関数らしく」

preprocessor(file) :=
block(
  [rs, ws, line, c, prefetch],
  rs : openr(file),
  ws : openw(concat(file, ".lisp")),
  do (
    line : readline(rs),
    prefetch : "",
    if line = false then return(),
    for c in charlist(line) do (
      if (constituent(c) = false) or (c = "'") then (
        printf(ws, concat(prefetch, c)),
        prefetch : "")
      elseif c = "(" then
        if slength(prefetch) = 0 then printf(ws, c)
        else (
          printf(ws, concat(c, prefetch, " ")),
          prefetch : "")
      else
      prefetch : concat(prefetch, c)),
    printf(ws, concat(prefetch, "~%"))),
  close(ws),
  close(rs)
  )$

このプリプロセッサを通すと、とっても関数らしい以下のコードが、疑似LISPのコードになります。

defun(Fibonacci (n) 
  cond(
    (or(equal(n 1) equal(n 2)) 1)
    (true plus(Fibonacci(minus(n 1)) Fibonacci(minus(n 2))))))

(defun Fibonacci (n) 
  (cond 
    ((or (equal n 1) (equal n 2)) 1)
    (true (plus (Fibonacci (minus n 1)) (Fibonacci (minus n 2))))))

余興以上にするにはパースツリーを実装して二項演算子にまで踏み込まないといけないが、このページは「それを書くには狭すぎる。」
本当はこう書きたい。

define(Fibonacci (n) 
  condition(
    (((n=1) or (n=2)) 1)
    (true (Fibonacci(n-1)+Fibonacci(n-2)))))

上のプリプロセッサは単なるフォーマッタで、何ら意味を変えていないので、フォーマット前の表現もLISPだと言えますが、二項演算子を導入すると、演算子を評価する直前に関数化する必要があって、アトムやリストの意味が変わってしまいます。ここでLISPじゃなくなるんでしょうね。MaximaLISPの拡張ではなくて、LISPで実装した別言語だと頷けます。