What can you put into the store besides strings? Almost all lisp values and objects can be stored: numbers, symbols, strings, nil, characters, pathnames, conses, hash-tables, arrays, CLOS objects and structs. Nested and circular things are allowed. Nested and circular things are allowed. You can store basically anything except compiled functions, closures, class objects, packages and streams. Functions can be stored as uncompiled lambda expressions. (Compiled functions and other kinds of objects may eventually get supported too.)
Elephant needs to use a representation of data that is independant of a specific lisp or data store. Therefore all lisp values that are stored must be serialized into a canonical format. Because Berkeley DB supports variable length binary buffers, Elephant uses a binary serialization system. This process has some important consequences that it is very important to understand:
(setq foo (cons nil nil)) => (NIL) (add-to-root "my key" foo) => (NIL) (add-to-root "my other key" foo) => (NIL) (eq (get-from-root "my key") (get-from-root "my other key")) => NIL
(setf (car foo) T) => T (get-from-root "my key") => (NIL)
This will affect all aggregate types: objects, conses, hash-tables, et cetera. (You can of course manually re-store the cons.) In this sense elephant does not automatically provide persistent collections. If you want to persist every access, you have to use BTrees (see Persistent BTrees).
This may seem terribly restrictive, but don't despair, we'll solve most of these problems in the next section.....