Attention: cross post PEP308 is concerned with the introduction of a ternary conditional operator (something like an "if cond: val_true else: val_false") into Zope. In my view, such an operator would make TALES expressions easier because we could get rid of the "and/or" hack to represent conditionals and we could forget about the "test" function, which evaluates too eagerly. Please have a look at PEP308 and consider voting. Details in "comp.lang.python.announce". Dieter
Attention: cross post
PEP308 is concerned with the introduction of a ternary conditional operator (something like an "if cond: val_true else: val_false") into Zope.
In my view, such an operator would make TALES expressions easier because we could get rid of the "and/or" hack to represent conditionals and we could forget about the "test" function, which evaluates too eagerly.
Please have a look at PEP308 and consider voting. Details in "comp.lang.python.announce".
Dieter
IMO TALES should solve this for itself by introducing an if/then/else expression form rather than depending on Python. If you can have a "not:.." expression, surely you can have an "if:..:then:..:else:.." expression. --Guido van Rossum (home page: http://www.python.org/~guido/)
Guido van Rossum wrote:
IMO TALES should solve this for itself by introducing an if/then/else expression form rather than depending on Python. If you can have a "not:.." expression, surely you can have an "if:..:then:..:else:.." expression.
--Guido van Rossum (home page: http://www.python.org/~guido/)
Yes, I'd be interested in seeing some kind of expression superset operator in TALES such that you could use some boolean logic in expressions which had subexpressions of different types (ie path expressions vs python expressions). Currently the "punt" is to go out to Python for any logic other than the path expression OR syntax. e.g. tal:define="variable tales: path: path_component | string: foo" An inline if/else might be C like tal:define="variable tales: local_var ? path: path_componenta : string: foo" where "tales:" is simply whatever the meta-expression handler name is.
Guido van Rossum wrote:
IMO TALES should solve this for itself by introducing an if/then/else expression form rather than depending on Python. If you can have a "not:.." expression, surely you can have an "if:..:then:..:else:.." expression.
Now that you point it out, it's not even hard. Here's a proof-of-concept, with really awful parsing (it obviously breaks on nested if: then: else:), that actually works: class IfExpr: def __init__(self, name, expr, compiler): self._s = expr = expr.lstrip() m = re.match('(.*) then:(.*) else:(.*)', expr) if m is not None: condexpr, thenexpr, elseexpr = m.groups() self._cond = compiler.compile(condexpr) self._then = compiler.compile(thenexpr) self._else = compiler.compile(elseexpr) def __call__(self, econtext): if econtext.evaluateBoolean(self._cond): return econtext.evaluate(self._then) return econtext.evaluate(self._else) (Tested with <div tal:replace="if:options/x then:string:yes else:string:no">) Is this worth a robust implementation, ZPT folks? Cheers, Evan @ 4-am
On Tue, Mar 04, 2003 at 03:21:57PM -0600, Evan Simpson wrote:
Is this worth a robust implementation, ZPT folks?
maybe, but i'd rather first wait and see how the PEP goes. it would suck to have to constantly deal with two totally different flavors of ternary. -- Paul Winkler http://www.slinkp.com
Evan Simpson wrote:
Guido van Rossum wrote:
IMO TALES should solve this for itself by introducing an if/then/else expression form rather than depending on Python. If you can have a "not:.." expression, surely you can have an "if:..:then:..:else:.." expression.
Now that you point it out, it's not even hard. Here's a proof-of-concept, with really awful parsing (it obviously breaks on nested if: then: else:), that actually works:
class IfExpr: def __init__(self, name, expr, compiler): self._s = expr = expr.lstrip() m = re.match('(.*) then:(.*) else:(.*)', expr) if m is not None: condexpr, thenexpr, elseexpr = m.groups() self._cond = compiler.compile(condexpr) self._then = compiler.compile(thenexpr) self._else = compiler.compile(elseexpr)
def __call__(self, econtext): if econtext.evaluateBoolean(self._cond): return econtext.evaluate(self._then) return econtext.evaluate(self._else)
(Tested with <div tal:replace="if:options/x then:string:yes else:string:no">)
Is this worth a robust implementation, ZPT folks?
I think so. Iam much too often using "python:test(...." just for simple condition testing.
Cheers,
Evan @ 4-am
(Tested with <div tal:replace="if:options/x then:string:yes else:string:no">)
There are an awful lot of colons in there :-) Here's an off-the-wall idea: <div tal:replace="talif" tal:if="options/x" tal:true="string:yes" tal:false="string:no" > This looks better as a tal:tag <tal:block replace="talif" if="options/x" true="string:yes" false="string:no" > Or, if you only use this kind of thing with tal:replace, tal:content and tal:define. <tal:block defineif="foo options/x" true="string:yes" false="string:no" > Of course, none of this helps for tal:attributes. -- Steve Alexander
(Tested with <div tal:replace="if:options/x then:string:yes else:string:no">)
There are an awful lot of colons in there :-)
Indeed ...
Here's an off-the-wall idea:
<div tal:replace="talif" tal:if="options/x" tal:true="string:yes" tal:false="string:no" >
This looks better as a tal:tag
<tal:block replace="talif" if="options/x" true="string:yes" false="string:no" >
Or, if you only use this kind of thing with tal:replace, tal:content and tal:define.
<tal:block defineif="foo options/x" true="string:yes" false="string:no" >
Of course, none of this helps for tal:attributes.
If I understood the intentions of ZPT right one of the ideas was to get rid of too much application logic in the template. But currently ZPT seems to be extended to become very similiar in functionality to DTML. I'd prefer to see an approach where Python is used wherever it makes sense and ZPT is kept as simple and stupid as possible. If a user has to learn new syntax it is, IMHO, better to let him learn the Python syntax, so he will be able to more easily migrate to using more Python later. More advanced ZPT that uses a lot of Python, like the one used in some Plone skins, really becomes very ugly and hard to read, even compared to DTML. My first impression from Zope 3 was that it becomes better there because of the heavy usage of views that specify helper methods that then are used from the ZPT. The most trivial approach to this is "Python Server Pages" (which has been implemented a couple of times), i.e. being able to write inline Python code in HTML/XML, but this doesn't have the elegance of ZPT (staying compatible with WYSIWYG HTML editors etc.). I don't know how to actually do this right now, but from a usability point of view it seems to me that the best solution would be similar to what you get in Windows RAD IDEs, where I can select a widget and then write code for it in a pop-up box. That would mean that in the ZPT there just is a very simple directive, like a tal:replace or tal:content, but I can expand this with a mouse click to get to a Script (Python) where I can write the code that will create the actual content. Joachim
OK, how about this: 1. Python is kept as is. 2. To support one-line if-else in attributes in ZPT, the python expressions used in ZPT imports an extra method. This method can be called whetever people want it toi be called, but for claritys sake lets call it 'if_else' if_else(expression, true_result, false_result) thusly: <img src="placeholder" tal:attributes="src if_else(has_icon, 'objectpath/icon', 'images/default_icon')"> Ok, then we can do if-then-else in one line for attributes of ZPT, without having to define a pythonscript that does it. The method if_else would look like: def if_else(c, a, b): if c: return a else: return b I'm not expert in how python expression work, and hence don't know how to make python expressions aware about this method, but I'm sure it's possible, right?
The method if_else would look like:
def if_else(c, a, b): if c: return a else: return b
I'm not expert in how python expression work, and hence don't know how to make python expressions aware about this method, but I'm sure it's possible, right?
This is possible. But, the problem remains that both a and b (in your example above) are evaluated. The python syntax change, and the TALES syntax change, would mean that only one of a and b are evaluated. -- Steve Alexander
Lennart Regebro wrote at 2003-3-7 15:57 +0100:
1. Python is kept as is. 2. To support one-line if-else in attributes in ZPT, the python expressions used in ZPT imports an extra method. This method can be called whetever people want it toi be called, but for claritys sake lets call it 'if_else'
if_else(expression, true_result, false_result)
We have this function. It is called "test" (and more flexible than your proposal). It causes occasional questions on the mailing lists because it does not behave as one expects of an if-then-else. The main problem: if existence_of_some_object then: expression_depending_on_this_object else: alternative_expression cannot be expressed with "test" (or whatever function, unless Python changes function call semantics). *Provided*, "expression_depending_on_this_object" does not evaluate to a Python false value, existence_of_some_object and expression_depending_on_this_object or alternative_expression can be used. However, this is less clear (than an explicit "if-then-else" expression) and error prone (due to the *provided* condition). Dieter
On Fri, Mar 07, 2003 at 07:33:44AM +0100, Joachim Werner wrote:
If I understood the intentions of ZPT right one of the ideas was to get rid of too much application logic in the template. But currently ZPT seems to be extended to become very similiar in functionality to DTML. I'd prefer to see an approach where Python is used wherever it makes sense and ZPT is kept as simple and stupid as possible.
+sys.maxint "ugly" python expressions in ZPT is to me a clear signal that you need to refactor and that's a GOOD THING. And refactoring is easy when you can just start by copy / pasting the python expressions into a Script. If they were some new-fangled "if: then: else:" syntax in TAL, you'd have to rewrite from scratch... and we're right back in the mess we got into with DTML: the poor developer is forced to learn many ways of doing the same thing. -- Paul Winkler http://www.slinkp.com look! up in the sky! it's secretary The Archer of Doom (randomhero courtesy isometric.spaceninja.com)
Paul Winkler wrote:
+sys.maxint
"ugly" python expressions in ZPT is to me a clear signal that you need to refactor and that's a GOOD THING. And refactoring is easy when you can just start by copy / pasting the python expressions into a Script. If they were some new-fangled "if: then: else:" syntax in TAL, you'd have to rewrite from scratch... and we're right back in the mess we got into with DTML: the poor developer is forced to learn many ways of doing the same thing.
+OO (that's infinity in case it's not clear...) cheers, Chris
Guido van Rossum wrote:
IMO TALES should solve this for itself by introducing an if/then/else expression form rather than depending on Python. If you can have a "not:.." expression, surely you can have an "if:..:then:..:else:.." expression.
I think not: is dubious and I'd find if-then-else way over the lines... Chris
In article <3E65F34D.8020701@nipltd.com> you write:
Guido van Rossum wrote:
IMO TALES should solve this for itself by introducing an if/then/else expression form rather than depending on Python. If you can have a "not:.." expression, surely you can have an "if:..:then:..:else:.." expression.
I think not: is dubious and I'd find if-then-else way over the lines...
What?!! not: is very useful. How do you write alternatives without it? <tal:if condition="foo"> .... </tal:if> <tal:if condition="not:foo"> .... </tal:if> Florent -- Florent Guillaume, Nuxeo (Paris, France) +33 1 40 33 79 87 http://nuxeo.com mailto:fg@nuxeo.com
Guido van Rossum wrote at 2003-3-4 15:23 -0500:
.... if-then-else expression ....
IMO TALES should solve this for itself by introducing an if/then/else expression form rather than depending on Python. If you can have a "not:.." expression, surely you can have an "if:..:then:..:else:.." expression.
Hopefully, we will get it in Python. There, it is useful, too, being clearer (more explicit) than "cond and expr1 or expr2" and less error prone... Dieter
--On Tuesday, March 04, 2003 03:23:54 PM -0500 Guido van Rossum <guido@python.org> wrote:
IMO TALES should solve this for itself by introducing an if/then/else expression form rather than depending on Python. If you can have a "not:.." expression, surely you can have an "if:..:then:..:else:.." expression.
If it was just TALES I'd agree. However I suspect that many other systems built on Python have the same problem of allowing only Python expressions in various contexts. It seems very likely that most of the other web templating systems have this limitation. If this is true then, IMO, it's better to have one way to do it across all the applications built on Python than have every app. do it differently. If I didn't believe this I would have voted for no change to the language. Dan Pierson
participants (12)
-
Chris Withers -
Dan L. Pierson -
Dieter Maurer -
Evan Simpson -
Florent Guillaume -
Godefroid Chapelle -
Guido van Rossum -
Joachim Werner -
Lennart Regebro -
Matthew T. Kromer -
Paul Winkler -
Steve Alexander