[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