RE: [Zope] Defining variables
-----Original Message----- From: Brian Lloyd [mailto:Brian@digicool.com] Sent: 13. juli 1999 23:47 To: 'Alexander Staubo'; Zope Mailing List (E-mail) Subject: RE: [Zope] Defining variables
Currently we have REQUEST.set(). This is nice, but I think there is a need for a general-purpose variable namespace that isn't related to REQUEST (plus the fact that typing "REQUEST.set(...)" all the time isn't so cool).
I have one specific case where it's simply arduous having to mix real REQUEST variables -- meaning those that come in through the query string or form data -- with actual request-related variables.
How about adding something like _.set()?
-- Alexander Staubo
Doesn't the Let tag basically accomplish what you are asking for? From the Let tag docs:
The problem is that the let and with tags are block tags. If I have numerous variables, that's a lot of blocks! Eg., <!--#let foo=1--> <!--#let foo=2--> <!--#let foo=3--> ... <!--#/let--> <!--#/let--> <!--#/let--> (And no, you can't convince to stop indenting. :-) Indenting is just part of the reason I think the "let" tag is inappropriate here. With the closing tag, that's just seven characters less than the REQUEST.set() alternative! Plus line break, that's actually five characters gained. Not much typing saved there. <!--#call "REQUEST.set('f', 1)"--> <!--#let f=1--><!--#/let--> I essentially want something like <!--#set foo=1--> <!--#set foo=3--> <!--#set foo=4--> or, as I outlined, something like _.set().
The let tag:
is a new tag that lets you create blocks like:
<!--#in "1,2,3,4"--> <!--#let num=sequence-item index=sequence-index result="num*index"--> <!--#var num--> * <!--#var index--> = <!--#var result--> <!--#/let--> <!--#/in-->
Which yields:
1 * 0 = 0 2 * 1 = 2 3 * 2 = 6 4 * 3 = 12
The #let tag works like the #with tag, but is more flexible in that it allows you to make multiple assignments, and allows you to chain assignments, using earlier declarations in later assignments. Notice inthe ablove example, the 'result' variable is based on 'num' and 'index', both of which are assigned in the same #let expression.
Syntacticly, each argument to be evalulated in the head of the let tag must be seperated by a newline. Enclosing an argument in double quotes causes it to be evaluated by the DTML expression machinery. Un-quoted arguments are referenced by name.
Is it just me, or is this newline-separation syntax really crazy? How does the "let" tag handle multiline expressions? Why not just use commas? It would mean alienating those suckers who actually use commas in object ids, but that's not a huge loss. ;-)
Evaluation is in sequence with the result of earlier assignments available to later ones. Later assignments can also override earlier ones, which can be helpful for longer step-by-step calculations. The variables thus set are in effect for the life of the <!--#let--> block.
Brian Lloyd brian@digicool.com Software Engineer 540.371.6909 Digital Creations http://www.digicool.com
-- Alexander Staubo http://www.mop.no/~alex/ "He could open a tin of sardines with his teeth, strike a Swan Vestas on his chin, rope steers, drive a steam locomotive and hum all the works of Gilbert and Sullivan without becoming confused or breaking down in tears." --Robert Rankin, _The Book of Ultimate Truths_
At 11:54 PM 7/13/99 +0200, Alexander Staubo wrote:
Syntacticly, each argument to be evalulated in the head of the let tag must be seperated by a newline. Enclosing an argument in double quotes causes it to be evaluated by the DTML expression machinery. Un-quoted arguments are referenced by name.
Is it just me, or is this newline-separation syntax really crazy? How does the "let" tag handle multiline expressions? Why not just use commas? It would mean alienating those suckers who actually use commas in object ids, but that's not a huge loss. ;-)
Um, the documentation quoted above is incorrect. I submitted a patch for the doc file the other day, but it has not been applied. Newlines are not required in order to seperate "let" arguments. The normal argument parsing of DocumentTemplate tags applies, except that "let" allows arguments to be repeated. I think the person writing the docs just assumed that newlines were required because all my examples used newlines and whitespace for clarity.
Indenting is just part of the reason I think the "let" tag is inappropriate here. With the closing tag, that's just seven characters less than the REQUEST.set() alternative! Plus line break, that's actually five characters gained. Not much typing saved there.
<!--#call "REQUEST.set('f', 1)"--> <!--#let f=1--><!--#/let-->
I essentially want something like
<!--#set foo=1--> <!--#set foo=3--> <!--#set foo=4-->
I'm planning to write a "set" tag that does exactly this. The tricky part is, it'll only be able to be used within the body of a "let" block, because it'll need to know what level of the namespace stack it can safely write to. It will do exactly what you want as long as there is at least *one* containing "let" block somewhere in the DTML namespace stack. It doesn't have to be in the same document or method, so long as the document or method is called from inside a let block somewhere. The only other way I see to handle it, is to have DocumentTemplates add an extra dictionary to the namespace stack at every level of calling stack - which is a heavy overhead to pay for such a feature, especially for those who don't use it! The "let" tag has to add a dictionary to the namespace stack anyway, and it also has the additional benefit of precisely scoping the applicability of the variable assignment. So "set" would never set anything globally, it would be strictly local to some precisely defined block. REQUEST.set would still be available for anything that really needed to be global. To give an example: <!--#let--> code... <!--#set foo="1"--> more code... <!--#set foo="3"--> still more code.. <!--#set foo="4"--> etc. <!--#/let--> As you can see, actually defining the variables in the let tag itself would be unnecessary. Although I've also thought it might be cool to require any variables you "set" to be defined by the "let", thus allowing a bit more safety. You see, one of the other tricky things about allowing "set" (in the general case), is that it breaks the "untrusted code" model of Zope. If method 1, written by user A, calls method 2, written by user B, and method 2 is sneaky and resets a variable used by method 1, then method 2 can potentially make method 1 do something it ain't supposed to. (Notice that setting things in the REQUEST object doesn't have this problem, because REQUEST is so far down in the namespace stack, AND if you're trying to be secure, you'll be wary of anything coming from the REQUEST object to begin with.) To make a safe "set" tag that deals with this situation requires more internal Zope Zen than I care to learn at this stage of things, because the stuff I use DocumentTemplates for doesn't use the Zope's "untrusted code" model. But, making "set" only valid inside a "let" block eliminates that problem, because you can always wrap a call to untrusted code in another let block so any changes it makes will be thrown away. Anyway, that's what I have in mind to implement, I'm open to suggestions as to how it might be done better.
participants (2)
-
Alexander Staubo -
Phillip J. Eby