(whoops, hit send too early) Re: local/set (was RE: Zope direction and 2.2roadmap...) direction and 2.2roadmap...)
At 12:01 AM 12/10/99 -0500, Christopher Petrilli wrote:
Can you clearly explain in 1 sentence each, what each tag is for? (This includes let)
Let: allows read-only variables to be computed whose values are usable within a DTML nesting scope. Local: allows writable variables to be computed, whose values are usable and changeable within a DTML nesting scope. Set: singleton tag that changes the value of a "local" variable, as long as it was defined in the innermost surrounding "local" block.
"Phillip J. Eby" wrote:
Let: allows read-only variables to be computed whose values are usable within a DTML nesting scope.
Local: allows writable variables to be computed, whose values are usable and changeable within a DTML nesting scope.
Set: singleton tag that changes the value of a "local" variable, as long as it was defined in the innermost surrounding "local" block.
Given these use-cases, consider the following variant of Let: <dtml-let x="1+1" person: firstname=" 'fred' " weight="180"> <dtml-var x>, <dtml-var firstname>, <dtml-var "person.weight"> <dtml-call "person.set('weight', 185)"> <dtml-var weight> </dtml-let> That is, every variable set after a colon-terminated singleton 'foo:' is also a mutable (through .set()) attribute of 'foo'. Cheers, Evan @ 4-am
At 01:40 PM 12/10/99 -0600, Evan Simpson wrote:
"Phillip J. Eby" wrote:
Let: allows read-only variables to be computed whose values are usable within a DTML nesting scope.
Local: allows writable variables to be computed, whose values are usable and changeable within a DTML nesting scope.
Set: singleton tag that changes the value of a "local" variable, as long as it was defined in the innermost surrounding "local" block.
Given these use-cases, consider the following variant of Let:
<dtml-let x="1+1" person: firstname=" 'fred' " weight="180"> <dtml-var x>, <dtml-var firstname>, <dtml-var "person.weight"> <dtml-call "person.set('weight', 185)"> <dtml-var weight> </dtml-let>
That is, every variable set after a colon-terminated singleton 'foo:' is also a mutable (through .set()) attribute of 'foo'.
I like it. In a lot of ways, it's much more elegant. For example, you can use set at multiple nesting levels. Except for one thing. If you are calling "untrusted" code from your DTML, you have no way to prevent that code from changing the value of the object's fields, without doing something like: <dtml-let person="_.None"><dtml-call untrusted_code></dtml-let> However, that is probably not such a bad deal. Let me throw out a counter-proposal, however. Suppose that the _()/_.namespace() functions were changed to return writable namespace objects? Then, your example could be written as: <dtml-let x="1+1" person="_(firstname='fred',weight=180)"> <dtml-var x>, <dtml-var "person.firstname">, <dtml-var "person.weight"> <dtml-call "person.set('weight',185)"> <dtml-var weight> </dtml-let> And then both dtml-set and dtml-local can go away, and the : syntax isn't needed. Also, the above example could then be written as: <dtml-with "_(firstname='fred',weight=180,x=1+1)"> <dtml-var x>, <dtml-var firstname>, <dtml-var weight> <dtml-call "set('weight',185)"> <dtml-var weight> </dtml-with> at least if you don't need to interact with multiple "local-variable" namespaces simultaneously. Everybody wins. Last, but not least, I should probably note that my enthusiasm at the simplicity and elegance of these solutions from a programming standpoint is matched only by my misgivings about how much harder they may be to teach someone how to use than local/set. But I guess I'll withhold judgment on that until I've had to do it. :)
"Phillip J. Eby" wrote:
Let me throw out a counter-proposal, however. Suppose that the _()/_.namespace() functions were changed to return writable namespace objects?
I confess to having already done this for my own use since v1.10.2 Your point about untrusted-call safety is well-taken, and now that I think about it I have an alternate proposal :-) If only lexically enclosed code is allowed to alter Let variables, why even bother with non-writable variables? Allow Set to operate on the enclosing Let namespace, without limit. Heck, allow it to introduce new names, if it wants to. Thus: <dtml-let x="1+1" firstname=" 'fred' "> ... <dtml-set firstname=" 'mary' " weight="135"> ... <dtml-set qty="5" price="1.50" extprice="qty * price"> ... </dtml-let> Note that this makes nested Let superfluous, and <dtml-let ...> is essentially shorthand for <dtml-let><dtml-set ...> Now if every DTML object had a default empty local namespace, we could do away with Let entirely and just use Set.
Then, your example could be written as:
<dtml-let x="1+1" person="_(firstname='fred',weight=180)"> <dtml-var x>, <dtml-var "person.firstname">, <dtml-var "person.weight"> <dtml-call "person.set('weight',185)"> <dtml-var weight>
This diverges here, since 'weight' is *only* an attribute of 'person', not a full member of the namespace. Of course, to complete the insanity of my new proposal, we could keep the colon notation as a compact way of defining/altering this sort of sub-namespace 8->
Last, but not least, I should probably note that my enthusiasm at the simplicity and elegance of these solutions from a programming standpoint is matched only by my misgivings about how much harder they may be to teach someone how to use than local/set. But I guess I'll withhold judgment on that until I've had to do it. :)
Ditto. Cheers, Evan @ 4-am
At 03:16 PM 12/10/99 -0600, Evan Simpson wrote:
If only lexically enclosed code is allowed to alter Let variables, why even bother with non-writable variables? Allow Set to operate on the enclosing
Let
namespace, without limit. Heck, allow it to introduce new names, if it wants to.
Thus:
<dtml-let x="1+1" firstname=" 'fred' "> ... <dtml-set firstname=" 'mary' " weight="135"> ... <dtml-set qty="5" price="1.50" extprice="qty * price"> ... </dtml-let>
Note that this makes nested Let superfluous, and <dtml-let ...> is essentially shorthand for <dtml-let><dtml-set ...>
Now if every DTML object had a default empty local namespace, we could do away with Let entirely and just use Set.
Um. Couple of problems. First, the DTML implementation architecture doesn't really have an accessible notion of lexical scoping that can be used to determine this. Second, adding an extra namespace to every DocumentTemplate would be create a potentially high performance hit (because of all the alloc/free overhead being added to inner loops). However, if there was a way to fix both of the above, your proposal might work. I would vote to keep let, however, so that you have a way to get rid of variables you don't need.
This diverges here, since 'weight' is *only* an attribute of 'person', not a full member of the namespace. Of course, to complete the insanity of my new proposal, we could keep the colon notation as a compact way of defining/altering this sort of sub-namespace 8->
Ugh.
participants (2)
-
Evan Simpson -
Phillip J. Eby