Today I had an idea to reduce the need for funcall in a Lisp-2: allowing some parameters of a lambda-list to be bound in the function namespace. So you could write, for example:
Code: Select all
(defun map (#'fun ls)
(if (null ls)
nil
(cons (fun (first ls))
(map #'fun (rest ls)))))
Code: Select all
(defpackage :sharpquoteful-lisp
(:use :common-lisp)
(:shadow :lambda :defun)
(:export :lambda :defun))
(in-package :sharpquoteful-lisp)
(cl:defun function-form-p (x)
(and (consp x)
(eq (car x) 'function)))
(defmacro lambda (args &body body)
(let ((args-g (gensym))
(arg-alist (mapcan
(cl:lambda (arg)
(cond ((function-form-p arg)
(list (cons arg (gensym))))
((and (consp arg) (function-form-p (car arg)))
(list (cons (car arg) (gensym))))
(t nil)))
args)))
`(cl:lambda ,(sublis arg-alist args)
(cl:flet (,@(mapcar (cl:lambda (pair)
`(,(cadar pair) (&rest ,args-g)
(apply ,(cdr pair) ,args-g)))
arg-alist))
,@body))))
(cl:defmacro defun (name args &rest body)
`(setf (symbol-function ',name) (lambda ,args ,@body)))
;; Examples.
(shadow 'map)
(defun map (#'fun ls)
(if (null ls)
nil
(cons (fun (first ls))
(map #'fun (rest ls)))))
(defun hack (ls &optional (#'act #'print))
(dolist (i ls)
(act i)))
(print (map #'sqrt '(1 2 3 4 5)))
(hack '(1 2 3 4 5))
(hack '(1 2 3 4 5) #'princ)