Re: MML dispatch
HaloO Larry, you wrote: On Tue, Jul 12, 2005 at 08:13:22PM +0200, "TSa (Thomas Sandlaß)" wrote: : Actually it's a pitty, that the multi method call syntax isn't as : rich as the single method call syntax where we have .?method, .+method : and .*method. Something like (Snoopy, Mr_PotatoHead, HopeDiamond).*foo : doesn't exist, right? Or is it foo.*(Snoopy, Mr_PotatoHead, HopeDiamond)? It doesn't seem to make much practical sense. Multimethods are generally written to be exclusive of ancestral methods. Ordinary methods are generally written to be cumulative with ancestral methods. Interesting that we are thinking in orthogonal ways. I was arguing for a syntax that allows the caller to prevent 'no method' and 'method ambiguous' errors with .?() and .+() respectively. And .*() would prevent both. In the ambiguous case all applicable targets would be called in an undefined order. Is there also an answer to the odering versus metric question? Why was the former rejected and the latter choosen? -- TSa (Thomas Sandlaß)
Re: MML dispatch
Mark Reed asked: OK, sorry if I missed this in an earlier discussion. For purposes of calculating this Manhattan distance, I gather that we're treating lists of N arguments/parameters as points in N-space. I further assume that the monoaxial distance between a parameter coördinate and the corresponding argument coördinate - the distance between two types, where the types are known to be assignment-compatible - is the number of inheritance steps between them? Correct. This is the usual underlying metric, regardless of MMD scheme. And one more dumb question: why is it that the L[1] metric is superior to the L[2] metric for this purpose? The use of summed lineal distance (L[1]) rather than RMS distance (L[2]) probably *isn't* superior as a closeness measure. But it's computationally much simpler (and hence likely to be more efficient), it doesn't suffer from precision issues in "photo finishes", and it is almost certainly easier for the average programmer to predict correctly. That said, I'd have no *particular* objection to an MMD implementation that used RMS inheritance distance as its metric, provided the dispatch performance was not appreciably worse. Damian
Re: MML dispatch
TSa (Thomas Sandlaß) wrote: Unique least-inherited most-specialized match, or default Do I read this correctly as dispatching partly in the class hierarchy and partly in the type hierarchy? Err. The class hierarchy *is* the type hierarchy in Perl 6. Or do you mean with 'least-inherited' most specific non-where type and with 'most-specialized' the strictest where clause? I mean: least cumulative derivation distance summed over the set of parameter types, with greatest *number* of parameter specializations as a tie-breaker (if required). Damian
Re: MML dispatch
TSa (Thomas Sandlaß) wrote: Is there also an answer to the odering versus metric question? Why was the former rejected and the latter choosen? MMD is really just a partitioning of the discrete N-dimensional search space formed by the class hierarchies of the N parameters of a multimethod/multisub. A linear summation (or other geometric) metric ensures that the search space is completely partitioned by whatever variants are defined for a given multi. A "pure ordering" dispatch scheme generally leaves large regions of the search space unclaimed by any variant, necessitating the definition of numerous extra variants solely for the purpose of disambiguation. This larger number of ambiguous (and therefore undispatchable) argument lists reduces the utility and forward compatibility of "pure ordering" multiple dispatch, by forcing the developer to specify a much larger number of variants, most of which will then have to delegate to a single variant (which is typically the one a linear metric would have chosen anyway). There's a strong parallel with allowing shift-reduce ambiguities in LR parsers. You *could* make the developer explicitly cover all the possible interpretations of a given sequence of symbols, but only at the cost of exponentially increasing the number of grammar rules being required. Similarly, since the number of potential variants is the Cartesian product of the total sizes of the class hierarch(y|ies) for each parameter position, getting adequate coverage of the MMD search space quickly becomes tedious if most of the search space is (by default) ambiguous, as in "pure ordering" dispatch schemes. One very common problem with pure ordering schemes is that subsequent changes in one or more class hierarchies can cause previously unambiguous cases to become ambiguous, by extending a zone of ambiguity in the search space. In contrast, because a metric approach always fully partitions the entire search space, hierarchy changes may alter where a particular call dispatches to, but only ever to a "closer", more appropriate variant. Note too that Perl 6 *will* still support a form of "pure ordered" dispatch--a left-most-closest-match scheme like that used by CLOS--via "invocant groups": multi sub Foo(A: B: C:) {...} multi sub Foo(A: D: C:) {...} multi sub Foo(F: B: G:) {...} This, of course, is not "global pure ordering", but rather "left-biased pure ordering". To summarize: pure ordering renders more of the MMD search space "ambiguous", which is potentially safer but much less DWIMish. Metric schemes have far fewer ambiguities and usually dispatch in an predictable way. Metric schemes can still provide pure-ordering analyses via static analysis tools or special warning modes, but pure ordering schemes can't avoid ambiguities or DWIM. Of course, none of this prevents: use MMD ; Damian
Re: MML dispatch
HaloO Damian, thank you very much for your explaination. I just want to hint the Perl6 community to the fact that there exists a US patent on geometric MMD: http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO2&Sect2=HITOFF&p=1&u=/netahtml/search-bool.html&r=1&f=G&l=50&co1=AND&d=ptxt&s1=ferragina.INZZ.&OS=IN/ferragina&RS=IN/ferragina I haven't check the relevance to Perl6 yet. Has someone access to the STOC'99 paper? -- TSa (Thomas Sandlaß)
Re: User-defined infix subs/methods?
On Tue, 12 Jul 2005, Larry Wall wrote: Good, I'd forgotten about that. Which means that it's even harder for someone to compile a module in a "strange" dialect, since they'd essentially have to write their own version of "use" that forces recompilation ("reuse", if you will). And the harder we make it to write "reuse", the better. IIUC this will introduce a certain degree of asymmetry though, in that in some sense p6 will be extremely generous in giving users the ability to use whatever dialect/syntax modification they like in their programs but just at the same time it will try to make it hard for them to do so when refactoring code into suitable modules. Ain't it so? Michele -- Either of these mechanisms should be available in IE (after sacrificing a suitable animal to XP SP2, I suppose). - Alan J. Flavell in clpmisc, "Re: character encoding in CGI.pm"
Re: Perl 6 Summary for 2005-07-05 through 2005-07-12
Damian Conway wrote: Important qualification: Within a method or submethod, C<.method> only works when C<$_ =:= > $?SELF>. C<.method> is perfectly legal on *any* topic anywhere that $?SELF doesn't exist. Just to be clear, this includes any method/submethod with an explicitly named invocant, I hope.
Re: User-defined infix subs/methods?
Hi, Michele Dondi wrote: >> Good, I'd forgotten about that. Which means that it's even harder >> for someone to compile a module in a "strange" dialect, since they'd >> essentially have to write their own version of "use" that forces >> recompilation ("reuse", if you will). And the harder we make it to >> write "reuse", the better. > > IIUC this will introduce a certain degree of asymmetry though, in that > in some sense p6 will be extremely generous in giving users the > ability to use whatever dialect/syntax modification they like in their > programs but just at the same time it will try to make it hard for > them to do so when refactoring code into suitable modules. Ain't it > so? no, if I understood Larry correctly, you can of course write a nice grammar-modifying module, but other modules you use() still use Perl 6's standard grammar. E.g.: use Grammar::Ruby; # Ruby syntax from here on: proc { |a| puts a + 1 }.call 3# 4 use SomeOtherModule # SomeOtherModule.pm will be parsed using the standard grammar, # *not* Grammar::Ruby. If you wanted the compiler to parse SomeOtherModule.pm using Ruby's grammar, you'd have to write: use Grammar::Ruby; reuse SomeOtherModule --Ingo -- Linux, the choice of a GNU | Row, row, row your bits, gently down the generation on a dual AMD | stream... Athlon!|
Re: Perl 6 Summary for 2005-07-05 through 2005-07-12
Dave Whipp skribis 2005-07-13 8:44 (-0700): > > Within a method or submethod, C<.method> only works when C<$_ =:= > > $?SELF>. > >C<.method> is perfectly legal on *any* topic anywhere that $?SELF > >doesn't exist. > Just to be clear, this includes any method/submethod with an explicitly > named invocant, I hope. No, $?SELF exists in every method. It's not the *default* invocant variable, it's the *always there* invocant variable. There is no default variable anywhere in the language that isn't $_. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
RE: DBI v2 - The Plan and How You Can Help
Sorry, instead of implicit 'commit', I mean to say implicit conversion. - Ron Reidy Lead DBA Array BioPharma, Inc. -Original Message- From: Reidy, Ron Sent: Wednesday, July 13, 2005 9:06 AM To: Sam Vilain; Dean Arnold Cc: dbi-users@perl.org; dbi-dev@perl.org; perl6-language@perl.org Subject: RE: DBI v2 - The Plan and How You Can Help -Original Message- From: Sam Vilain [mailto:[EMAIL PROTECTED] Sent: Tuesday, July 12, 2005 5:04 PM To: Dean Arnold Cc: dbi-users@perl.org; dbi-dev@perl.org; perl6-language@perl.org Subject: Re: DBI v2 - The Plan and How You Can Help >Dean Arnold wrote: >> RE: LOBs and "SQL Parse Trees": having recently implemented >> LOB support for a JDBC driver (and soon for a DBD), I can assure >> you that SQL parse trees are unneeded to support them. For databases > or this; >SELECT > * >FROM > FOO >WHERE > SOME_DATE_COLUMN > ? > SOME_DATE_COLUMN is the database native date type. On Oracle you'll > need to convert the ? to a 'TO_DATE(?)'. No you do not. The SQL engine will perform an implicit commit of the data. - Ron Reidy Lead DBA Array BioPharma, Inc. > Sam. This electronic message transmission is a PRIVATE communication which contains information which may be confidential or privileged. The information is intended to be for the use of the individual or entity named above. If you are not the intended recipient, please be aware that any disclosure, copying, distribution or use of the contents of this information is prohibited. Please notify the sender of the delivery error by replying to this message, or notify us by telephone (877-633-2436, ext. 0), and then delete it from your system. This electronic message transmission is a PRIVATE communication which contains information which may be confidential or privileged. The information is intended to be for the use of the individual or entity named above. If you are not the intended recipient, please be aware that any disclosure, copying, distribution or use of the contents of this information is prohibited. Please notify the sender of the delivery error by replying to this message, or notify us by telephone (877-633-2436, ext. 0), and then delete it from your system.
Re: User-defined infix subs/methods?
On Wed, Jul 13, 2005 at 05:10:14PM +0200, Michele Dondi wrote: : On Tue, 12 Jul 2005, Larry Wall wrote: : : >Good, I'd forgotten about that. Which means that it's even harder : >for someone to compile a module in a "strange" dialect, since they'd : >essentially have to write their own version of "use" that forces : >recompilation ("reuse", if you will). And the harder we make it to : >write "reuse", the better. : : IIUC this will introduce a certain degree of asymmetry though, in that in : some sense p6 will be extremely generous in giving users the ability to : use whatever dialect/syntax modification they like in their programs but : just at the same time it will try to make it hard for them to do so when : refactoring code into suitable modules. Ain't it so? Well, yes and no. No, it just means you need to make sure you copy the "pedigree" into the new module, if you want the same language. Since we have policy modules, this could be as simple as copying a single "use MyLanguage;". I don't mind making some of the pedigree information indirect like that, as long as the indirection itself is explicit. But I will always resist any proposal to move pedigree information out into the implicit environment. That would be as useful as URI you don't know the root of. It would be a good way to fragment the Perl community into a tower of babble. That being said, yes, it will make refactoring harder to the extent you've mixed the language pedigree in with the actual code you're trying to refactor. But then, detangling that sort of mixup is precisely what refactoring is all about, ain't it? Larry
RE: DBI v2 - The Plan and How You Can Help
-Original Message- From: Sam Vilain [mailto:[EMAIL PROTECTED] Sent: Tuesday, July 12, 2005 5:04 PM To: Dean Arnold Cc: dbi-users@perl.org; dbi-dev@perl.org; perl6-language@perl.org Subject: Re: DBI v2 - The Plan and How You Can Help >Dean Arnold wrote: >> RE: LOBs and "SQL Parse Trees": having recently implemented >> LOB support for a JDBC driver (and soon for a DBD), I can assure >> you that SQL parse trees are unneeded to support them. For databases > or this; >SELECT > * >FROM > FOO >WHERE > SOME_DATE_COLUMN > ? > SOME_DATE_COLUMN is the database native date type. On Oracle you'll > need to convert the ? to a 'TO_DATE(?)'. No you do not. The SQL engine will perform an implicit commit of the data. - Ron Reidy Lead DBA Array BioPharma, Inc. > Sam. This electronic message transmission is a PRIVATE communication which contains information which may be confidential or privileged. The information is intended to be for the use of the individual or entity named above. If you are not the intended recipient, please be aware that any disclosure, copying, distribution or use of the contents of this information is prohibited. Please notify the sender of the delivery error by replying to this message, or notify us by telephone (877-633-2436, ext. 0), and then delete it from your system.
Method Resolution Order question
Hello, More questions for the metamodel. I am trying to add proper submethod and private method handling and I have a question about method resolution order as a whole. I asked a similar question last week, but this time I have more details :) Given this class: class Foo { submethod bar { ... } method bar { ... } } and given this code: Foo.new().bar() What should happen? The Syn/Apoc seem to indicate that methods and submethods of the same name can coexist. So the class definition itself is legal. However, it brings up an issue when it comes time to call bar(). Should submethod bar() be called first, then method bar() after it? Should method bar() be called first, then submethod bar() after it? Can submethods only be called from within the class (like private methods)? And if submethods can only be called from within the class, then how do I handle this: class Foo { submethod bar { ... } method bar { ... } method baz { $?SELF.bar() } } Foo.new().baz() Thanks, Stevan
Re: MML dispatch
On Wed, Jul 13, 2005 at 06:11:32PM +1000, Damian Conway wrote: : TSa (Thomas Sandlaß) wrote: : : >>Unique least-inherited most-specialized match, or default : > : > : >Do I read this correctly as dispatching partly in the class hierarchy : >and partly in the type hierarchy? : : Err. The class hierarchy *is* the type hierarchy in Perl 6. Implicit is that role distance is N + the distance to the nearest class that incorporates that role for small values of N. If class Dog does role Bark and also does role Wag, then passing a Dog to multi (Bark $x) multi (Wag $x) should result in ambiguity. The interesting question is whether N should be 0 or 1 (or possibly epsilon). If we have multi (Bark $x) multi (Dog $x) arguably Dog is more specialized than Bark, which says N maybe shouldn't be 0. Whether it should be epsilon or 1 depends on how you think of role composition, and whether you think of roles more like immediate parent classes or generic paste-ins. You can think of them as immediate parent classes, but in that case they're actually closer than a real parent class that would have distance 1, since role methods override parent class methods. That argues for N < 1. The problem with N == epsilon is in visualizing how Dog is more constrained than Bark. It is constrained, but its constraint is that a class is required to be about a real object (or a fake real object in the case of the Class object), whereas a role is not so constrained. This is inside out from the view that "a role is a class that isn't allowed to create an object", but while that's stated as a constraint, it's a constraint in the service of more generality rather than more specificity. So it's more accurate to say something like "a class is a role that is constrained to deal with concrete objects". It's sort of a "where exists" constraint. So I could be happy with either 0 or epsilon. 0 is simpler, and fits better with the role flattening world view. Epsilon has the additional problem that it's, er, additive rather than subtractive in this case. If we say Bark where Wag, it's simultaneously more specialized and less specialized. I think epsilons should be restricted to explicit "where" counting, though I'm liberal on the subject of whether those explicit "where" mentions are in the actual signature or in a subtype declaration somewhere. I suspect these should be equivalent distance in where-space: sub ( $x of Int where { $_ % 1 } ) subtype Odd of Int where { $_ % 1 } sub { Odd $x } I suppose a case could be made that a Bark could be considered more constrained than a Dog, which would solve the addition/subtraction problem, but it still violates the explicit-where dictum. So I'm still in favor of 0 distance for role composition. Note, however, that run-time mixins can increase distance by one if they have to create an anonymous class. Additional mixins may or may not increase the distance depending on whether the mixin mechanism creates additional anonymous classes or just adds more roles to the existing anonymous class. The former approach is probably cleaner, and we don't really need the latter mechanism to compose multiple mixins into an anonymous class simultaneously, assuming we can stack $mammal does Bark does Wag; and get some kind of list-associative simultaneous precedence. Or maybe that should be spelled $mammal does Bark&Wag; Larry
Re: Raw bytes in perl6
You guys are beating a live horse. Apocalypse 5 already discusses arrays pretending to be strings for the sake of parsing. The capability has to be there, and in fact Patrick has been bearing that in mind in the design of PGE. The only question for p6l is how much syntactic sugar you want. I've always been a bit partial to explicit polymorphic declarations: my byte [EMAIL PROTECTED]; to mean that $foo and @foo are two views of the same object. In that sense, the implicit declaration of $/ is really [EMAIL PROTECTED]/ or some such. And by happy chance, $@ and $% have both come available in Perl 6. :-) Or we can just use traits like the Apocalypse suggests. But I like the idea of highlanderish variables as long as they're explicitly declared that way. On the other hand, it does admit the possibility of people mixing up [EMAIL PROTECTED] with @$foo. So perhaps the polymorphic forms are allowed only in the declaration, and in normal code you have to pick one or the other. Though I suppose it then becomes an interesting question whether @foo ~~ $foo returns true or not. Larry
Re: Method Resolution Order question
On Wed, Jul 13, 2005 at 12:51:49PM -0400, Stevan Little wrote: : Hello, : : More questions for the metamodel. I am trying to add proper submethod : and private method handling and I have a question about method : resolution order as a whole. I asked a similar question last week, but : this time I have more details :) : : Given this class: : : class Foo { : submethod bar { ... } : method bar { ... } : } : : and given this code: : : Foo.new().bar() : : What should happen? : : The Syn/Apoc seem to indicate that methods and submethods of the same : name can coexist. So the class definition itself is legal. However, it : brings up an issue when it comes time to call bar(). If the Syn/Apoc is giving that impression, it's giving the wrong impression. Subs, methods, and anything in between all live in the same namespace. The class above is illegal because you're trying to give two things the name &bar in the absence of a "multi". : Should submethod bar() be called first, then method bar() after it? : Should method bar() be called first, then submethod bar() after it? Question doesn't arise. : Can submethods only be called from within the class (like private : methods)? No, they can be called from anywhere. They're just constrained to work only when a dispatcher's idea of "current class" matches the actual class, where "current class" usually means the actual class of the object in question, but can also mean an ancestral class when we're doing BUILDALL, for instance. There's some kind of "yes I mean you" notion in the dispatcher. It comes out in user-visible terms in .*foo calls but not ordinary .foo calls, which call a submethod only when the object is actually that type, and otherwise look for an ancestral method of that name. : And if submethods can only be called from within the class, then how do : I handle this: : : class Foo { : submethod bar { ... } : method bar { ... } : method baz { : $?SELF.bar() : } : } : : Foo.new().baz() Again, illegal class. : Thanks, : : Stevan :
Re: MML dispatch
On Jul 13, 2005, at 1:12 PM, Larry Wall wrote: If class Dog does role Bark and also does role Wag, then passing a Dog to multi (Bark $x) multi (Wag $x) should result in ambiguity. My understanding is that a Role is an abstract (i.e. cannot be instantiated) blob of methods and, possibly, data. The purpose of a Role is to paste it into a class--in other words, a Role is a not a type, it is a part of a type. Assuming that that understanding is correct, then I would expect the above multi declarations to be a compile time error: 'multi (Wag $x)' means "expect some data, call it $x, which will be of type Wag"...but Wag isn't a type, it's a partial type. I would require that declaration to be written as one of the following: multi (Dog does Bark $x)# Dog is an actual type that can be instantiated multi (Animal does Bark $x)# Animal is an abstract base class multi (Object does Bark $x)# Object (or whatever the name is) is the root of the entire class/type hierarchy I could see stretching a point and allowing the last one to be rewritten as: multi (does Wag $x)# Still references root type, but implicitly The point of this is to force the programmer to give a reasonable constraint...when they expect something that Wags, does it need to be a Dog, or will any Animal that can Wag be sufficient? Or are they really looking for absolutely anything that is capable of Wagging? Doing it this way would (I think) be both more intuitive and would resolve a lot of the ambiguity that was discussed farther on. multi (does Bark $x) multi (Dog does Bark $x)# Dog is more specific than "any data type" ---new example multi (Tree does Bark $x) multi (Dog does Bark $x)# Equally specialized classes in separate parts of the hierarchy. If passed an "Object does Bark" param, this should be an error. ---new example multi (Labrador does Bark $x)# Labrador is a subclass of Dog and therefore more specific if passed a Labrador param multi (Dog does Bark $x) # This catches any other 'Dog' params multi (does Bark $x) # This catches anything else that Barks, including 'Dingo is Dog does not Bark' The interesting question is whether N should be 0 or 1 (or possibly epsilon). If we have multi (Bark $x) multi (Dog $x) arguably Dog is more specialized than Bark, [...] The problem with N == epsilon is in visualizing how Dog is more constrained than Bark. Assuming that the declaration of Dog is 'class Dog does Bark', then yes, I think Dog should be considered more specialized than Bark-- lots of things might Bark, but only a Dog will bark in precisely this way. Or, to put it a different way, a 'Dog' class has a certain specificity and a 'Bark' Role has a certain specificity: the combination of the two produces something more specific than either. (And, of course, 'Dog does Bark does Wag' (or 'Dog does Bark&Wag' if you prefer) is yet more specific.) --Dks
Re: MML dispatch
On Wed, 2005-07-13 at 16:07 -0400, David Storrs wrote: > My understanding is that a Role is an abstract (i.e. cannot be > instantiated) blob of methods and, possibly, data. The purpose of a > Role is to paste it into a class--in other words, a Role is a not a > type, it is a part of a type. Nope, it's a type. What is a type besides a named blob of methods and, possibly, data? > The point of this is to force the programmer to give a reasonable > constraint...when they expect something that Wags, does it need to be > a Dog, or will any Animal that can Wag be sufficient? Or are they > really looking for absolutely anything that is capable of Wagging? The latter. As soon as you require signatures to enforce *how* the arguments fulfill a type constraint, you've violated a principle design goal of roles, namely that it's more important that something fulfills the requirements of type ("RobotDog understands bark() in the context of Doglike, not Treelike") than that it fulfills the requirements of the type by inheriting from a base class, delegating to a contained object, applying a role, or whatever other way you can imagine. -- c
Re: MML dispatch
On Jul 13, 2005, at 4:35 PM, chromatic wrote: On Wed, 2005-07-13 at 16:07 -0400, David Storrs wrote: My understanding is that a Role is an abstract (i.e. cannot be instantiated) blob of methods and, possibly, data. The purpose of a Role is to paste it into a class--in other words, a Role is a not a type, it is a part of a type. Nope, it's a type. What is a type besides a named blob of methods and, possibly, data? A label that says how the data is stored internally. For example, compare "Int" and "int". The former is a type and a blob of methods and not necessarily abstract. The second is a type, is NOT a blob of methods, and is definitely NOT abstract. That was part of why I was careful to say "an ***abstract [...] blob of methods" (Emphasis added.) The point of this is to force the programmer to give a reasonable constraint...when they expect something that Wags, does it need to be a Dog, or will any Animal that can Wag be sufficient? Or are they really looking for absolutely anything that is capable of Wagging? The latter. Fine. Make them say that, then. Making people think about what they really want is a good idea. As soon as you require signatures to enforce *how* the arguments fulfill a type constraint, you've violated a principle design goal of roles, namely that it's more important that something fulfills the requirements of type ("RobotDog understands bark() in the context of Doglike, not Treelike") than that it fulfills the requirements of the type by inheriting from a base class, delegating to a contained object, applying a role, or whatever other way you can imagine. That's a reasonable point. However, I wasn't deliberately using 'does Bark' to mean 'has been composed with the role Bark'. I was using it to mean "is able to perform the interface specified by Bark". So, if you prefer, I'll invent a new term: isableto. (Which I think is a lousy choice for the term, but I don't care what color that bike shed is.) Note that there are two subtly different kinds of type constraints under discussion: the first is what class something is, and the second is what behavior it can exhibit. The two are very slightly different: multi foo(Dog $x); # Must be of class Dog, or a class that is a descendant of Dog multi foo(Dog $x where { not $x.feral });# Must be of anonymous class "class Dog (or descendant) with $.feral set to false" multi foo(Dog isableto Bark);# Must be of class Dog (or descendant), and must be able to Bark multi foo(Object isableto Bark); # Absolutely any object so long as it can Bark...how it does that is up for grabs, though. multi foo( isableto Bark); # Same as previous The distinction I'm drawing is between pure behavior and behavior +state. I'm drawing this based on the idea that Roles are not allowed to have state--that they are pure virtuals, only used for defining interface. If that is not true, then (A) I apologize for the wasted bandwidth and (B) I'd like to have it explained what Roles offer that justifies their existence, since they won't be anything but a restricted form of a class. --Dks
Re: User-defined infix subs/methods?
On Wed, Jul 13, 2005 at 05:48:47PM +0200, Ingo Blechschmidt wrote: : If you wanted the compiler to parse SomeOtherModule.pm using Ruby's : grammar, you'd have to write: : : use Grammar::Ruby; : reuse SomeOtherModule You'd also have to write "reuse", because we're not going to write it for you, because we'd rather you just put "use Grammar::Ruby" in the front of the other module instead of trying to force it implicitly into a different language. On the other hand, if Grammar::Ruby also modifies the file extension to look for, "reuse" might be the fastest way to write a Ruby compiler. :-) Larry
Re: WTF? - Re: method calls on $self
On Tue, Jul 12, 2005 at 04:43:06PM +0530, Aankhen wrote: : I agree with what is being said here. `.method` is a great way to : eliminate a lot of repetitive, tedious typing. Surely there is a : viable alternative that doesn't involve outlawing it? Certainly. The problem is that there are too many viable alternatives, and half of everyone hates half of the alternatives. You will know I'm no longer a benevolent dictator when I start to enjoy watching people squirm every time I change my mind. Larry
Re: MML dispatch
On Wed, 2005-07-13 at 17:33 -0400, David Storrs wrote: > > What is a type besides a named blob of methods > > and, possibly, data? > A label that says how the data is stored internally. For example, > compare "Int" and "int". The former is a type and a blob of methods > and not necessarily abstract. The second is a type, is NOT a blob of > methods, and is definitely NOT abstract. I contend that that's meaningless to Perl. Why does the internal representation of data matter if the interface is the same? In Perl 5 terms, should you not be able to pass a tied hash to a module that expects a hash because the internal implementation may be very different? If yes, then we have very different ideas about types and signatures and I'm not sure we can reconcile our views. I realize that it could appear that I've shifted the example to container types away from your argument about value types, but I don't think it's an important distinction here. > Making people think about what they really want is a good idea. I agree, but only as far as what they really want is actually what they really want. To put it another way, if you have a method that prints something passed in, do you want a signature that says "This must be a string, perhaps with a specified encoding and internal representation" or a signature that says "This must be something that stringifies"? I want the latter. > Note that there are two subtly different kinds of type constraints > under discussion: the first is what class something is, and the > second is what behavior it can exhibit. I think the former is silly, almost always useless, and nearly always wrong, especially in library code. > The two are very slightly different: > > multi foo(Dog $x); # Must be of class > Dog, or a class that is a descendant of Dog No, I think it must conform to the type of Dog, whether it is an instance of the Dog class, an instance of a subclass of Dog, or something that performs the Dog role. Why does its internal implementation matter? What are you doing inside foo() that its internals matter? > multi foo(Dog $x where { not $x.feral });# Must be of > anonymous class "class Dog (or descendant) with $.feral set to false" Again, I think it must conform to the type of Dog, but with the additional constraint. > The distinction I'm drawing is between pure behavior and behavior > +state. I'm drawing this based on the idea that Roles are not > allowed to have state--that they are pure virtuals, only used for > defining interface. If that is not true, then (A) I apologize for > the wasted bandwidth and (B) I'd like to have it explained what Roles > offer that justifies their existence, since they won't be anything > but a restricted form of a class. Roles do have state. They exist because: 1) hierarchies aren't the only way to express type relationships -- nor are they often even a good way 2) conformity to an interface is more important than uniformity of internal representation, especially in a language with late binding 3) non-hierarchical code-reuse is possible -- and very useful 4) making no distinction between class, role, and type names makes genericity and polymorphism much easier and much more powerful Aside from optimization and introspection, why is it useful for a method signature to say "This has to be a Dog or something that inherits from Dog"? -- c
Re: DBI v2 - The Plan and How You Can Help
Dean Arnold wrote: Column 3 is a BYTEA column in Pg and needs special peppering to work. What sort of "peppering" ? DBI provides SQL_BLOB, and SQL_CLOB type descriptors (as well as SQL_BLOB_LOCATOR and SQL_CLOB_LOCATOR), so presumably DBD::Pg (or any other DBD supporting LOBs) provides the logic to map from $sth->bind_param(3, $somelob, SQL_CLOB); >>> SOME_DATE_COLUMN is the database native date type. On Oracle you'll >>> need to convert the ? to a 'TO_DATE(?)'. > Er, why ? I haven't used DBD::Oracle lately, but assuming you > $sth->bind_param(1, '2005-07-13', SQL_DATE), > I'd assume DBD::Oracle would be smart enough to communicate that That bind_param peppering is precisely what I'm talking about, thanks for demonstrating my point. This requirement to use "bind_param" to explicitly tell the DBI which placeholders correspond to which types is rarely mentioned on any introductions to DBI, and as a result, very few people carry this out in practice or are prepared to do the necessary re-work to code bases to perform it. So, DBD drivers need to hope that the database driver is smart enough to pull apart the query, match it against the schema and automatically setup the type correctly. Perhaps many C database access libraries provide enough information to do this, and pardon my ignorance for never having written or worked on a DBD to this level - but I'm guessing that such query introspection isn't always possible. And, in a sense, requiring that the DBD is able to introspect the query and DTRT is an "extra restriction" that DBD authors need to conform to, setting the bar for conformance so high that it is practically impossible to write portable database access code. Please note that I'm not suggesting that we do away with the existing interface, for people who don't care about writing portable database code. But I'd like to be able to write, for instance; use v6; use DBI-2; my $query = SQL { SELECT * FROM FOO LEFT JOIN BAR ON BAR.FOOID = FOO.ID }; if ($one) { $query &&= SQL::WhereClause { ONE = $one }; } my $dbh = DBI.connect(:source("myapp")); my $sth = $dbh.prepare($query); my $resultset = $sth.execute(); for =$resultset -> @row { ... } So what's happening here? Well, the SQL construct marks the beginning of a segment of code that happens to be in an alternate grammar, corresponding to some level of ANSI SQL. This builds an object which corresponds to that query. In fact, this can happen at compile time! The SQL { } is actually a closure that returns a SQL object when it is called. The later SQL::WhereClause is the same; the variable isn't merely interpolated, but is closed over, and included as if it were a placeholder. The &&= assignment operator uses the overloaded && operator on the SQL object, which sees it is being given a query fragment, and adds it into the appropriate point on the SQL AST. This should all be quite transparent - of course, an optional (but portable) method of writing database queries. And it's all deliciously Perlish, yielding less fussing around with buggy code stitching together queries, and more clean expression of queries using a standard language. Of course it will be entirely possible to layer support for this sort of thing atop any DBI interface; but this *is* a version 2, we do have prototypes for the mechanics of all this stuff - and Done Right™, it could actually fulfil the goal of DBI - being able to write Database-driven applications that are truly independant of the database product in use. DBI v1 cuts the porting time down to next to nothing; but we can get it even closer! Sorry to "bang on" about this for so long, I'm sure you're all getting sick of it by now- I had hoped that the original suggestion was just going to be acknowledged as a valid way to enhance portability and flexibility and considered without too much rehashing of what to some is an old topic. Sam.
Re: MML dispatch
On Jul 13, 2005, at 6:16 PM, chromatic wrote: On Wed, 2005-07-13 at 17:33 -0400, David Storrs wrote: What is a type besides a named blob of methods and, possibly, data? A label that says how the data is stored internally. For example, compare "Int" and "int". The former is a type and a blob of methods and not necessarily abstract. The second is a type, is NOT a blob of methods, and is definitely NOT abstract. I contend that that's meaningless to Perl. Um...huh? Sorry, I'm not trying to be sarcastic, but I honestly don't understand how you can think that. There are things that you can do with an Int that you cannot do with an int, so how can this be a meaningless distinction? Or did I miss a decision saying that 'int' was just a request, and that 'int' data could freely be autoboxed into an Int if necessary? That's quite possible...I haven't reread the AESs in a long time and things change often enough that I admit to not having a solid grip on the current state. Why does the internal representation of data matter if the interface is the same? It shouldn't, I agree. My point was that the interface to Int (the object) is not the same as the interface to int (the low-level representation). For example, last I heard this was one of the differences: Int foo = 0 but true; # no problem int foo = 0 but true; # problem! nowhere to store the trait Making people think about what they really want is a good idea. I agree, but only as far as what they really want is actually what they really want. To put it another way, if you have a method that prints something passed in, do you want a signature that says "This must be a string, perhaps with a specified encoding and internal representation" or a signature that says "This must be something that stringifies"? I want the latter. Excellent, so do I. Our views are not that far apart after all. The two are very slightly different: multi foo(Dog $x); # Must be of class Dog, or a class that is a descendant of Dog No, I think it must conform to the type of Dog, whether it is an instance of the Dog class, an instance of a subclass of Dog, or something that performs the Dog role. Ok, but you're begging the question. I'm trying to illustrate my definition of the word "type"; it doesn't help for you to say 'it must conform to the type...' when 'type' is what I'm trying to define. In my mind, 'class' is one component that goes into making up a type. So is 'where clause'. So is 'roles that have been composited in'. Etc. A 'type', in my mind anyway, is a promise about the interface and state (*) that something will provide. Here are some examples (illustrative, not definitive): int $a# 4 bytes (on a 32-bit system), can't store traits Int $a# Can do everything 'int' can do, can also store traits Int $a where { 0 < $a < 7 }# Can do everything Int can do but value is between 0 and 7 exclusive I would contend that that list contains 3 types but only one class (maybe two if you interpret the where clause as creating a new class). Does this seem like a reasonable definition of 'type' to you? Because I think we need to make sure we're using the same terms before we continue this. (*) I hestitated on whether to include the 'and state' clause there, but finally decided to leave it. In that clause, I am only referring to state that is either publicly visible (and therefore, arguably part of the interface), or that governs (and therefore constrains) the behavior of the interface. I am not including internal-only state. Taking your final question out of order: Aside from optimization and introspection, why is it useful for a method signature to say "This has to be a Dog or something that inherits from Dog"? Because it is an assertion that 'This' will be something that behaves like a Dog, and has the exposed state that I expect to see from a Dog. In other words, I agree with you--it's all about the interface. The point I'm trying to make is that, from the recipient's point of view, all of these statements are exactly the same: implements the interface of Dog === is of class Dog === has been composited with the Role Dog Given that, why do we need the second version? (Don't say 'TIMTOWTDI'. Extra WTDI are only useful if they have different nuances.) Roles do have state. Ok, I didn't realize that. My bad. They exist because: 1) hierarchies aren't the only way to express type relationships -- nor are they often even a good way 2) conformity to an interface is more important than uniformity of internal representation, especially in a language with late binding 3) non-hierarchical code-reuse is possible -- and very useful 4) making no distinction between class, role, and type names makes genericity and polymorphism much easier and much more powerful I agree
DBI v2 - Data In and Data Out
The proposals so far have dealt mostly with the SQL itself, and supporting database-neutral layers on top of DBI. Personally, I don't mind writing the SQL myself, I rarely need to make a particular statement work on two databases in my work, and I can optimize a lot better than any SQL generator. I like DBI shortcuts (selectrow_array, etc), and I would like them to become even more convenient in DBIv2, so I have been thinking about ways to streamline the movement of data in and out of DBI. A lot of these ideas are probably obvious, but I haven't seen them actually stated anywhere yet. A lot may be bad or wrong, which is where you readers come in... Data Input * placeholders (3 types): ? PRO: simple everyone supports this CON: each parameter may only be accessed once and in the order determined by the SQL (rewrite your function and your interface changes) :1 :2 :3 "true" positional placeholders PRO: elimiates redundancy (list the same argument twice) and dependancy (reorder args if sql changes) :name PRO: easier to manage for dynamic sql CON: requires separate bind_param for each biggest CON: not all are supported by every driver. DBI could have a (optional?) compatibility layer, which would translate down for those drivers that do not support :1 or :name, replacing them with ? and reordering and duplicating the args if necessary. I don't think a full SQL parser would be required. For :name syntax, the execute function (do, selectrow_*, etc) should do the binding automatically if Pairs are passed as arguments. $dbh->do('update table set x = :x where y = :y', undef, x => $foo, y => $bar ); * bind_param I would like to avoid the need to call this if possible. Perhaps attributes on the parameters could be used to flag certain things, but I would prefer to do it semi-automatically, based on the object type of the parameter, as described in "Data Types on input" below. * bind_param_array I think execute_array with ArrayTupleFetch is a better solution. * execute_array with ArrayTupleFetch ArrayTupleFetch should accept a (Lazy) Array of Array|Hash as well as a code block in perl6. Data Types on input strings and numbers are handled transparently (good!). Other types less so: Dates, LOBs, etc. It would be nice if we could tell DBI how to handle objects of various types. If I pass it a DateTime object, format it "this way" to pass it to the driver. If I pass it a LOB or IO object, bind it with the type needed to handle it correctly. I'm not sure what the best way to do this would be. Maybe it looks for an object method with a specific name, which we could define as a multi sub. multi sub _dbi_format( DateTime $d ) returns String { ... } Or maybe we register types with DBI and tell it what to do. $dbh->register_type( DateTime, format => &my_format_sub , type => SQL_VARCHAR ); Data Output ways to get data out: * fetchrow get a single row I would like it if there was a single fetchrow function which returned a row object. Or at least if the unsuffixed fetchrow did that. The row object can be accessed as both an array or a hash, since query results have both a position and a name. If the row object is evaluated in Array or Hash context, it should return a list of values or key=>value pairs, so that it can be easily assigned to an array or hash. In String or Number context, it should probably return the value of the first column. * fetchall get multiple rows This should return a Lazy List (iterator) of row objects. * selectcol get column(s) as a list This is a bit of an oddball, since there is no corresponding fetchcol function. But it is a very useful oddball for when you want to turn a lookup table into a hash, for instance. I think the thing to do is to unify this with fetchall, by allowing the $slice parameter to fetchall to be a code block. The code block could return a arrayref or hashref to duplicate the existing slice functionality, or it could return a list of values, a pair, a row object, or something else entirely. %hash = $sth->fetchall( slice => sub($row) { return ($row[0] => $row[1]) } ); This could also be added to DBIv1. A couple of the more obvious slice funtions could be provided, allowing a nice looking call: %hash = $sth->fetchall_array( &as_pairs ); * bind_col Honestly, I don't use this method personally, so I haven't thought about it much. fetchrow_hashref works well enough for me. * bind_param_inout I do use this, but only behind an sqlProcedure( $procname, $arg ... ) wrapper, which calls bind_param_inout for any $args which are references. This type of binding could be invoked by an attribute on the parameter: $sth->execute( $arg but inout ); or maybe "but rw", but rw may be overoverloaded already. Data Types on output It would be nice to have some datatypes already
Re: Method Resolution Order question
Larry, On Jul 13, 2005, at 2:30 PM, Larry Wall wrote: : The Syn/Apoc seem to indicate that methods and submethods of the same : name can coexist. So the class definition itself is legal. However, it : brings up an issue when it comes time to call bar(). If the Syn/Apoc is giving that impression, it's giving the wrong impression. Subs, methods, and anything in between all live in the same namespace. The class above is illegal because you're trying to give two things the name &bar in the absence of a "multi". Horray : Can submethods only be called from within the class (like private : methods)? No, they can be called from anywhere. They're just constrained to work only when a dispatcher's idea of "current class" matches the actual class, where "current class" usually means the actual class of the object in question, but can also mean an ancestral class when we're doing BUILDALL, for instance. The way I am viewing the notion of "current class" for submethods currently is: From inside another method or submethod: - a submethod should only be called from the class which defines it. This means that since Object::bless() calls Object::BUILDALL() it is all well and good, assuming you have not overridden bless() in your class, and are calling it $class.bless(). (Object::BUILDALL of course then digs into the metaclass to call BUILD() for all the superclasses in post-order. I am not sure how to do that otherwise, submethod or not.) However, if you define MyClass::bless, then you will need to define MyClass::BUILDALL as well. Or is it possible just do $self.Object::BUILDALL()? So can I call a submethod from a different class if I fully qualify it? From outside a method (in "user" space): - the invocant of the submethod must be a direct instance of the class in which the submethod is defined. No inheritance involved. Maybe this is too strict, though? What do you think? There's some kind of "yes I mean you" notion in the dispatcher. It comes out in user-visible terms in .*foo calls but not ordinary .foo calls, I am not familiar with .*foo calls? Can you elaborate? which call a submethod only when the object is actually that type, and otherwise look for an ancestral method of that name. Yes, to expand upon my above statements. The method resolution would begin looking in the local submethod table, then move onto the local method table, and then on up the superclass hierarchy. Is that correct? Thanks, Stevan
Re: MML dispatch
On Wed, Jul 13, 2005 at 05:33:18PM -0400, David Storrs wrote: : I'd like to have it explained what Roles : offer that justifies their existence, since they won't be anything : but a restricted form of a class. Please check your assumptions. In addition to what chromatic said, I'd like to point out that you've got the abstraction levels backwards by my lights: these days I tend to think of the class as a restricted form of role. A class is restricted to having to provide a working interface to real objects. A role doesn't have to do that--it's just a semantic slice of interface and maybe some handy default behavior. It's a bit of generic code that doesn't have to make complete sense in isolation, as long as some real class can make some sense of it when combined with other things. Looking at it another way, roles are attempting to provide the stable semantic currency that other languages try to provide with final classes. Because roles are composed rather than inherited, they avoid many of the problems that final classes engender in such languages. Class finalization (as instigated by the class itself) will someday be viewed as a tremendous botch, I think. Larry
Re: MML dispatch
(Taking things slightly out of order.) On Jul 13, 2005, at 7:32 PM, Larry Wall wrote: A class is restricted to having to provide a working interface to real objects. Can't there be pure-abstract, non-instantiable classes? Or are you still considering those to be interfaces to "real objects"? I suppose, arguably, the class pseudo-object could make that work, but it seems a sleight-of-hand. In addition to what chromatic said, I'd like to point out that you've got the abstraction levels backwards by my lights: these days I tend to think of the class as a restricted form of role. Ok, fine, then let's get rid of classes and just use roles. Right now, it sounds like the functionality of one of them is a proper subset of the functionality of the other. If that's the case, why do we need both? Or is there something that one of them can do that the other cannot and that absolutely cannot be rolled into the other one? (I hope that made sense.) --Dks
Re: MML dispatch
TSa (Thomas Sandlaß) wrote: I just want to hint the Perl6 community to the fact that there exists a US patent on geometric MMD: Well, fortunately it's really just a patent on the specific combination of a mathematical isomorphism and a well-known geometric algorithm to *optimize* method dispatch, rather than on the Manhattan metric itself. So I very much doubt there's a problem. If MMD optimization does become an issue, there are plenty of other non-patented algorithms available. Besides which, even without a highly optimized dispatch mechanism you can get asymptotically close to the same performance by jitting an MMD look-up table on-the-fly (possibly with some table-compression where large hierarchies or many parameters are involved). Damian
Re: What do use and require evaluate to?
On Tue, Jul 12, 2005 at 08:48:41PM +0300, Gaal Yahas wrote: : I propose to throw away the filesystem coupling, and map from a more : general name of the bit of code we are requiring to a more general : description of which instance of it we actually got. Once modules return : interesting values, it might be useful to keep a copy of that value : somewhere on the value side of %*INC: or else turn it inside out and : stipulate that a standard field in the Module object is where you got : this particular module. Yes, that's basically what I was mumbling about in my response. Now just make sure %*INC is lexically scoped. : Probably, %*INC values should be weak references. Why should they be weak references? If %*INC is lexically scoped then its entries represent this lexical scope's *real* references to modules, and there's no need to weaken them, since it's not functioning as some kind of cache. As long as this lexical scope sticks around, it needs the modules it points to. As soon as the lexical scope is destroyed, it doesn't need them any more. (Counting all closures over this lexical scope as preserving its needfulness, until all such closures are dead objects.) It's my conjecture that any explicit need for weak references probably indicates a design failure somewhere. Something like the mis-scoping of a reference variable, or maybe only something niggly like the absence of a feature like "is cached" to encapsulate weak semantics. Or maybe something as major as the lack of robust GC, in the case of Perl 5... Of course, *somebody* has to write the internals for "is cached". But we already know that all optimizations are a form of cheating. :-) Larry
Re: User-defined infix subs/methods?
On Tue, Jul 12, 2005 at 02:10:06PM -0700, Larry Wall wrote: > Good, I'd forgotten about that. Which means that it's even harder > for someone to compile a module in a "strange" dialect, since they'd > essentially have to write their own version of "use" that forces > recompilation ("reuse", if you will). And the harder we make it to > write "reuse", the better. Within perl 5, there is an extremely easy way to write that, namely coderef in @INC that provides line-based filtering: http://search.cpan.org/dist/Acme-use-strict-with-pride/pride.pm Are we to discontinue use of [EMAIL PROTECTED], and switch to the slightly more difficult but far more manageable approach of rebinding &*require? Thanks, /Autrijus/ pgpe8MIKLR2cj.pgp Description: PGP signature
Re: MML dispatch
Larry Wall wrote: In addition to what chromatic said, I'd like to point out that you've got the abstraction levels backwards by my lights: these days I tend to think of the class as a restricted form of role. A class is restricted to having to provide a working interface to real objects. Can I present an alternative way of viewing them, which I don't think contradicts with what I've understood of them so far from the Apocalypses and Synopses documents. First a couple of definitions; A "runtime class" is a package name, and a collection of functions that form a "dispatch table". There are actually two tables - one for private and one for public methods. The public table links to "superclasses" where further dispatch may occur. A "method" on a Role or a Class is a function that takes two implicit arguments; a dispatch table for private method lookups, and one for public methods lookups. The private dispatch table is bound when the function is added to a runtime class, but the public dispatch table is bound as late as possible (or until the class is closed in some situations). Here's the meat: A Class is then a Role that gets its runtime class created, and all its methods' private dispatch tables bound at declaration time. A Role, on the other hand, leaves methods that can't be called, until they are bound into a "runtime class". So they _look_ like they are flattened as the runtime classes are composed, unless you are introspecting to the sufficient level. The "runtime class" would be the ::Type objects, and the real Class and Role objects what you get from the .meta objects. This might be a half empty / half full thing, I just thought you might find that description interesting. Note that I don't deal with "state", I'm just treating attributes as if all they are is a set of accessor functions, which store in an unspecified&unimportant location. Sam.
Re: DBI v2 - Data In and Data Out
On Wed, Jul 13, 2005 at 17:23:28 -0600, John Williams wrote: > The proposals so far have dealt mostly with the SQL itself, and > supporting database-neutral layers on top of DBI. > > Personally, I don't mind writing the SQL myself, I rarely need to make > a particular statement work on two databases in my work, and I can > optimize a lot better than any SQL generator. > > I like DBI shortcuts (selectrow_array, etc), and I would like them > to become even more convenient in DBIv2, so I have been thinking > about ways to streamline the movement of data in and out of DBI. I would like to propose one more output format, optimized for performance: The packed array is a piddle like interface, which is 0 overhead - no conversion or copying is made, the driver simply implements an IType over the native data that it can provide. Result matrices are given back in the natural buffer size of the driver, or a user defined setting. I also think that your compatibility concerns shouldn't matter - we already have DBI for perl 5. It provides all the compatibility we need. I'd like a more accessible binding interface, and more flexible placeholders (especially for safety). Since Perl 6 has more explicit types I'd like DBI to be able to leverage these, too. -- () Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418 perl hacker & /\ kung foo master: /me supports the ASCII Ribbon Campaign: neeyah!!! pgpoml771u5Hb.pgp Description: PGP signature