lambda lists

Discussion of Common Lisp
Post Reply
gutzofter
Posts: 10
Joined: Thu Jul 03, 2008 12:53 pm

lambda lists

Post by gutzofter » Tue Dec 16, 2008 9:40 am

As of right now I'm creating my own objects. I also use macros to automatically create those objects. The object is specifically a list composed of properties and their access functions:

Code: Select all

(defun make-obj ()
  (let ((data :my-whatever))
    (list
     :get-data (lambda ()
                 data)
     :set-data (lambda (d)
                 (setf data d)))))

(defun get-data (obj)
  (funcall (getf obj :get-data)))

(defun set-data (obj d)
  (funcall (getf obj :set-data) d))
I use this macro for each item in the property list to create access functions:

Code: Select all

(defmacro make-property (name&args)
  (destructuring-bind (name args) name&args
    (let ((g (gensym)))
      `(progn
         (defun ,(new-symbol (symbol-name name)) (obj ,@args)
           (destructuring-bind ,args (rest ,g)
             (apply (getf obj ,name) (WHAT-GOES-HERE?))))))))
WHAT-GOES-HERE? is the problem. Anybody have any suggestions?

S11001001
Posts: 5
Joined: Tue Sep 30, 2008 9:18 pm
Location: Indiana, USA
Contact:

Re: lambda lists

Post by S11001001 » Wed Dec 17, 2008 4:20 am

I see a reference to ,g, but nothing that is binding it (g is bound in the compilation context, but the gensym created by g is not bound in the runtime context).

More broadly, I can't tell what you want make-property to define. Perhaps you have some usage examples?

Harleqin
Posts: 71
Joined: Wed Dec 17, 2008 5:18 am
Location: Bonn, Germany

Re: lambda lists

Post by Harleqin » Wed Dec 17, 2008 9:12 am

This looks like you are trying to program Java with Lisp syntax. Have a look at defclass, and how accessors are defined in it.

gutzofter
Posts: 10
Joined: Thu Jul 03, 2008 12:53 pm

Re: lambda lists

Post by gutzofter » Wed Dec 17, 2008 12:27 pm

@S11001001

'destructoring-bind' handles lambda-lists (lists with keyword paramters?).

Code: Select all

(destructuring-bind (&key a) '(:a 1123) (print a))
The output:

Code: Select all

1123 1123
The macroexpand-1:

Code: Select all

(LET ((#:WHOLE1043 '(:A 1123)))
  (DECLARE (TYPE LIST #:WHOLE1043))
  (LET* ((#:KEYWORDS-1045 #:WHOLE1043))
    (DECLARE (SB-EXT:MUFFLE-CONDITIONS SB-EXT:CODE-DELETION-NOTE))
    (DECLARE (IGNORABLE #:KEYWORDS-1045))
    (MULTIPLE-VALUE-BIND
        (#:KEY-PROBLEM-1046 #:INFO-1047)
        (SB-KERNEL::VERIFY-KEYWORDS #:KEYWORDS-1045 '(:A) 'NIL)
      (WHEN #:KEY-PROBLEM-1046
        (ERROR 'SB-KERNEL::DEFMACRO-LAMBDA-LIST-BROKEN-KEY-LIST-ERROR
               :KIND 'DESTRUCTURING-BIND :PROBLEM #:KEY-PROBLEM-1046 :INFO
               #:INFO-1047)))
    (LET* ((A
            (IF (SB-KERNEL::KEYWORD-SUPPLIED-P :A #:KEYWORDS-1045)
                (SB-KERNEL::LOOKUP-KEYWORD :A #:KEYWORDS-1045) NIL)))
      (PRINT A))))
So when I do a d-bind on

Code: Select all

(rest ,g)
I'm actually at run-time or the gensym should hold

Code: Select all

(:a 1123)
The reason I think were using

Code: Select all

(rest ,g)
instead of

Code: Select all

,g
is because I stole the example from OnLisp and it is part of creating macros. If you use a keyword parameter &whole it binds the entire form into whole, including the name and to do a rest means you get everything after the name.

gutzofter
Posts: 10
Joined: Thu Jul 03, 2008 12:53 pm

Re: lambda lists

Post by gutzofter » Wed Dec 17, 2008 12:27 pm

@Harleqin

Yes, I would say your right about Java and C#. If you look at my blog you can see some of my experiments with an object framework. I've learned a lot of Lisp because of this. Instead of doing book examples I thought I would get out there.

What I'm driving towards is framework that doesn't use inheritance. Instead of IS-A, drive towards HAS-A coupling and using events/closures for communicating between objects.

It looks like pretty soon I'll abandon my object framework. The underlying implementation is a hack-a-rama, but it is fun figuring out how to implement different functionality.

My Blog is:http://uglylispcode.wordpress.com

gutzofter
Posts: 10
Joined: Thu Jul 03, 2008 12:53 pm

Re: lambda lists

Post by gutzofter » Thu Dec 18, 2008 1:01 am

WooHoo! I did it!

Code: Select all

(defmacro make-prop (name args)
  (let ((g (gensym))
        (r-args (flatten (remove-keywords args))))
    `(progn
       (defun ,name (obj &rest ,g)
         (block ,name
           (destructuring-bind ,args ,g
             (declare (ignorable ,@r-args))
             (apply (getf obj ',name) ,g)))))))
Note this is only REPL tested, not unit tested.

I was even able to silence the warning for the declared variables.

Here is the code to remove keywords from a tree.

Code: Select all

(defun replace-key-args (args)
  (labels ((rka-aux (args is-key-arg?)
             (if (atom args) 
                 args
                 (progn
                   (if (equal '&key (first args))
                       (progn
                         (setf args (rest args))
                         (setf is-key-arg? t)))
                   (cond
                     (is-key-arg?
                      (if (consp (first args))
                          (cons (rka-aux (first args) nil)
                                (if (rest args)
                                    (rka-aux (rest args) nil)))
                          (cons (rka-aux (make-keyword (first args)) nil)
                                (cons (rka-aux (first args) nil)
                                      (if (rest args)
                                          (rka-aux (rest args) t))))))          
                     (t
                      (cons (rka-aux (first args) nil)
                            (if (rest args)
                                (rka-aux (rest args) nil)))))))))
    (rka-aux args nil)))
If somebody wants to refactor it please show me the code.

Post Reply