Hello all,
I'm in a quest to make functional data structures, with referencial
transparency. In the process i had to define a record structure, which
is based on arrays.
The whole thing is easy with macros, but i'd like to have a functional
interface underlying those macros. (as record types need to be redefined
dynamically when one of their "superclass" is redefined)
Defining accessors from the functional interface is trivial using the
compile function. But i would like those accessors to be inlined as well.
so i did something like this :
(defun make-accessor (class-name slot-name slot-index)
(eval `(declaim (inline ,(slot-name class-name slot-name))))
(compile (slot-name class-name slot-name)
`(lambda (instance)
(aref instance ,slot-index))))
I suspect this might not work though. And i don't even know how to make
sure this works !
Any idea on how to do this, and also how to make sure those accessors
are actually inlined ?
I'm using lispworks 5.0.2
Thanks in advance,
Sacha
ps : yes, i'm aware this is greenspuning CL records !
On May 24, 10:36 am, Sacha <····@address.spam> wrote:
> Hello all,
>
> I'm in a quest to make functional data structures, with referencial
> transparency. In the process i had to define a record structure, which
> is based on arrays.
>
> The whole thing is easy with macros, but i'd like to have a functional
> interface underlying those macros. (as record types need to be redefined
> dynamically when one of their "superclass" is redefined)
>
> Defining accessors from the functional interface is trivial using the
> compile function. But i would like those accessors to be inlined as well.
>
> so i did something like this :
>
> (defun make-accessor (class-name slot-name slot-index)
> (eval `(declaim (inline ,(slot-name class-name slot-name))))
> (compile (slot-name class-name slot-name)
> `(lambda (instance)
> (aref instance ,slot-index))))
That's weird. Why not a macro?
(defun make-accessor (class-name slot-name slot-index)
`(progn
(declaim (inline ,(slot-name class-name slot-name)))
(defun ,(slot-name class-name slot-name) (instance)
(aref instance ,slot-index))))
In article <························@r3g2000prh.googlegroups.com>,
Joe Marshall <··········@gmail.com> wrote:
> On May 24, 10:36 am, Sacha <····@address.spam> wrote:
> > Hello all,
> >
> > I'm in a quest to make functional data structures, with referencial
> > transparency. In the process i had to define a record structure, which
> > is based on arrays.
> >
> > The whole thing is easy with macros, but i'd like to have a functional
> > interface underlying those macros. (as record types need to be redefined
> > dynamically when one of their "superclass" is redefined)
> >
> > Defining accessors from the functional interface is trivial using the
> > compile function. But i would like those accessors to be inlined as well.
> >
> > so i did something like this :
> >
> > (defun make-accessor (class-name slot-name slot-index)
> > (eval `(declaim (inline ,(slot-name class-name slot-name))))
Use PROCLAIM instead of EVAL of DECLAIM:
(proclaim `(inline ,(slot-name class-name slot-name)))
> > (compile (slot-name class-name slot-name)
> > `(lambda (instance)
> > (aref instance ,slot-index))))
>
> That's weird. Why not a macro?
I think because he's creating these things at runtime. BTW, why does
your supposed macro definition start with DEFUN? :)
>
> (defun make-accessor (class-name slot-name slot-index)
> `(progn
> (declaim (inline ,(slot-name class-name slot-name)))
> (defun ,(slot-name class-name slot-name) (instance)
> (aref instance ,slot-index))))
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Barry Margolin wrote:
> In article <························@r3g2000prh.googlegroups.com>,
> Joe Marshall <··········@gmail.com> wrote:
>
>> On May 24, 10:36 am, Sacha <····@address.spam> wrote:
>>> Hello all,
>>>
>>> I'm in a quest to make functional data structures, with referencial
>>> transparency. In the process i had to define a record structure, which
>>> is based on arrays.
>>>
>>> The whole thing is easy with macros, but i'd like to have a functional
>>> interface underlying those macros. (as record types need to be redefined
>>> dynamically when one of their "superclass" is redefined)
>>>
>>> Defining accessors from the functional interface is trivial using the
>>> compile function. But i would like those accessors to be inlined as well.
>>>
>>> so i did something like this :
>>>
>>> (defun make-accessor (class-name slot-name slot-index)
>>> (eval `(declaim (inline ,(slot-name class-name slot-name))))
>
> Use PROCLAIM instead of EVAL of DECLAIM:
>
> (proclaim `(inline ,(slot-name class-name slot-name)))
>
Thanks you =P
Now the last question remains : how do i make sure the inlining actually
works (beside decompiling) ?
Sacha
Sacha <····@address.spam> writes:
> Barry Margolin wrote:
>> In article <························@r3g2000prh.googlegroups.com>,
>> Joe Marshall <··········@gmail.com> wrote:
>>
>>> On May 24, 10:36 am, Sacha <····@address.spam> wrote:
>>>> Hello all,
>>>>
>>>> I'm in a quest to make functional data structures, with referencial
>>>> transparency. In the process i had to define a record structure, which
>>>> is based on arrays.
>>>>
>>>> The whole thing is easy with macros, but i'd like to have a functional
>>>> interface underlying those macros. (as record types need to be redefined
>>>> dynamically when one of their "superclass" is redefined)
>>>>
>>>> Defining accessors from the functional interface is trivial using the
>>>> compile function. But i would like those accessors to be inlined as well.
>>>>
>>>> so i did something like this :
>>>>
>>>> (defun make-accessor (class-name slot-name slot-index)
>>>> (eval `(declaim (inline ,(slot-name class-name slot-name))))
>> Use PROCLAIM instead of EVAL of DECLAIM:
>> (proclaim `(inline ,(slot-name class-name slot-name)))
>>
>
>
> Thanks you =P
>
> Now the last question remains : how do i make sure the inlining
> actually works (beside decompiling) ?
Reading the doc of your implementation, and seeing what guarantee they
give about inlining.
--
__Pascal Bourguignon__ http://www.informatimago.com/
NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
Pascal Bourguignon wrote:
> Sacha <····@address.spam> writes:
>
>> Barry Margolin wrote:
>>> In article <························@r3g2000prh.googlegroups.com>,
>>> Joe Marshall <··········@gmail.com> wrote:
>>>
>>>> On May 24, 10:36 am, Sacha <····@address.spam> wrote:
>>
>> Now the last question remains : how do i make sure the inlining
>> actually works (beside decompiling) ?
>
> Reading the doc of your implementation, and seeing what guarantee they
> give about inlining.
>
Haha well ok, not quite the answer i expected but thanks anyways.
Sacha
In article <·······················@phobos.telenet-ops.be>,
Sacha <····@address.spam> wrote:
> Pascal Bourguignon wrote:
> > Sacha <····@address.spam> writes:
> >
> >> Barry Margolin wrote:
> >>> In article <························@r3g2000prh.googlegroups.com>,
> >>> Joe Marshall <··········@gmail.com> wrote:
> >>>
> >>>> On May 24, 10:36 am, Sacha <····@address.spam> wrote:
> >>
> >> Now the last question remains : how do i make sure the inlining
> >> actually works (beside decompiling) ?
> >
> > Reading the doc of your implementation, and seeing what guarantee they
> > give about inlining.
> >
>
> Haha well ok, not quite the answer i expected but thanks anyways.
What kind of answer DID you expect? How can you tell anything about
what the compiler does, except by decompiling?
As far as the Common Lisp spec is concerned, a valid implementation of
COMPILE could work by expanding all macros and outputing code that calls
EVAL on the resulting expression. But no serious implementation would
do this (although byte-compiling, as in Emacs Lisp, is not too much
better), so you don't have to worry about it.
The same thing with inline functions. Either an implementation supports
them, in which case I'd expect it to do it all the time, or it doesn't.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Barry Margolin wrote:
> In article <·······················@phobos.telenet-ops.be>,
> Sacha <····@address.spam> wrote:
>
>> Pascal Bourguignon wrote:
>>> Sacha <····@address.spam> writes:
>>>
>>>> Barry Margolin wrote:
>>>>> In article <························@r3g2000prh.googlegroups.com>,
>>>>> Joe Marshall <··········@gmail.com> wrote:
>>>>>
>>>>>> On May 24, 10:36 am, Sacha <····@address.spam> wrote:
>>>> Now the last question remains : how do i make sure the inlining
>>>> actually works (beside decompiling) ?
>>> Reading the doc of your implementation, and seeing what guarantee they
>>> give about inlining.
>>>
>> Haha well ok, not quite the answer i expected but thanks anyways.
>
> What kind of answer DID you expect? How can you tell anything about
> what the compiler does, except by decompiling?
>
> As far as the Common Lisp spec is concerned, a valid implementation of
> COMPILE could work by expanding all macros and outputing code that calls
> EVAL on the resulting expression. But no serious implementation would
> do this (although byte-compiling, as in Emacs Lisp, is not too much
> better), so you don't have to worry about it.
>
> The same thing with inline functions. Either an implementation supports
> them, in which case I'd expect it to do it all the time, or it doesn't.
>
yep this makes sense ...
Anyways i had warnings all over the place telling me the inline
expansion wasn't available... so i guess that's not working =(
Sacha
Joe Marshall wrote:
> That's weird. Why not a macro?
>
> (defmacro make-accessor (class-name slot-name slot-index)
> `(progn
> (declaim (inline ,(slot-name class-name slot-name)))
> (defun ,(slot-name class-name slot-name) (instance)
> (aref instance ,slot-index))))
>
Let's say i have a class foo deriving from bar, bar has 3 slots.
so the first slot of foo will be (aref instance 3)
now i redefine bar so that it has 4 slots ... now the first slot of foo
is at (aref instance 4) ... so i need to recompile slot definitions for
all derived instances of bar.
Using a macro, i would end up with a macro expansion about foo in the
file concerning bar ... that doesn't sound right, hence the functional
interface.
Sacha
In article <·······················@phobos.telenet-ops.be>,
Sacha <····@address.spam> wrote:
> Joe Marshall wrote:
>
> > That's weird. Why not a macro?
> >
> > (defmacro make-accessor (class-name slot-name slot-index)
> > `(progn
> > (declaim (inline ,(slot-name class-name slot-name)))
> > (defun ,(slot-name class-name slot-name) (instance)
> > (aref instance ,slot-index))))
> >
>
>
> Let's say i have a class foo deriving from bar, bar has 3 slots.
> so the first slot of foo will be (aref instance 3)
>
> now i redefine bar so that it has 4 slots ... now the first slot of foo
> is at (aref instance 4) ... so i need to recompile slot definitions for
> all derived instances of bar.
Is there a good reason you're not using CL's built-in object system,
rather than rolling your own and reinventing these wheels?
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
Barry Margolin wrote:
> In article <·······················@phobos.telenet-ops.be>,
> Sacha <····@address.spam> wrote:
> Is there a good reason you're not using CL's built-in object system,
> rather than rolling your own and reinventing these wheels?
>
Not quite a good reason.
First and foremost, for the hell of it ! have fun, learn new concepts,
see how it's done.
Then there is a long term goal.
I have this application consuming lots and lots of memory, maintaining
tons of objects .... every now and then i need to serialize those to
disk, and the whole thing blocks until serialization is done. This is
quite a problem for a service which is supposed to be available at all
times.
I figured it would be nice to have the whole data model defined as
purely functional so that i could pass the current root object to a
thread for serialization, and keep using the structure and "updating" it
without waiting for the end of serialization.
Then i'd get all the goodies that come with it, easy transactions,
non-blocking read from any thread and so on.
So i plundered the Haskell library source code for Data.Map ...a purely
functional binary balanced tree, but my CLOS implementation was really
performing poorly compared to other non-functional implementations. So i
tested this with arrays for nodes and a couple macros to make it look
quite like clos objects. There my implementation was performing as well
as non-functional ones i could find.
So there it is, i want to have this _very lightweight_ record system,
and already started building around it, having great fun in the process =P
I could have been using Haskell for this, but i miss the lisp syntax and
the macro system as soon as i go see elsewhere now ... damn you all for
this !
Sacha
On May 25, 4:02 am, Sacha <····@address.spam> wrote:
> So i plundered the Haskell library source code for Data.Map ...a purely
> functional binary balanced tree, but my CLOS implementation was really
> performing poorly compared to other non-functional implementations. So i
> tested this with arrays for nodes and a couple macros to make it look
> quite like clos objects. There my implementation was performing as well
> as non-functional ones i could find.
>
> So there it is, i want to have this _very lightweight_ record system,
> and already started building around it, having great fun in the process =P
Common Lisp comes with heavier-weight objects via defclass/make-
instance, and lighter-weight ones via defstruct. SBCL (and CMUCL)
even have very nice semantics defined for what happens when you
incompatibly redefine a structure class. It also allows you to
specify representation as a vector or a list, but I think that's a bit
of an anachronism.
On May 24, 6:22 pm, Sacha <····@address.spam> wrote:
> Joe Marshall wrote:
> > That's weird. Why not a macro?
>
> > (defmacro make-accessor (class-name slot-name slot-index)
> > `(progn
> > (declaim (inline ,(slot-name class-name slot-name)))
> > (defun ,(slot-name class-name slot-name) (instance)
> > (aref instance ,slot-index))))
>
> Let's say i have a class foo deriving from bar, bar has 3 slots.
> so the first slot of foo will be (aref instance 3)
>
> now i redefine bar so that it has 4 slots ... now the first slot of foo
> is at (aref instance 4) ... so i need to recompile slot definitions for
> all derived instances of bar.
>
> Using a macro, i would end up with a macro expansion about foo in the
> file concerning bar ... that doesn't sound right, hence the functional
> interface.
I think this will turn out to be the least of your problems.
If you redefine bar, you not only have to recompile all the accessors
for every class derived from bar, but you also have to figure out what
to do with the old instances of those classes (which will not be
morphologically the same) *and* recompile every function that inlined
the old accessors (I don't know *how* you'd enumerate these).
Joe Marshall wrote:
> On May 24, 6:22 pm, Sacha <····@address.spam> wrote:
>> Joe Marshall wrote:
>>> That's weird. Why not a macro?
>>> (defmacro make-accessor (class-name slot-name slot-index)
>>> `(progn
>>> (declaim (inline ,(slot-name class-name slot-name)))
>>> (defun ,(slot-name class-name slot-name) (instance)
>>> (aref instance ,slot-index))))
>> Let's say i have a class foo deriving from bar, bar has 3 slots.
>> so the first slot of foo will be (aref instance 3)
>>
>> now i redefine bar so that it has 4 slots ... now the first slot of foo
>> is at (aref instance 4) ... so i need to recompile slot definitions for
>> all derived instances of bar.
>>
>> Using a macro, i would end up with a macro expansion about foo in the
>> file concerning bar ... that doesn't sound right, hence the functional
>> interface.
>
> I think this will turn out to be the least of your problems.
>
> If you redefine bar, you not only have to recompile all the accessors
> for every class derived from bar, but you also have to figure out what
> to do with the old instances of those classes (which will not be
> morphologically the same) *and* recompile every function that inlined
> the old accessors (I don't know *how* you'd enumerate these).
>
>
for the instances of old class i can do with it, scratch the data start
anew ... but yeah i didn't think about the inlined code ... so much for
inlining then!
Sacha