#:g1: LEXPRの定義構文を作ってみよう

Posted 2022-03-04 03:03:07 GMT

特に何があったというわけでもないですが、lexprの構文が作りたくなったので作ってみました。
そもそも、LEXPRとは何かですが、引数をリストで受け取り中で分解して参照するような仕組みです。 MACLISP系統のMACLISP、Lisp machine Lisp、Franz Lispで使えますが、Common Lispが登場する頃にはより柔軟なλリストキーワードの方式が登場していたためか、可変長引数に対応するだけのLEXPRは取り入れられませんでした。

(defpackage lexpr
  (:use)
  (:export defun arg setarg listify))

(defmacro lexpr:defun (name argn &body body) (let ((args (gensym "args"))) `(defun ,name (&rest ,args &aux (,argn (length ,args))) (declare (ignorable ,argn)) (flet ((lexpr:arg (pos) (declare (type list ,args)) (elt ,args (1- pos))) (lexpr:setarg (pos val) (declare (type list ,args)) (setf (elt ,args (1- pos)) val)) (lexpr:listify (n) (if (minusp n) (last ,args (- n)) (subseq ,args 0 n)))) (declare (inline lexpr:arg lexpr:setarg lexpr:listify)) ,@body))))

argsetargの引数は1オリジンなので注意が必要

(lexpr:defun plus args
  (lexpr:setarg 1 (* 2 (lexpr:arg 1)))
  (lexpr:setarg 2 (* 2 (lexpr:arg 2)))
  (print (lexpr:listify -3))
  (+ (lexpr:arg 1) (lexpr:arg 2)))

(plus 1 1 1 2 2 2 2 'l 'a 's 't)
>> (a s t)
→ 4

(lexpr:defun print-no-of-arguments n
  (princ "Number of arguments supplied: ")
  (princ n)
  (terpri))

(print-no-of-arguments 'x 'y 'z)
>> Number of arguments supplied: 3
→ nil

(lexpr:defun power n
  (expt (lexpr:arg 1)
        (cond ((> n 1) (lexpr:arg 2))
              (T 2))))

(power 3)
→ 9

(power 3 4) → 81

まとめ

LEXPRの定義構文を真似てみました。 思えば、Unixのシェルスクリプトの$1$2あたりと似ていますね。


HTML generated by 3bmd in LispWorks 8.0.0

comments powered by Disqus