Page 1 of 1

lambda lists

PostPosted: Tue Dec 16, 2008 9:40 am
by gutzofter
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))
     :get-data (lambda ()
     :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)))
         (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?

Re: lambda lists

PostPosted: Wed Dec 17, 2008 4:20 am
by S11001001
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?

Re: lambda lists

PostPosted: Wed Dec 17, 2008 9:12 am
by Harleqin
This looks like you are trying to program Java with Lisp syntax. Have a look at defclass, and how accessors are defined in it.

Re: lambda lists

PostPosted: Wed Dec 17, 2008 12:27 pm
by gutzofter

'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)))
  (LET* ((#:KEYWORDS-1045 #:WHOLE1043))
        (#:KEY-PROBLEM-1046 #:INFO-1047)
      (WHEN #:KEY-PROBLEM-1046
    (LET* ((A
                (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

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.

Re: lambda lists

PostPosted: Wed Dec 17, 2008 12:27 pm
by gutzofter

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:

Re: lambda lists

PostPosted: Thu Dec 18, 2008 1:01 am
by gutzofter
WooHoo! I did it!

Code: Select all
(defmacro make-prop (name args)
  (let ((g (gensym))
        (r-args (flatten (remove-keywords args))))
       (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)
                   (if (equal '&key (first args))
                         (setf args (rest args))
                         (setf is-key-arg? t)))
                      (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))))))         
                      (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.