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))))
arg
、setarg
の引数は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