evan's original examples... ---
These first examples are pretty trivial, and can mostly be done today as python expressions with no difficulty. For the fmt: and var: examples, i'll just hand-wave, I think what I mean is pretty clear...
Now for Evan's tricky examples: options/foo/item:0 | request/foo/item:0 | default data/stat/fmt:thousands_commas | string:No data. My solution using Python expressions: First of all, provide a namespace that provides access to API stuff. We can argue later about how this can be named & organized. This namespace is always available in ZPT, and can be imported in Python Scripts. Next, we provide a function that behaves a little bit like the existing path() function - given some names, for each successive pair it tries to find foo[bar] and getattr(foo, bar) and if both fail, we don't raise the AttributeError or KeyError - we just return false (more on this below). This allows you to chain function calls with "or". TALES has to be modified a bit for this to work as I intend, as described below. This path lookup function should just take, as arguments, any number of ids to look up. You can pass a sequence using the *args notation. Note that since it just tries __getitem__ and __getattr__ at each step, it works fine with mappings (e.g. the request object). I can't think of a good name so i'm calling it zget. Examples: original: options/foo/item:0 | request/foo/item:0 | default mine: zget('options','foo')[0] or zget('request','foo')[0] or default original: data/stat/fmt:thousands_commas | string:No data. mine: zope.fmt.thousands_commas(zget('data','stat')) or 'No data' Note a significant difference in this latter example: in Evan's version, the thousands_commas call can be short-circuited if data/stat does not exist, while in mine it cannot be avoided (it is merely called on an empty string). How this works: the "false" value returned by zget is a bit special - it's a lightweight "null object". e.g. __len__ returns 0, while __getitem__, __getattr__, and __call__ return None ... and __str__ (and __repr__?) returns ''. It would also keep an _exception attribute which would be the exception that led to its creation (e.g. the AttributeError). TALES would then have to be modified such that if the end result of a TALES expression is one of these special null objects, we re-raise its _exception. That way you still find out what the missing item was.