Re: packages vs. classes
On 5/23/06, Sam Vilain [EMAIL PROTECTED] wrote: Right, but we should really ship with at least a set of Meta Object Protocol Roles, that covers the core requirements that we will need for expressing the core types in terms of themselves; - classes and roles - attributes and methods - subsets (ie constraints/subtypes) - generics (including, by induction, nested generics) I *think*, at this point, that's all that are necessary. I would maybe add a protocol for instance creation. We have recently added that to Moose, and found it very useful in terms of abstracting out the kind of instance storage used (ARRAY based storage currently Just Works given the right Instance sub(meta)class). I see the instance protocol as being an important component of cross language runtime thing. If all instances conform to, or can be made to conform to, an base instance protocol, making Perl 6 objects which inherit from Python objects should be fairly easy. People can instantiate the roles that cover all that to an actual metaclass in whatever way they like (eg, Moose::Meta::Class-isa(Class::MOP::Class)), but not having to detect the type and then figure out how to talk to it for at least the core of the object system would be good. I think the roles can serve as the core interface nessecary to function with the base object system. As long as my metaclass .does() the correct role, it should be able to function in the object system. Of course the old garbage-in garbage-out rule applies, we should give you enough meta-rope to shoot your meta-self in your meta-foot. People can diverge completely with completely incompatible metaclasses that don't .do those roles, the only side effect of which being that people who write code for the standard Perl 6 metamodel will be incompatible, and maybe some ways of setting up the class won't work without another layer of trickery. I *think* that's what you're getting at. Of course, it shouldn't be prohibited just because it smells. I am not sure I like this, incompatible metaclass issues are really really tricky and hard to debug (aka - smells *really* bad). And the system needed to support them really can bloat the metamodel internals in a nasty way. There are several papers out there on the subject, none of which IMO provide a satisfactory solution. The problem then becomes compounded by introducing the Python and Ruby metamodels into the fray. Having a single compatability level made out of roles is not that much of a restriction really, and keeps much of the system interals clean and orderly. It also makes it much easier for use to add new metamodels from other languages by just by writing a layer to map to the core metamodel roles. - Stevan
Re: packages vs. classes
--- Stevan Little [EMAIL PROTECTED] wrote: On 5/23/06, Sam Vilain [EMAIL PROTECTED] wrote: People can diverge completely with completely incompatible metaclasses that don't .do those roles, the only side effect of which being that people who write code for the standard Perl 6 metamodel will be incompatible, and maybe some ways of setting up the class won't work without another layer of trickery. I *think* that's what you're getting at. Of course, it shouldn't be prohibited just because it smells. I am not sure I like this, incompatible metaclass issues are really really tricky and hard to debug (aka - smells *really* bad). And the system needed to support them really can bloat the metamodel internals in a nasty way. There are several papers out there on the subject, none of which IMO provide a satisfactory solution. The problem then becomes compounded by introducing the Python and Ruby metamodels into the fray. Having a single compatability level made out of roles is not that much of a restriction really, and keeps much of the system interals clean and orderly. It also makes it much easier for use to add new metamodels from other languages by just by writing a layer to map to the core metamodel roles. my $.02 I'd say a more standard system is much better, so long as we leave a standard set of hooks by which someone can insert a nonstandard setup. A small API isn't a huge bloat, and is worth it, though I agree that a full system might actually be counterproductive. And by all that I've seen lately, the whole language is pretty malleable that way; those who really want the nonstandard model can take the small overhead hit of whatever internal shenanigans they need to implement, and just about anything like that can be stuffed into a module now, can't it? So the upshot is, a standardized metamodel seems like the way to go to me /my $.02 ot And Congrats again, gramps. May your new little one be as loved as the language you've also labored so much to guide to maturity. ;o] /ot Paul on est aisément dupé par ce qu'on aime -- Molière (one is easily fooled by that which one loves) Increase in wisdom can be measured accurately by the corresponding decrease in anger. -- Friedrich Nietzsche There are trivial truths and there are great Truths. The opposite of a trival truth is obviously false. The opposite of a great Truth is also true. -- Neils Bohr Real friends are those whom, when you must inconvenience them, are bothered less by it than you are. -- me. =o) Hodges' Rule of Thumb: Don't expect reasonable behavior from anything with a thumb. __ Do You Yahoo!? Tired of spam? Yahoo! Mail has the best spam protection around http://mail.yahoo.com
Re: packages vs. classes
Larry Wall wrote: 'Course, I left out everything about prototype objects there... The name Foo also (in context) represents an uninitialized object of the class in question. Any object, initialized or not, can get at its type handlers by saying Foo.meta $foo.meta and, in fact, the Foo.^bar syntax is just short for Foo.meta.bar. Perhaps saying it is like: Foo.meta.get_attribute(bar) Would be safer. Don't want to stomp on the meta-objects. [...] of the actual magic being defined elsewhere. It would be possible to access classes et al. only via the mechanisms supplied by the metaobject protocols, but that would be kind of like the bad old [...] Right, but we should really ship with at least a set of Meta Object Protocol Roles, that covers the core requirements that we will need for expressing the core types in terms of themselves; - classes and roles - attributes and methods - subsets (ie constraints/subtypes) - generics (including, by induction, nested generics) I *think*, at this point, that's all that are necessary. They are actually quite a useful set for the concerns I raised earlier about automatically inferring relational information from the metamodel (if only I knew these terms back then... ;)) http://groups.google.com/groups?threadm=200303042358.56560.sam%40vilain.net People can instantiate the roles that cover all that to an actual metaclass in whatever way they like (eg, Moose::Meta::Class-isa(Class::MOP::Class)), but not having to detect the type and then figure out how to talk to it for at least the core of the object system would be good. People can diverge completely with completely incompatible metaclasses that don't .do those roles, the only side effect of which being that people who write code for the standard Perl 6 metamodel will be incompatible, and maybe some ways of setting up the class won't work without another layer of trickery. I *think* that's what you're getting at. Of course, it shouldn't be prohibited just because it smells. On different note, there should be nice, per-class ways to make type constraints not simply code blocks - otherwise too much reverse engineering will be required to do the final stage of compiling typesafe code, where you close the classes and discard all the runtime type checks. An easy example of this is generics. With where, this is what you write (ignore the syntax errors for now): class Array of Str is Array where { $_.isa(Str) for @$_ } But that sucks, because that information about the type of the container is buried deep within the code reference, is slow, and we can't build our methods with the right signatures. So, we write; role Array[::T] { ... } class Array of Str does Array[Str]; Great. Now that information is available to Array in a structured manner and the signatures can be built correspondingly. But to represent the core types like Mapping or Set, we also need, for instance, the unique constraint to be represented as an object, not a code block: For instance, role Mapping[::T1, ::T2] does Coll[::T1, ::T2] where Unique(0); The where Unique(0) is the important bit. What is Unique, and who uses it? In my prototypes, I've been considering it being the job of the composing class or role to handle that, as a meta-object method call. So, the above might call Coll.meta.Unique(0) (look, I'm stomping all over the meta-object now) during the composition of the Mapping role, and it uses this to affect the methods that it builds until you get something that behaves not entirely quite unlike a Mapping. However feel free to continue to handwave for now. Personally I'd like to see this synoptic before the Perl 6.0 release, to avoid the mistakes of other (*cough* C# *cough* Java 1.5 *cough*) languages that slipped on getting the generics in their libraries, to their ultimate detriment. Sam.
Re: packages vs. classes {long}
On Fri, May 19, 2006 at 05:05:02PM -0700, Larry Wall wrote: So what's in a name? One could say that .meta is functioning more like a name sigil than like a method, and the Real Name of the metaobject is Foo::^Bar or some such, if it needs a name. Method, I like. Stealth sigil, I don't like. Generally, dependence on names for proper functioning of any programming construct -- variable, classe, whatever -- is in my experience almost invariably a design flaw, which ends up being rectified eventually (unless the enclosing system dies first), sometimes at significant cost to the thematic coherence of the system. For example, Perl 5 acquired references, and made anonymous subroutines, arrays, and hashes convenient. Where the language did not make something anonymous, modules came to the rescue (e.g. IO::Handle). I don't have to tell _you_ how much of Perl 4 became either vestigial or embarrasing in the transition, and how frustrating a _partial_ adaptation to anonymity became. Similarly, while it's taken decades, Unix variants are finally coming around to making most filesystem operations available on file descriptors rather than only on names. (fchown, fchmod, flink, etc.) So, if you want arbitrary_expression.meta to work, I think you should bite the bullet and admit that it actually *is* a method, or attribute, or anything else that's value-derived ... as long as it's not name-derived. You can't sigilize a name that isn't there. Then maybe Foo::Bar is just a strange hash. Or maybe it has its own sigil. But from the viewpoint of Dorothy the programmer, it's the package that presents the public interface Oz::Wizard, and it's the metaobject that's trying to hide behind the metacurtain. I think I don't understand you. However, if I do understand you, I disagree. Think through the use case of the entirely anonymous class -- the class which is not only nameless in the end, but which never had a name to begin with. (I'm not very familiar with prototype-based programming, but if I have the right inkling, anonymous prototype objects might even be the norm. But at this point I've begun speculating; so if that's wrong, ignore it.) Such an anonymous class, and objects of such a class, respond to named methods, to be sure; but the class *itself* has no name, and never did. Where do its methods live? Perhaps in a package, but of necessity that package has no name. (If the package name was merely obscure as opposed to nonexistent, it could not be garbage-collected when it was no longer in use, as its parent would continue to refer to it.) Furthermore, and perhaps most persuasively, I can easily imagine meta objects that have no use for a package at all, or that require several packages to respresent the partitioning of various subfunctions. Parrot's classes may be such metaobjects soon, as the HLL developers clamor to have the names introduced by the Parrot implementation completely segregated from their own work areas. Thus, choosing a _package_ as the owner of the primary entry point to a class's data structures -- that is, in the common case, it's name -- makes little sense to me. - At the risk of plowing ground that has already been sold to developers: I would suggest that the type object in Perl 6 might well be the point of entry for the suite of (type,meta,package). The relationships would work like so: type object -- meta object {e.g. Class} -- package {optional} \--- more packages? {possible} Note that the package(s) is (are) optional. Some metaobjects won't need them. For example, in Parrot, the metaobject for namespace doesn't point to a namespace object, for chicken-and-egg reasons. OTOH, it's possible for some metaobjects to need more than one. Getting back to the common case: the default behavior of Class creation will include creating names for the type object and the package object, and perhaps also for the metaobject, e.g.: Oz::Wizard:: ---+ | Oz::Wizard | | | v v type object -- Class -- package ^ | Oz::^Wizard? ---+ Details of this second diagram are for illustration purposes only, to show that I'm not suggesting that everything be anonymous. My point is that the type system should (must!) still work even if no such names are ever assigned. I don't know the p6 lexical magic required to make it happen, but if the Wizard type object is anonymous, it should still be possible to say my arbitrary_expression_returning_Wizard $gandalf; and similarly it should be possible to use arbitrary expressions for all other type/meta operations including introspection, modification, subclassing, etc. -- Chip Salzenberg [EMAIL PROTECTED]
Re: packages vs. classes
On Thu, May 18, 2006 at 03:17:36PM -0700, Chip Salzenberg wrote: : What's the relationship in perl6 between namespaces and classes? Hmm, well, that's hard to put one's finger on, but to the first approximation namespaces are for declarational names, while classes can really only name things operationally. So packages, modules, classes, roles, subsets, enums, etc. all pretend they are packages for purposes of naming from a global root. Any extra semantics are defined by the objects that support each type of declarator. But as container objects they all support the Package role, or some such. The situation is analogous to the filesystem. We have a /proc filesystem nowadays because it's convenient to name certain abstractions in the OS as if they were ordinary files despite most of the actual magic being defined elsewhere. It would be possible to access classes et al. only via the mechanisms supplied by the metaobject protocols, but that would be kind of like the bad old days when ps(1) had to rummage around in /dev/kmem to figure out what to say. : For example, given: : : package Foo { sub bar {...} } : class Corge { method grault {...} } : : Is the full name of foo Foo::foo? Yes, assuming that Foo is a top-level package name, and that you meant bar. : What's the full name of grault? Just as if the class were a package: Corge::grault Though nowadays for clarity we often write these as Foo::bar Corge::grault instead. : Is there a common role that Foo and Corge both do? As bare names they can be taken in context to mean either the package or the type. When necessary we can disambiguate these: Foo.^{$x} call .{$x} on the type metaobject Foo::{$x} call .{$x} on the package object Contextually, though, a bare package name is generally taken to be a pun on the type unless followed by ::. So my Corge $foo; is not really saying much about the Corge package except that there has to be one, and to the extent that the Corge type supports certain methods at declaration time, those names appear to be in the Corge package. It's quite possible that the Corge type has metamethods that let us get at unnameable behavior, but that would generally be construed as violating encapsulation--hopefully for a good reason--but the public interface of a type should generally be presented declarationally via packages and the objects they contain. A consequence of all this is that when you use any type declarator: module M ... class C ... role R ... subset S ... enum E ... the name is referring to both the package and the type simultaneously, and the type is allowed to present whatever public interface it likes, generally via the package. It also presents an internal declarational interface to the innards of the declarator, so that metamethods like has and does and is are given meaning in your class declaration. The type also presumably controls which traits make sense on various declarations. Interestingly, even the tag groups of module exports are done with the package interface currently. The is export (:DEFAULT) trait merely pokes the current name down into the ::DEFAULT subpackage of the module, and it hopefully can become very efficient to import a prepackaged set of symbols as a lump. If this isn't answering what you were asking, please ask s'more, and I'll try to reply when I'm not busy having a grandbaby. Larry
Re: packages vs. classes
'Course, I left out everything about prototype objects there... The name Foo also (in context) represents an uninitialized object of the class in question. Any object, initialized or not, can get at its type handlers by saying Foo.meta $foo.meta and, in fact, the Foo.^bar syntax is just short for Foo.meta.bar. The Foo object maybe therefore be used to reason about objects of a class, but the Foo object itself is not the class. Foo.meta is the real class object. Foo itself is just a Foo that hasn't been defined yet. Foo.isa(Class) is false, because there's no Class type in Perl 6 as far as Perl 6 is concerned. The type of metaobject Foo.meta might be called Class if that's what the metaobject protocol decides it should be, but Perl the Language doesn't care. If so, then Foo.meta.isa(Class) would be true. But Foo.isa(Class) is still false. The purpose of all this is to support prototype-based programming as well as class-based programming. Assuming either one or the other (in the absence of appropriate declaration) is a kind of encapsulation violation of the .meta interface. Larry
Re: packages vs. classes
On Fri, May 19, 2006 at 12:35:11PM -0700, Larry Wall wrote: If this isn't answering what you were asking, please ask s'more, and I'll try to reply when I'm not busy having a grandbaby. adCONGRATULATIONSvance :-) Packages, modules, classes, roles, subsets, enums, etc. all pretend they are packages for purposes of naming from a global root. Any extra semantics are defined by the objects that support each type of declarator. But as container objects they all support the Package role, or some such. The above paragraph is about half of what I was asking. It contains a bit of bad news: it imples that Parrot can't assume that each HLL only has one namespace-ish class. But I think that particular guilletine blade was already on its way down. The other half: Your distinction between the type object and the class object is more than a little disturbing to the current design issues I'm facing. You write: Foo.^{$x} call .{$x} on the type metaobject Foo::{$x} call .{$x} on the package object Two and a half questions and a proposal on that. Q1: How do you disambiguate type from package in the Perl 6 namespace? Given a class Foo::Bar, is Foo::Bar:: the package and Foo::Bar the type? Or what? Q1.5: If I asked why the circumflex is in there, would I regret it? Q2: What is the object reference relationship among Foo::, Foo::Bar the type, and Foo::Bar:: ? (Where are the object reference arrows?) Proposal: In Parrotland, it seems at the moment that Parrot type objects might be best implemented as specializations of Parrot namespace objects. Consider: Defining a new class creates exactly one named object. Aliasing (e.g. importing) a class requires exactly one namespace operation. Removing a class requires deleting exactly one namespace entry. There is no confusion as to which object is the class object. There is no confusion as to what should be looked up where. As something of a probing attack -- to provoke informative rebuttal -- I'd like to propose that type objects should do Package. What say? -- Chip Salzenberg [EMAIL PROTECTED]
Re: packages vs. classes
On Fri, May 19, 2006 at 12:53:29PM -0700, Larry Wall wrote: and, in fact, the Foo.^bar syntax is just short for Foo.meta.bar. So, you anticipated my half-question. The type of metaobject Foo.meta might be called Class if that's what the metaobject protocol decides it should be, but Perl the Language doesn't care. If so, then Foo.meta.isa(Class) would be true. But Foo.isa(Class) is still false. OK, in my previous message, you should apparently read metaobject for type object. But I think the questions still apply, as does the proposal that all _metaobjects_ that currently are correlated with packages should instead just _do_ Package. -- Chip Salzenberg [EMAIL PROTECTED]
Re: packages vs. classes
On Fri, May 19, 2006 at 02:51:55PM -0700, Chip Salzenberg wrote: On Fri, May 19, 2006 at 12:53:29PM -0700, Larry Wall wrote: The type of metaobject Foo.meta might be called Class if that's what the metaobject protocol decides it should be, but Perl the Language doesn't care. If so, then Foo.meta.isa(Class) would be true. But Foo.isa(Class) is still false. OK, in my previous message, you should apparently read metaobject for type object. But I think the questions still apply, as does the proposal that all _metaobjects_ that currently are correlated with packages should instead just _do_ Package. And again I must correct myself, the above doesn't make sense. Based on what I'm seeing, the Perl 6 type object is the thing that claims the primary name associated with a class. Foo::Bar is the type object. The metaobject seems to be anonymous. And the package seems to be fairly questionable... given how generic you want to be, the Perl 6 implmentation probably can't assume that there is exactly one package associated with a given type object, either directly or indirectly. -- Chip Salzenberg [EMAIL PROTECTED]
Re: packages vs. classes
On Fri, May 19, 2006 at 03:25:43PM -0700, Chip Salzenberg wrote: : Based on what I'm seeing, the Perl 6 type object is the thing that claims : the primary name associated with a class. Foo::Bar is the type object. : The metaobject seems to be anonymous. And the package seems to be fairly : questionable... given how generic you want to be, the Perl 6 implmentation : probably can't assume that there is exactly one package associated with a : given type object, either directly or indirectly. I think the only constraint on it is that Foo::Bar.meta can't point to two different objects. But .meta isn't a real method--it's more like a notation representing the blessing, in P5 terms. Certainly different packages could share the same .meta object if the particular kind of metaobject it points to chooses to store all the state in the package rather than the metaobject. In that sense the package is just a handy place to put publicly named class state. Going the other way, $object.meta makes no guarantees that the metaobject it points to has any name. Could be completely anonymous, or an eigenclass, or whatever. Presumably metaobjects that are associated with a package can tell you that name somehow, perhaps even by stringification. But which operations can succeed through .meta will depend on what .meta.isa, as it were. In this, Perl is so OO that it even encapsulates the OO, so Perl is agnostic even about the extent to which Perl is an OO language. In Perl 6, all objects are blessed equally, but some objects are blessed more equally than others... So what's in a name? One could say that .meta is functioning more like a name sigil than like a method, and the Real Name of the metaobject is Foo::^Bar or some such, if it needs a name. Then maybe Foo::Bar is just a strange hash. Or maybe it has its own sigil. But from the viewpoint of Dorothy the programmer, it's the package that presents the public interface Oz::Wizard, and it's the metaobject that's trying to hide behind the metacurtain. And as in the original, sometimes the official story needs a bit of tweaking. But for now the Package of Oz is great and glorious, and doubtless you should be quaking in fear. :) All that and several bucks'll get you a Starbucks... Larry
packages vs. classes
On Thu, May 18, 2006 at 02:52:53PM -0700, Chip Salzenberg wrote: { copied to P6L for the use case question below } Well, that message wasn't, but this one is... What's the relationship in perl6 between namespaces and classes? For example, given: package Foo { sub bar {...} } class Corge { method grault {...} } Is the full name of foo Foo::foo? What's the full name of grault? Is there a common role that Foo and Corge both do? -- Chip Salzenberg [EMAIL PROTECTED]