Avoiding funcall in a Lisp-2

Whatever is on your mind, whether Lisp related or not.
Post Reply
huangho
Posts: 3
Joined: Fri Sep 03, 2010 5:15 pm
Location: Porto Alegre, Brazil
Contact:

Avoiding funcall in a Lisp-2

Post by huangho » Fri Jun 17, 2011 10:43 am

Hello!

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)))))
Here is an implementation for lambda and defun (there are other lambda-list-using forms that would have to be covered, of course):

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)
One problem with this is that it makes it impossible to have an optional parameter named 'function' and specify a default value (since #'foo expands to (function foo)). It could be extended to work with let too (but similarly it might not interact very well with the (let (x y z) ...) form); this would unify let and flet. What do you think?

Post Reply