[Zope] Use of lambda expression in DTML

Chris McDonough chrism@digicool.com
Mon, 29 May 2000 22:58:54 -0400


> > What I would like to say is that if your application needs lambda, filter or
> > map, your code is getting bejond report or presentation generation (for which
> > DTML is intended) and in the realm of data manipulation and business rules. In
> > this case your code would be much better placed in some form of Method object,
> > be that an External, Python, or when ready, Perl Method, or even as a disk
> > based Product.
> 
> 1: This is simply not true, and a very poor excuse for
> handicapping the language.

Nope.  Lamba, filter, reduce, and map should IMHO not be part of DTML. 
Actually, exprs probably shouldn't be in there in the first place. 
People are trying to use DTML as a way to process non-UI elements.  This
is a slippery slope, and leads to something like PHP or ASP.  My opinion
is this:  Generate and format your HTML with DTML, and do everything
else in Python.  This gives you the added benefit that you can change
the return values of functions by changing the Python code without
having to muck with DTML, which is painful any way you look at it.

People are right when they say DTML is beginning to get worse than Perl,
and IMHO, adding these functions could make it even worse than it is
now.  This sort of processing was not meant to happen in an expr under
Zope.  Python lets you do it, but it's sort of hard for somebody else to
understand after you've completed it, even if they know Python well. 
Functional constructs are handy, but not the most clear thing on the
planet.

> 
> A common example is:
> 
> <dtml-in "_.map (lambda item: Catalog.getobject (item.data_record_id_),
>         Catalog (REQUEST)">


How could someone understand this when you're finished with it?  I
looked at it three times before figuring out what you were trying to
do.  What if you didn't write it and you needed to answer somebody
asking a question about it on this mailing list?

Isn't this much more understandable as an external method explicitly?

def return_cataloged_objects(self):
    obs = []
    catalog = self.Catalog
    request = self.REQUEST
    for r in catalog(request):
        d_rid = r.data_record_id_
        ob = catalog.getobject(d_rid)
        obs.append(ob)

    return obs

then:

<dtml-in return_cataloged_objects>
...
</dtml-in>

It *might* be slighly slower, but someone maintaining your code will
eventually thank you for this.  Eventually it will cost you less money
somewhere that you might be able to buy a faster server with.
 
> I know fetching the actual records from a ZCatalog introduces a
> performance penalty, but sometimes it's necessary; there are
> times you need to be absolutely sure everything is pushed on
> the namespace, including user-defined properties and
> sub-objects. This is the case in Hack&Roll, and I have to use a
> very ugly Python Method there (and as PythonMethods don't have
> map either, I have to build a list from scratch using for,
> which introduces additional penalties as I'm basically
> bypassing Python's optimizations).

Sometimes.  Sometimes not.  Read
http://www.python.org/doc/essays/list2str.html .

As I understand it, by using expr syntax to begin with, you're defeating
some of Zope's caching mechanisms, actually slowing things down in
reality.

> 2: If I should be using a Python Method, then Python Methods
> should have these forms, and they don't.

Maybe they should... it would be nice.  I'm not sure why they're not in
Python Methods, other than Evan tried to make the security inherent in
Python methods as close to DTML as he could.  I use map a lot.  I don't
use lambda unless I really, really have to.  Reduce and filter.. eh.  I
dunno.  They're sort of on the periphery of usefulness.

> 
> 3: In short, these excuses are just the fallback (or should I
> say Acquired?) excuses used mostly by people who don't know how
> to use these very cool features of Python.

I would hardly say Martijn is one of those.  :-)