[ZPT] Re: TAL's lack of an else...

Evan Simpson evan at 4-am.com
Fri Aug 1 14:22:08 EDT 2003


Fergal Daly wrote:
> As I've pointed out, people are already working around the lack of if/else in 
> a fairly ugly way. Isn't controlled, standardised, safe ugliness better than 
> what currently exists?

IMHO, yes, although there doesn't seem to be much evidence of use cases 
more complicated than the one you cite here:

> I suppose, although that's a bit of a pain. All ways of doing this are ugly 
> but I still think we can find something better than
> 
> <tal:x tal:define="temp user/isLoggedIn">
>   <tal:x tal:condition="temp">
>     welcome
>   </tal:x>
>   <tal:x tal:condition="not:temp">
>     please login
>   </tal:x>
> </tal:x>

...and frankly I think that this is about as good as this case is going 
to get.  You need a parent element that scopes the if/else, you need the 
actual if-condition, and you need to mark elements for 
inclusion/omission based on the value of the if-condition.  Apart from 
the variable "temp", which is largely flawed in my eyes by not being 
spelled "logged_in", not for existing, this sample's idiom is quite easy 
to understand and use, and about a compact as TAL gets.

It also has the virtue of being straightforwardly extensible in ways 
that some 'if/else' constructs that have been proposed in this thread 
are now, vis:

<p tal:define="has_duck here/hasDuck"
    comment="I'm not a dummy tag, I'm a real paragraph!">

I like ducks.

   <tal:x condition="has_duck">
     I see you have one. Nice duck, man!
   </tal:x>
   <tal:x condition="not:has_duck">
     You should get one!
   </tal:x>

They aren't for everyone of course.

   <tal:x condition="has_duck">
     But then, you're not everyone, are you ;-)
   </tal:x>
   <tal:x condition="not:has_duck">
     But I still think you should get one.
   </tal:x>
</p>

...that is, you can reuse the boolean variable, you can intersperse 
non-conditional spans, etc.

> What can you split on?

Since no valid variable name can contain a space, it works.
Algorithm sketch:

def parse_condition_expression(expr):
     parts = expr.strip().split(None, 1)
     if len(parts) == 2 and re.match(parts[0], _valid_name):
        return parts
     return None, expr

condvar, expr = parse_condition_expression(expr)

> My internal jury is still out on condition-group, it can do more than 
> if/elsif/else but it seems to me that when you use it to do more it gets very 
> hard to follow (see above for an example of me not following ;-)

You've provoked me into realizing that my tal:condition-group (as I 
envisioned implementing it) is essentially syntactic sugar for 
tal:define="condition_variable nothing", and can be dropped.  In fact, I 
can avoid playing with the implementation of condition by adding an 
expression type, instead:

tal:condition="flag:condition_var expression"

A 'flag:' expression has, as arguments, a variable name and another 
expression (of any type).  It first checks the variable.  If it has a 
true value, this is the value of the entire expression, and the 
sub-expression is ignored.  Otherwise, the expression is evaluated, the 
variable is bound to this value, and the value is returned.  This has 
the additional virtue of allowing chaining:

tal:condition="flag:var1 flag:var2 a_test"

In this design, the simple case above remains unchanged, and you only 
deal with 'flag' when you need more than two branches:

<p tal:define="has_pet here/hasDuck">

I like ducks.

   <tal:x condition="has_pet">
     I see you have one. Nice duck, man!
   </tal:x>
   <tal:x condition="flag:has_pet here/hasCat">
     Cats are OK, too, I guess.
   </tal:x>
   <tal:x condition="not:has_pet">
     You should get one!
   </tal:x>
</p>

This also suggests to me the idea of 'and:' and 'or:' expression types, 
that also behave as short-circuit booleans, but don't set the value of 
the variable.  Mix-n-match:

tal:condition="and:being_polite flag:has_pet here/hasCat"

Cheers,

Evan @ 4-am




More information about the ZPT mailing list