=============================
README: Cellulose
=============================

:Author: Matthew Marshall
:Contact: matthew@matthewmarshall.org


Cheesy summary written up for the Cheeseshop
============================================

Cellulose provides a mechanism for maintaining consistency between
inter-dependant values with caching and lazy evaluation.

You can think of it like a spreadsheet program --  Many cells are are calculated
from the values of other cells.  When one cell changes, all of the dependant
cells get updated with new values.

However, cellulose goes quite a ways beyond this.  It guarantees that when a
value is read, it is consistant with all the values it depends on.  It also is
lazy (read: efficient.)  Calculating a value is put off till the very last
possible moment, and only recalculated when absolutely needed.

Dependency discovery and cache invalidation are fully transparent and automatic.
This greatly reduces a major source of bugs in software.

A goal of the project is to be as simple as possible, (but no simpler,) so that
anyone wanting to seriously use it could easily understand the internals.

Cellulose is similar in purpose to PyCells, but is in a way 'lower level'.  It
tries real hard to stay out of your way, but, as a result, lacks some of the
helpers that PyCells provides.  The most essential algorithmic difference is
probably that Cellulose desperately wants to be lazy, while in PyCells everything
is calculated immediately (by default.)  (On the flipside of this, observers in
PyCells are quite a bit easier to work with.)


Documentation
=============

In the docs directory there is an attempt at a tutorial that should explain
usage.  There is also a document giving a high level explanation of how the
algorithm works.  I highly recommend reading (and understanding) this if you
decide to use cellulose.

Please let me know if you find any of it confusing.  I've reworked the entire
thing in my thoughts enough times that I might have made up some terminology :-)


Porting code to 0.2 from 0.1.2
===============================

Version 0.2 makes some minor backwards incompatible changes from 0.1.2.  This
should only affect you if you are either 1) using the cellulose.restrictions
module or 2) writing your own cells class.

Porting code that uses cellulose.restrictions
---------------------------------------------

I decided that the restrictions functionality really didn't belong in the core
of cellulose.  It was beginning to complicate things that didn't need to be
complicated.  So, I moved everything into ``cellulose.extra.restrictions.``
Porting involves two steps:

    1)  Import from ``cellulose.extra.restrictions`` instead of from
        ``cellulose.restrictions``

    2)  Use ``RestrictedInputCell`` and ``RestrictedComputedCell`` instead of
        ``InputCell`` and ``ComputedCell`` respectively.  (These are both in the
        restrictions module, along with their respective descriptors.)

Note that RestrictedInputCellDescriptor takes a default value for the first
argument, not a restriction.

Porting cell classes
--------------------

I'd be surprised if anyone has actually done this, but what the heck.  I feel
like documenting it!

  * ``dependency_changed`` should now take the dependency as an argument, just
    like ``dependency_possibly_changed,`` only it's optional.

  * The internals of ``ComputedCell`` has been shuffled around some.  If you
    override ``get`` or ``run`` you'll need to update your code.

  * ``ComputedCell.__init__`` and ``InputCell.__init__`` no longer take
    ``restriction`` as a default argument.

  * The cell descriptors class structure has been shifted around.
    ``CellDescriptor`` is now the base class.  Also ``get_cell`` will no longer
    take a default value.  (That only makes sense on ``InputCell``\ s, and even
    then wasn't useful.)

  * Instead of ``cellulose.dependant_cell_stack`` use
    ``cellulose.get_dependant_stack()``  (It's a function now.)



Future directions
=================

 *  I *really* want a way to have network support.  It should be possible to do
    it elegantly without modifying any current modules, just by using the
    ``deep_dependencies`` feature in the DependantCell class.  I have some basic
    ideas on how it would work, I just need to get around to trying it.

 *  A general use way of observing for changes needs to be made.  What is
    currently in observers.py is more or less in the direction I want to go, but
    it at least needs more 'syntactical sugar.'

 *  A somewhat common use case I have been seeing is maintaining a list that is
    a filtered copy of another list.  Having efficient helpers to make this easy
    would be really nice.

 *  Perhaps prevent cells from being modified while a cell is being calculated.
    (ie, no side effects.)  (and naturally, this should be optional)

 *  A good way to introspect restrictions would probably be needed.
    (restrictions in general might need to be rethought.)

 *  I'd like to experiment with ways to vectorize computed cells, but that's
    further down the line.


Feedback
========

Cellulose has had something over 700 downloads since I first released it, but I
have received literally no feedback.  If you are using it at all I'd like to
hear about it, partly so I can have an idea of where I should keep backwards
compatibility.  (Is anyone still using python2.3?)

You can email me at matthew <at> matthewmarshall <dot> org.  If there is anyone
using it maybe I'll set up a ML or something.

