Hi,
I need a sort of two dimensional dynamic array which I can think of in terms
of rows and columns. Columns should have certain attributes like :name or
:hidden. Rows should be easily accessible and modifyable. Well I wrote it
myself and called it snapshot. Although it works fine and already is a
version 2 I still find it a somehow clumsy. I feel I can't see the forrest
for the trees regarding simplicity.
You might review my code for that beast (with two real life examples
attached) at
www.atp-media.de/devel/snapshot.lsp
Any suggestions or hints where I can find something similar or how I can
improve the code are very appreciated.
Thanks
Andreas
Sounds to me like some kind of database table (of sorts), where you
want to be able to modify column values and sort by column values. If I
were to implement something like this, I'd probable use a list for all
the rows, and each row would be a hash-table, where each key was a
column symbol.
Using the above, sorting becomes no more difficult than using the SORT
function, where the compare function just compares particular keys'
values. You could also create a COLUMN macro that returns a GETHASH, so
it is settable.
That may be a bit simplistic for what you are trying to accomplish,
though. It would require keeping track of the "type" of each column and
writing a compare function for each type to send to SORT. It also might
not be as fast, but I see it being extremely flexible.
I typed up a quick example at:
http://www.retrobyte.org/lisp/table.lisp
Jeff M.
"Jeff M." <·······@gmail.com> schrieb im Newsbeitrag
·····························@f14g2000cwb.googlegroups.com...
> Sounds to me like some kind of database table (of sorts), where you
> want to be able to modify column values and sort by column values. If I
> were to implement something like this, I'd probable use a list for all
> the rows, and each row would be a hash-table, where each key was a
> column symbol.
>
> Using the above, sorting becomes no more difficult than using the SORT
> function, where the compare function just compares particular keys'
> values. You could also create a COLUMN macro that returns a GETHASH, so
> it is settable.
>
> That may be a bit simplistic for what you are trying to accomplish,
> though. It would require keeping track of the "type" of each column and
> writing a compare function for each type to send to SORT. It also might
> not be as fast, but I see it being extremely flexible.
>
> I typed up a quick example at:
> http://www.retrobyte.org/lisp/table.lisp
>
> Jeff M.
>
Hi Jeff,
thanks for your hint. Indeed this "snapshot" should be something like an
ADORecordset. It will mostly work on database results but not only. Yet I
did not consider sorting. I thought it will mostly be done by the database.
Because I want to put arbitrary rows in my snapshot, sorting indeed is an
issue.
Sometimes speaking things out helps. I did not explain my problem clearly.
The snapshot contains a 'row-pointer' so it has a current row. This is what
I called imperative interface. It is the method
(defmethod field ((snapshot snapshot) id)
"return the named field from current row where id might be either a column
name or number"
... )
which together with a macro for-each-row allows code like:
(for-each-row (snapshot)
;; getting a 'field'
(setf x (field snapshot "Name"))
;; or setting a 'field'
(setf (field snapshot "Name") y))
)
The unpleasant thing has been what I called the functional interface
(defmethod row-field ((snapshot snapshot) row id) ... )
I had to supply both the snapshot and a row, which is redundant information
and leads to a nonunique interface, because there are two methods field and
row-field.
Just after posting I thought about this further explanation. My easy answer
to my own question is: each row must contain a reference to the snapshot and
should be of class 'row. In this case I can replace method row-field by
(defmethod field ((row row) id) ... )
which is consistent with the first method 'field' and allows functional
access with minimal writing.
Well, your post still helped me, because it started discussion on sorting.
Thanks
Andreas
"Andreas Thiele" <··········@nospam.com> writes:
> Hi,
>
> I need a sort of two dimensional dynamic array which I can think of in terms
> of rows and columns. Columns should have certain attributes like :name or
> :hidden. Rows should be easily accessible and modifyable. Well I wrote it
> myself and called it snapshot. Although it works fine and already is a
> version 2 I still find it a somehow clumsy. I feel I can't see the forrest
> for the trees regarding simplicity.
>
> You might review my code for that beast (with two real life examples
> attached) at
>
> www.atp-media.de/devel/snapshot.lsp
>
> Any suggestions or hints where I can find something similar or how I can
> improve the code are very appreciated.
I just took a quick look at this but it looks similar enough to
something that I wrote for my book that you might find my take on the
same problem interesting. A draft of the relevant chapter is at:
<http://www.gigamonkeys.com/book/practical-an-mp3-database.html>
And it gets used in:
<http://www.gigamonkeys.com/book/practical-an-mp3-browser.html>
-Peter
--
Peter Seibel ·····@javamonkey.com
Lisp is the red pill. -- John Fraser, comp.lang.lisp
"Peter Seibel" <·····@javamonkey.com> schrieb im Newsbeitrag
···················@javamonkey.com...
> "Andreas Thiele" <··········@nospam.com> writes:
>
> > Hi,
> >
> > I need a sort of two dimensional dynamic array which I can think of in
terms
> > of rows and columns. Columns should have certain attributes like :name
or
> > :hidden. Rows should be easily accessible and modifyable. Well I wrote
it
> > myself and called it snapshot. Although it works fine and already is a
> > version 2 I still find it a somehow clumsy. I feel I can't see the
forrest
> > for the trees regarding simplicity.
> >
> > You might review my code for that beast (with two real life examples
> > attached) at
> >
> > www.atp-media.de/devel/snapshot.lsp
> >
> > Any suggestions or hints where I can find something similar or how I can
> > improve the code are very appreciated.
>
> I just took a quick look at this but it looks similar enough to
> something that I wrote for my book that you might find my take on the
> same problem interesting. A draft of the relevant chapter is at:
>
> <http://www.gigamonkeys.com/book/practical-an-mp3-database.html>
>
> And it gets used in:
>
> <http://www.gigamonkeys.com/book/practical-an-mp3-browser.html>
>
> -Peter
>
> --
> Peter Seibel ·····@javamonkey.com
>
> Lisp is the red pill. -- John Fraser, comp.lang.lisp
Peter,
playing around with some nice internet subjects your book gives indepth
explanations for rookies like me. I enjoyed reading the chapters.
Very helpful.
Thanks
Andreas
Andreas Thiele wrote:
> Hi,
>
> I need a sort of two dimensional dynamic array which I can think of in terms
> of rows and columns. Columns should have certain attributes like :name or
> :hidden. Rows should be easily accessible and modifyable. Well I wrote it
> myself and called it snapshot. Although it works fine and already is a
> version 2 I still find it a somehow clumsy. I feel I can't see the forrest
> for the trees regarding simplicity.
>
> You might review my code for that beast (with two real life examples
> attached) at
>
> www.atp-media.de/devel/snapshot.lsp
>
> Any suggestions or hints where I can find something similar or how I can
> improve the code are very appreciated.
I would do something along these lines. Storage is an adjustable array of
instances of CLOS classes. Columns are then slots. To add a column one
would have to redefine the class.
I think an array is better for storage, it is easier to index.
(in-package :cl-user)
(defclass searchable-instances ()
((storage :initform (make-array 256 :fill-pointer 0 :element-type t :adjustable t)
:accessor storage)
(storage-type :initarg :type :reader storage-type)
(current-index :initform nil :reader current-index)))
(defmethod number-instances ((obj searchable-instances))
(length (storage obj)))
(defmethod add-instance ((obj searchable-instances) new-instance)
(assert (typep new-instance (storage-type obj)))
(vector-push-extend new-instance (storage obj)))
(defmethod column-values ((obj searchable-instances) column)
(map 'list (lambda (inst) (slot-value inst column)) (storage obj)))
#|
;; Example
(defclass person ()
((name :initarg :name)
(age :initarg :age)))
CL-USER 24 > (setf si (make-instance 'searchable-instances :type 'person))
#<SEARCHABLE-INSTANCES 2067831C>
CL-USER 25 > (add-instance si (make-instance 'person :name "wade" :age :too-old))
0
CL-USER 26 > (number-instances si)
1
CL-USER 27 >(add-instance si (make-instance 'person :name "libby" :age 13))
1
CL-USER 28 > (number-instances si)
2
CL-USER 29 > (column-values si 'age)
(:TOO-OLD 13)
CL-USER 30 > (defclass person ()
((name :initarg :name)
(age :initarg :age)
(sex :initarg :sex :initform :unknown)))
#<STANDARD-CLASS PERSON 2066AFCC>
CL-USER 31 > (column-values si 'sex)
(:UNKNOWN :UNKNOWN)
CL-USER 32 >
|#
Wade