RE: [Zope] Zope needs this (and Dynamo has it)
From: 'Martijn Faassen' [mailto:faassen@vet.uu.nl] Sent: Sunday, March 12, 2000 12:11 AM To: Zope Mailing List (E-mail) Subject: Re: [Zope] Zope needs this (and Dynamo has it)
[snip]
[snip explanation why open-source like collaboration is harder for languages]
It's hard for language *design*, yes, but it's less hard when you're doing language implementation (for instance a faster one), and it's easier still when you're writing libraries and such. And it does happen for language design as well -- the Python static type design is currently being fleshed out (in bursts) by the types-SIG (though of course Guido does final approval about what goes into Python proper).
Indeed, but do I need to remind you that we're still at version 1.52? :-) And as for your argument that OSS boosts language implementation, true in theory, but sitting down with a compiler and changing it, or building a compiler from scratch, is a daunting and time-consuming task. I have, certainly, thought about building a native-code compiler for Python. But no time right now. Your comments are well received. I hope I can put my own comments to shame in the future by committing some of my resources to the Python effort. As for the types-SIG, I've read through Guido's latest proposal, and found it so-so; I have some comments about the syntax -- which IMHO is heading in the right direction, but I feel it's still quite unpolished, like the new "decl" keyword and the very odd, un-Pythonic "->" operator. Other than that, it looks a lot like I had in mind myself. [Re: C++ extensions with Python]
There are various tools out there for Python which do offer this kind of functionality, though, I think? Check at the vaults of parnassus sometime: http://www.vex.net/parnassus
Not sure which you mean. Found this one: http://www.vex.net/parnassus/apyllo.py?i=52521115
Let me finish the last sentence first: I also have a database-centric Zope app that causing me headache. The ZODB is *way* too immature to replace a database right now -- fine for the kind of stuff that runs on zope.org, not for us. We're actually looking at alternative app servers and solutions (such as hardwired C++ CGI code) right now. It's a shame, and I'm fighting it, but we might end up with something like Dynamo.
I'll repeat my question; why not use a relational database? Do you need an object database? How is the ZODB too immature?
Interestingly enough, I'm discussing this with Jon Udell on his Byte newsgroups (go news.cmpnet.com). I'll quote something I wrote in this discussion, slightly edited for clarity: <quote> I can't easily tell Zope that objects of type A refers to objects of type B (mutual relationships), and that objects of type B should not be deletable as long as an object of type A is referring to it (referential integrity). The only kind of relationship Zope knows about is containment, a parent-child relationship. There is simply no other way for an object to refer to another object. Consider the case of news articles. Let's say articles should be able to hold multiple sections of text, as well as images. Assuming we use Z Classes and not Products, two solutions come to mind: Either (a) let an article be a descendant of Zope's folder or object manager classes, and thus contain any such sub-data as objects -- a design which currently is the most useful, but which has its shortcomings -- or (b) let sub-data exist as objects elsewhere in the ODB, and have string attributes on the article object that refer to their names, eg. an attribute "Illustrations" of type "lines" containing image IDs such as "mayor.jpg", "airplane.jpg" etc. This is obviously ugly -- for example, these image objects could be moved or removed and the article object would never know. As for dividing article texts into multiple sections (page 1, page 2 etc., with appropriate headings), this is obviously pretty simple with scheme (a), but in the case of (b), the text could exist in one large attribute, and some sort of page tagging system might be enforced -- or we could go all the way and do XML. So far, with these solutions, we'll survive. Cracks begin to show when we start thinking about organizing authors, publications, and document flow. Zope doesn't provide a framework to solve this things. Equally worse is that the ZODB hierarchy is so easily polluted with things that don't belong there. You end up putting a lot of objects in the root folder because they're needed globally -- and anyone who has used Zope will tell you that a folder becomes unwieldy and disorganized when it grows past 20+ objects. (Case in point: Personally, several of my Zope sites have a root-level Utils folder containing oft-used External Methods, because they tend to pollute the whole namespace.) Zope needs a multiple-root, "multihomed" hierarchy. Z Classes must be able to exist anywhere, not just in the one Products hierarchy. </quote> [Re: Python syntax issues]
I don't necessarily say they're _my_ problems, but some people think they are, and that counts. I don't miss "switch" myself, although I do miss a kind of enumerated type.
Like this?
FOO, BAR, BAZ = range(3)
[snip neat example of the use of eval() in Python]
No, although that's a clever trick. Hey, do it again! :-) What you cite above may mirror the effect of an enumerated type, but it doesn't contain any meta-information about the type itself: That is, FOO, BAR, BAZ are integers. They will fit into any integer expression and can be passed to any function taking integer arguments. The function won't balk if you pass a value from another "enumeration". Another problem with the above is that there is no way to ask Python to enumerate the values or names in the sequence, because its values are part of the top-level namespace -- I don't like that kind of namespace pollution. Instead, perhaps, this: class Enum: def __init__(self, Value): self.Value = Value def __int__(self): return self.Value class DeadParrot(Enum): FOO, BAR, BAZ = range(3) def PetShop(P): if int(P) == DeadParrot.FOO: print 'It''s resting.' D = DeadParrot(DeadParrot.FOO) PetShop(D) ...But hardly elegant.
I don't think you'll see protected members any time soon.
I think Zope's source code is one huge, glowing argument in favour of having protected members.
Why so? I myself think Zope's source is an argument for explicit interfaces. :)
The same side of two different coins, I think. :-)
Tuples are immutable, dicts and lists are mutable. Why? Because Guido says so. Jon Udell, I think it was, has argued that tuples are currently a redundant element in the language. Why have two kinds of lists? It just confuses people.
Well, tuples can be used as dictionary keys, lists cannot.
And that makes sense to you? I don't know the historical significance of tuples in Python -- I know the mathematical meaning, but Python tuples aren't quite it -- but it smells a lot like an interface that has been fit to the size of the implementation. A lot like, coincidentally, a procrustean bed. (Coincidentally because the term has popped up a lot lately; see the Byte thread.)
A syntax for declaring the mutability of types would be helpful in clearing out this mess. For example, you should be able to declare a dict to be immutable when passed to a certain function call -- ie., forcing a copy.
Forcing a *copy*, implicitly? But Python works with reference semantics only? It's be nice to have a way to declare stuff immutable, I think, but I'm not sure how often one would need to use it. There's something to say for knowing something's a tuple, instead of having a list and having to know whether it's immutable or not. Though perhaps that's not a big problem in practice.
I think the idea that mutability as a behaviour is distributed among primitives is, frankly, a questionable design choice. ;-)
Python has no "out" parameter, only "in" parameters that are mutable depending on the type of the object passed. The syntax I'm alluding to would effectively give you both "out" and "const" parameters.
(No, it would not -- it would effectively give you both "out" and *pass-by-value* parameters.)
But that might result in a lot of incomprehensible code. I'm not sure if I'm in favor of having 'out' parameters anyway.
The alternative is returning dictionaries or tuples, is it not? Maybe I'm not thinking in a Pythonic vein. Maybe A, B, C = GetABC() is more immediately grokkable than GetABC(A, B, C) # assuming these are "out" parameters Well. Sure it is. Damn, I think you're right. ;-) -- Alexander Staubo http://alex.mop.no/ "`Ford, you're turning into a penguin. Stop it.'" --Douglas Adams, _The Hitchhiker's Guide to the Galaxy_
Okay; off-topic or not, this looks like a fun thread, and I couldn't help but put my 0.02 in =) On Sun, 12 Mar 2000, Alexander Staubo wrote:
FOO, BAR, BAZ = range(3)
No, although that's a clever trick. Hey, do it again! :-)
What you cite above may mirror the effect of an enumerated type, but it doesn't contain any meta-information about the type itself: That is, FOO, BAR, BAZ are integers. They will fit into any integer expression and can be passed to any function taking integer arguments. The function won't balk if you pass a value from another "enumeration". Another problem with the above is that there is no way to ask Python to enumerate the values or names in the sequence, because its values are part of the top-level namespace -- I don't like that kind of namespace pollution.
Define "top-level namespace"? This is one of my favorite things about Python. You get the behavior you want below *for free*, because modules are done the Right Way (tm). '-- spam.py --- | FOO, BAR, BAZ = range(3) | | class Spam: | def __init__(self,foovar): | self.var=foovar `-- '-- eggs.py -- | import spam | can=spam.Spam(spam.FOO) `-- Alternatively, if eggs.py uses spam.py heavily, and is closely integrated with it: '-- eggs2.py -- | from spam import * | can=Spam(FOO) `-- I use both styles -- and you can choose! Clean namespaces, or terse syntax -- voluntary namespace pollution. You can even be selective (and this can really be fun) with expressions like: '-- eggs3.py | import spam | FOO=spam.FOO | Spam=spam.Spam `-- if you're heavily using FOO, but not BAR or BAZ in eggs ...
Well, tuples can be used as dictionary keys, lists cannot.
And that makes sense to you? I don't know the historical significance of tuples in Python -- I know the mathematical meaning, but Python tuples aren't quite it -- but it smells a lot like an interface that has been fit to the size of the implementation. A lot like, coincidentally, a procrustean bed. (Coincidentally because the term has popped up a lot lately; see the Byte thread.)
For some strange reason, although they have come under lots of fire, tuples make perfect sense to me. They don't seem to confuse new programmers much, either, since I've been introducing lots of people to python... For example; lists used as dictionary keys, if mutable, would have all sorts of confusing effects. Class instances, being explicitly references, don't have this problem; but if you pass a list in as a dictionary key, change the list... what should happen? class A: pass x=[] q=[] # you may want to think of that as # q=copy(x) # instead y={} z=() a=A() b=A() y[a]='a' y[b]='b' y[z]='z' # broken, but to prove the point y[x]='x' print y[q] The same thing goes for strings... I dunno. Type-defined mutability makes a lot of sense to me.
The alternative is returning dictionaries or tuples, is it not? Maybe I'm not thinking in a Pythonic vein. Maybe
A, B, C = GetABC()
Doesn't that just *look* nice? This is certainly how I'd write this happening in pseudocode, and I was overjoyed to find that python did it automatically.
is more immediately grokkable than
GetABC(A, B, C) # assuming these are "out" parameters
This style is BAD BAD BAD. I don't like having my variables manipulated by functions, if they're mutable... but it would be even WORSE to have the symbols actually changed! Nonsense like this contributes to some of the least readable code I've ever seen in C and C++ ... ugh. I *wish* you could return tuples in C++ =) (The worst part about this is that SOMEtimes, calling a function would create new variables for you, or reassign them, and sometimes it wouldn't... ugh. I don't like it.)
Well. Sure it is. Damn, I think you're right. ;-)
Glad you see it that way =) (Tuple unpacking is also brilliant, by the way, for constructs like for key,val in dict.items() ) -- ______ __ __ _____ _ _ | ____ | \_/ |_____] |_____| |_____| |_____ | | | | @ t w i s t e d m a t r i x . c o m http://www.twistedmatrix.com/~glyph/
From: zope-admin@zope.org [mailto:zope-admin@zope.org]On Behalf Of Glyph Lefkowitz Sent: Monday, March 13, 2000 8:50 AM To: Alexander Staubo Cc: 'Martijn Faassen'; Zope Mailing List (E-mail) Subject: RE: [Zope] Zope needs this (and Dynamo has it)
Okay; off-topic or not, this looks like a fun thread, and I couldn't help but put my 0.02 in =)
Interestingly enough, the US dollar dropped exactly 0.02 cents today from yesterday. ;-)
FOO, BAR, BAZ = range(3)
No, although that's a clever trick. Hey, do it again! :-)
What you cite above may mirror the effect of an enumerated type, but it doesn't contain any meta-information about the type itself: That is, FOO, BAR, BAZ are integers. They will fit into any integer expression and can be passed to any function taking integer arguments. The function won't balk if you pass a value from another "enumeration". Another problem with the above is that there is no way to ask Python to enumerate the values or names in the sequence, because its values are part of the top-level namespace -- I don't like that kind of namespace pollution.
Define "top-level namespace"? This is one of my favorite things about Python. You get the behavior you want below *for free*,
Not exactly. I suggest you read it again. What you and Martijn propose gives _no_ type safety at run-time. That's just like using constants, except they're wrapped in a module namespace. And they do pollute the top-level -- that is, the module-global -- namespace. Let me know when you find out how to enumerate the values in an enumerated type, and how to convert an enumerated value back to its name -- and then I might think you're up to something. Similarly to C++, Python classes behave like namespaces, so you can avoid pollution by wrapping the values in a class: class Foo: FOO, BAR, BAZ = range(3) and so you can enumerate the values as attributes.
because modules are done the Right Way (tm).
True. However, personally I prefer lexical scoping -- which I hear is under consideration for Python 3000 -- to the weird three-level namespace that Python provides. Having to import "global" variables because the compiler optimizes assignments is way uncool. [Re: Tuples, mutability]
For some strange reason, although they have come under lots of fire, tuples make perfect sense to me. They don't seem to confuse new programmers much, either, since I've been introducing lots of people to python...
For example; lists used as dictionary keys, if mutable, would have all sorts of confusing effects. Class instances, being explicitly references, don't have this problem; but if you pass a list in as a dictionary key, change the list... what should happen?
I'm not contesting that dictionary keys should be immutable, but rather that lists and tuples are nearly the same things (*nearly*, but not quite) with the crucial difference that lists are mutable. Why? There's no real design here. The only scientific answer to that question is "Because." -- Alexander Staubo http://alex.mop.no/
[Alexander Staubo, on Mon, 13 Mar 2000] :: I'm not contesting that dictionary keys should be immutable, but rather :: that lists and tuples are nearly the same things (*nearly*, but not :: quite) with the crucial difference that lists are mutable. Why? There's :: no real design here. The only scientific answer to that question is :: "Because." Seems like this discussion should be moved to c.l.p., but ... I don't understand your objection here. Tuples are immutable "by design," or "by definition" if you prefer. What alternative approach would you suggest? We certainly benefit from having a mutable sequence type designed to contain arbitrary objects. We benefit from having a high level mapping type designed into the language. You agree that dictionary keys must be immutable and you appear to agree that sequences make useful keys, as well. Under the covers, we also benefit from Python's design choice that assignments create object references and the design choice that dictionaries hash object references, not the objects themselves (which therefore requires immutable keys). So what's wrong with Guido setting things up this way and then saying, "hmmm, this is pretty cool, we just need an immutable sequence type for use in dictionary keys." It's a little like the Old Testament Creation mythology. God creates the heavens and the earth and he sees that it is good. But he decides he needs to populate it. He finds that one human type isn't enough -- it gets lonely. So it turns out that in His world, he needs two essentially similar types, but with a key difference. So Guido took a rib from the list and made the tuple. ;)
Glyph Lefkowitz wrote:
Okay; off-topic or not, this looks like a fun thread, and I couldn't help but put my 0.02 in =)
I'm off-topicing on. :)
You can even be selective (and this can really be fun) with expressions like:
'-- eggs3.py | import spam | FOO=spam.FOO | Spam=spam.Spam `-- if you're heavily using FOO, but not BAR or BAZ in eggs ... Python has a syntax for that:
import spam from spam import FOO But I suppose you knew that already? For any newbies that may be reading. :) Regards, Martijn
Sigh. I wish I had an nntp server I could use to read c.l.p... On Mon, 13 Mar 2000, 'Martijn Faassen' wrote:
I'm off-topicing on. :)
Python has a syntax for that:
import spam from spam import FOO
But I suppose you knew that already? For any newbies that may be reading. :)
Yeah, I knew that, but I love the fact that everything in python is really just assignment, so I do it explicitly a lot. I got carried away... :-) ______ __ __ _____ _ _ | ____ | \_/ |_____] |_____| |_____| |_____ | | | | @ t w i s t e d m a t r i x . c o m http://www.twistedmatrix.com/~glyph/
Alexander Staubo wrote: [snip me writing that open source does help with languages]
And as for your argument that OSS boosts language implementation, true in theory, but sitting down with a compiler and changing it, or building a compiler from scratch, is a daunting and time-consuming task.
But still people do change compilers! People have added garbage collecting to the Python interpreter, list comprehensions, and there's the whole huge stackless effort. I'm sure there are more examples in the past, for Python. Without open source, this wouldn't have happened.
I have, certainly, thought about building a native-code compiler for Python. But no time right now.
I've thought about it too, and no time either. Maybe we should get together some time. :) [snip tyepes-SIG I agree that the syntax could use some polishing. [extending Python easily with C++]
Not sure which you mean. Found this one: http://www.vex.net/parnassus/apyllo.py?i=52521115
I didn't mean any in particular, I just knew they existed. :) There's also a tool used to wrap the Qt interface in Python. [snip description of efficiency problem with Zope]
I'll repeat my question; why not use a relational database? Do you need an object database? How is the ZODB too immature?
Interestingly enough, I'm discussing this with Jon Udell on his Byte newsgroups (go news.cmpnet.com). I'll quote something I wrote in this discussion, slightly edited for clarity:
[snip discussion] That's indeed a shortcoming in Zope as it stands, but that's not an efficiency problem, is it? A faster Python wouldn't solve it. :)
[Re: Python syntax issues]
I don't necessarily say they're _my_ problems, but some people think they are, and that counts. I don't miss "switch" myself, although I do miss a kind of enumerated type.
Like this?
FOO, BAR, BAZ = range(3)
[snip neat example of the use of eval() in Python]
No, although that's a clever trick. Hey, do it again! :-)
FOO, BAR, BAZ = range(3) :)
What you cite above may mirror the effect of an enumerated type, but it doesn't contain any meta-information about the type itself: That is, FOO, BAR, BAZ are integers. They will fit into any integer expression and can be passed to any function taking integer arguments.
That's true, but please note that C's enum is used successfully and isn't checked either. [snip experiments] I agree it might be nice to have a more elegant way to deal with enumerated types. Perhaps as a result of static type checking extensions?
Why have two kinds of lists? It just confuses people.
Well, tuples can be used as dictionary keys, lists cannot.
And that makes sense to you? I don't know the historical significance of tuples in Python -- I know the mathematical meaning, but Python tuples aren't quite it -- but it smells a lot like an interface that has been fit to the size of the implementation. A lot like, coincidentally, a procrustean bed. (Coincidentally because the term has popped up a lot lately; see the Byte thread.)
Well, it makes sense to disallow mutable dictionary keys. You asked why have two kinds of lists, I tried to give the answer. Lists and tuples have been moving towards each other in recent Python versions, though; I believe originally only tuples supported unpacking. If there was somekind of mutability system in place that could replace tuples. [snip]
I think the idea that mutability as a behaviour is distributed among primitives is, frankly, a questionable design choice. ;-)
It's cute though, as immutable objects behave like pass by value objects do (except those darn tuples again, if they contain something mutable like a list or an instance). I think that's a neat idea. [snip discussion of grokkability]
Well. Sure it is. Damn, I think you're right. ;-)
*grins* Regards, Martijn
participants (4)
-
'Martijn Faassen' -
Alexander Staubo -
Glyph Lefkowitz -
Patrick Phalen