You should be automatically redirected . If not, visit
http://newlisper.wordpress.com
and update your bookmarks.

30/01/2009

Simple database, second attempt

Rewriting is part of a writer's job, and with practice it's easy to be ruthless about your previous drafts. This chap has written more about the process than I ever could.

But it's slightly harder for me to be ruthless when editing code, because once I manage to get something working, I'm reluctant to break it just to try and make it better. But I'm slowly getting the hang of this too.

The simple database I started working on recently was OK, but there were things I didn't like about it. Perhaps the main problem area was with the way I switched between a simple list of lists:

((1 1.0079 "Hydrogen" "H" -259 -253 0.09 0.14 1776 1 13.5984) 
 (2 4.0026 "Helium" "He" -272 -269 0 0 1895 18 24.5874) 
 ...

to a list of association lists, where the keys were the 'column' names:

(((No 1) (AtomicWeight 1.0079) (Name "Hydrogen") ... )
 ((No 2) (AtomicWeight 4.0026) (Name "Helium") ... )
 ...

This happened all the time; virtually every function did this conversion process. Before any rows could be selected, the whole table had to be modified, with keys inserted before every value. Not a good idea with large tables!

So I abandoned the association list approach. You don't really have to use lookup, because nth and find can do a similar job, albeit less easily:

(setf (nth (find column-name columns) row) (eval modify-fn))

I had to rewrite many of the functions, too, because now you always have to know the name of the table you're working on (before, you didn't, because the association list's keys were all you needed). It's a little less easy on the eye now, but more powerful. To select rows, you do this:

(select-rows 'elements '(and (> 'EarthCrust 1) (< 'DiscoveryYear 1900)))

which is slightly different to the old way (there's no where any more):

; old version
(select-rows 'elements (where (and (> 'EarthCrust 5)) (< 'DiscoveryYear 1900)))

The select-rows function now also does column filtering and sorting:

(select-rows 
  'elements                               ; table
  '(> 'EarthCrust 1)                      ; selection criterion
  '(Name Symbol)                          ; columns to return
  'Symbol                                 ; column to sort by
  '(fn (x y) (> (length x) (length y)))   ; sort function 
  )

(You can perhaps see why I still think it would be cool to have named parameters...!)

I've also re-written change-rows so that it can access all columns when making a change. The idea here is that you can change a column's value using a newLISP expression that can access information from other columns in that row:

(change-rows          
  'elements                 ; table              
  '(ends-with 'Name "ium")  ; selection criterion        
  'MP                       ; column to modify 
  '(dec 'BP)                ; expression to apply to column        
)

This changes the Melting Point of every "ium" element to be one less than its Boiling Point. (Yes, I noticed that the 'BP is quoted, when it normally wouldn't be, but it's already been replaced by the actual value when the dec function is called.)

So far, it's looking promising, not much slower than a SQLite database, and doing the same job with fewer functions.

If you'd like to see the second attempt, you can find it here, and there's a simple database to practice with here. I'd be very grateful for any improvements you can suggest!

0 Comments:

Post a Comment

Links to this post:

Create a Link

<< Home