(rontolisp) docs

関数名前空間

rontolispはCommon Lispに倣った Lisp-2 です。関数と変数は別々の名前空間に存在します。

  • 裸のシンボルは 変数 として評価されます。car 単独の評価はエラーです(インタプリタでは The variable car is unbound、コンパイラではコンパイルエラー)。
  • 呼び出し位置 (f args...) のシンボルは関数名前空間のみで解決されます。car という名前の変数が関数 car をシャドウすることはありません。(let ((car 5)) (car (list car 2)))5 を返します。
  • 関数は #'name((function name) のリーダ構文)、#'(lambda ...)(symbol-function 'name) を通じて になります。これは組み込み演算子(#'+, #'car, #'1+, #'cadr)、ユーザ定義の defun、ラムダで機能します。
  • funcall/mapcar/reduce は関数を指す シンボル(関数指定子)も受け付けます。(funcall 'car '(1 2))1 を返します。コンパイラはシンボルが引用されたリテラルである場合にこれをサポートします。
  • defun は関数名前空間に定義し、関数名を返します。(setq f (lambda ...))変数 を関数値に束縛します。これは (f ...) ではなく (funcall f ...) で呼び出します。
  • マクロまたは特殊演算子の #'(例: #'if, #'defun)はエラーです。

関数値は、3つの実行モードすべてで、引数として渡したり、関数から返したり、データ構造に格納したりできます。

高階関数:

クロージャ(参照によるキャプチャ):

引数としてのラムダ:

第一級の値としての組み込み演算子:

+, car, 1+ のような組み込み演算子は #' を通じて高階関数に渡せます:

コンパイラの制限。 JVM/WASMコンパイラでは、#'name はコンパイル時に判明している関数(ユーザ定義の defun と組み込み演算子)に対して解決されます。#'mapcar#'reduce#'apply#'funcall 自体は値として利用できません(#'mapcan#'sort は利用できます)。symbol-function は引用されたシンボルリテラルの引数を要求します。--dynamic モードでは、未解決の #'name は他の未解決参照と同様にランタイムの eval 環境に委ねられます。コンパイルされたコードでは、apply/funcall は各組み込み演算子のために合成された固定アリティのラッパーに対して、実際の引数の数でディスパッチします。本来可変長の演算子 -- +-*/listminmax -- には可変長ラッパーがあるため、(funcall #'+ 1 2 3)(apply #'list ...) などは任意の引数の数を受け取ります。それ以外の複数引数の組み込みは固定アリティのラッパーのままです。#'cons#'append#'gcd や比較チェイン(#'<#'=、...)は 2 引数なので、異なる数に適用することはコンパイルパスではサポートされません( コンパイルされた eval の制限 に一致します)。それ以外のアリティにはユーザ定義関数か lambda を使ってください。インタプリタにはそのような制限はありません。