Re: Thoughs on Theory.pm
On 10/13/05, Dave Whipp <[EMAIL PROTECTED]> wrote: > I started thinking about the "in general, unverifiable programmatically" > bit. While obviously true, perhaps we can get closer than just leaving > them as comments. It should be possible to associate a > unit-test-generator with the theory, so I can say: > > theory Ring(::R) { > ... > axiom associative(R ($a, $b, $b)) { > is_true( ((a+b)+c) - (a+(b+c)) eqv R(0) ); > } > ... > } > > And then say "for type T, please generate 1000 random tests of T using > axioms of Ring". The points about hand-crafted edge-case tests are good, but that's not to say that this isn't a good idea. Putting the properties inline with the theory is good documentation (plus, as you say, it could be used to generate pre- and postconditions). By the way, Haskell already did this. http://www.haskell.org/ghc/docs/latest/html/libraries/QuickCheck/Test.QuickCheck.html :-) Luke
Re: [P6L] Closed Classes Polemic (was Re: What the heck is a submethod (good for))
On Thu, 2005-10-13 at 18:36 -0700, Chip Salzenberg wrote: > On Thu, Oct 13, 2005 at 06:13:09PM -0700, chromatic wrote: > > I just don't want people who merely write a module or class to be > > able to prevent people who actually use that module or class from > > using, extending, or poking around in it. > Sounds kind of like Linus's opinion of close-source modules. If they > exist and work, he's not going to break them, but he's not going to do > *anything* to specially support them. I mostly agree, but I'm not talking about the *license* of the code. I don't think that's clear to everyone reading this thread, so I think I should clarify. Regardless of the license, the author of a class or module should not be able to close off that class or module from people using that class or module who want to poke around in its guts at runtime, regardless of the license or availability of the source code. Allowing authors to say "This is my namespace and you cannot touch it" or "This is my class and you cannot touch it or derive from it or decorate it or apply roles to it" is silly, because they'll do stupid and wrong things that the rest of the world will have to work around forever, regardless of the license of their code. By all means write efficient code and well-encapsulated code and document your interfaces and intentions appropriately, but if you want to write generic and reusable code, don't "optimize" for situations which you can't possibly have profiled because no one has written the code for them yet. We should not encourage that. -- c
Custom Metaclass and Inheritance of Class Methods
Hey All, So, given the abundance of positive responses ;) for my "class methods don't inherit" proposal, I have decided to withdraw that proposal (see my last response on the thread). Of course, this means we now have to work out the details of exactly *how* they get inherited in all situations. The trickiest one being in the presence of custom metaclasses. So, onto the questions. (NOTE: if you get bored about half-way through this mail (and you probably will), there is a conculsion/wrap-up at the very bottom that you can probably safely skip ahead too) Should custom metaclasses are "inherited" along "normal" subclass lines? This would mean that if Foo uses CustomMeta as it's metaclass, any subclass of Foo will do the same. This is something Larry mentioned, and something I had been thinking about a lot myself and discussed recently with Rob Kinyon. I drew a diagram in my response to Larry that looked like this: Class ^ : CustomMeta ^ : eFoo<...eBar ^ ^ | | Foo<...Bar This shows the structure which would be created. The result is that method dispatch would go like this: Bar.foo eBar.get_method(foo) eFoo.get_method(foo) CustomMeta.get_method(foo) Class.get_method(foo) ! No Method Found Error ! I think this makes sense in many ways since CustomMeta can theoretically add capabilities to the Foo class, which one would want inherited by subclasses of Foo. (NOTE: if CustomMeta adds instance methods to Foo, they will get inherited, mostly I am talking about class functionality here) However, I can also see where it would make sense for this *not* to behave this way. But if we the opposite approach, the eigenclass/ metaclass hierarchy begins to get more complex. To start with, we would need to create another anon-class (called xFoo here) which uses multiple inheritence to inherit from eFoo and CustomMeta, then eBar would inherit from eFoo (and through eFoo, to Class), this would keep CustomMeta out of Bar's method dispatch path. Class ^^... : : CustomMeta : ^ : : : xFoo...>eFoo<...eBar ^ ^ | | FooeFoo xBar>eBar ^ ^ ^: | :.|: | | Foo<..Bar The method dispatch path for this is pretty much the same as above, with the addition of CustomMeta2. This example now actually brings up another issue. What should the superclass ordering be within the x* classes? If eBar comes first, followed by CustomMeta2, then we get the following method dispatch path: Bar.foo xBar.has_method(foo) # xBar should never have any of it's own method eBar.has_method(foo) eFoo.has_method(foo) CustomMeta2.has_method(foo) # this would fall here under C3 Class.has_method(foo) ! Method Not Found Error ! But if CustomMeta2 comes first, followed by eBar, then we get the following method dispatch path: Bar.foo xBar.has_method(foo) CustomMeta2.has_method(foo) eBar.has_method(foo) eFoo.has_method(foo) Class.has_method(foo) ! Method Not Found Error ! The question really is, which has precedence, the custom metaclass, or the local class methods (including class methods inherited along "normal" class lines)? Now, all these method dispatch paths are using the C3 MRO. And personally I find neither of these approaches to be the best. One alternate (but kind of whacky) approach would be to not use C3 here, but instead use breath-first traversal. Now, this may seem really odd at first, but given the highly regular structure of these class groupings, it might make the most sense. Here is what that method dispatch path might look like: Bar.foo xBar.has_method(foo) eBar.has_method(foo) CustomMeta2.has_method(foo) eFoo.has_method(foo) Class.has_method(foo) ! Method Not Found Error ! Notice how the eBar (which hold's Bar's class methods) is first, followed by the CustomMeta2 class, the followed by eFoo, then onto Class. This specialized dispatching beha
Continuing in the face of exceptions, and what's the negation of // ?
I retract my opposition to "err". After coding this: try { try { path = f.getCanonicalPath(); } catch (Exception e) { path = f.getAbsolutePath(); } } catch (Exception e) { path = f.toString(); } I am now a convert. To the extent that we are going to throw exceptions, there needs to be a quick way of huffmanizing the scaffolding. IIRC, "use fatal" decides between an exception being thrown and an "undef but ..." value being returned. IMO, it's important to coerce code into the same behavior: If a sub that I call tries to throw an exception, that needs to be converted into undef-but-whatever, too. One problem, of course, is drawing the line: «|die| creates a "normal" exception»[A4] so how, if at all, can a library coder force an abort? I suspect exit() is the only way -- there's always some guy wanting to override everything. So the "err" operator, or whatever, has to suppress fatal, call, check, return: sub infix: (Code &lhs, Code &rhs) { no fatal; &lhs; CATCH { &rhs; } } Producing: my $path = $f.getCanonicalPath() err $f.getAbsolutePath() err $f.toString(); But using "no fatal" at the top of your code reduces this to plain old //: no fatal; my $path = $f.getCanonicalPath() // $f.getAbsolutePath() // $f.toString(); I wonder what '\\' means? Is it the negation of //? So that: my $x = $hash<$key> \\ die "Error: hash<$key> already defined!" Or can we continue the breaktyping theme and grab it for fatal-suppression? Alternatively, of course, there's always /// or //! -- probably one of these is best, extending the theme of the "if undef" to include "if undef (and exception is very undef!)". At any rate, count me in for suppressing errors inline -- also for tarring and feathering the guy who put that kind of crap in the Java standard library. =Austin
Re: Re(vised): Proposal to make class method non-inheritable
On 14/10/05, Stevan Little <[EMAIL PROTECTED]> wrote: > So anyway, here are a few ideas, in no particular order: > >method bark (::Dog $d:) { ... } ># not sure if this notation is already taken or not > >method bark ($Dog $d:) { ... } ># not sure I like this one myself, but to me it helps to re- > enforce the singleton nature of the class instance > >method bark (Dog) { ... } ># this would be similar to functional languages where the > parameter matches a value, not the type of a value. ># The user would then be forced to use $?CLASS inside (this one is > probably too much B&D) > >classmethod bark { ... } ># you can't get more specific than this :) > > Okay, thats all for now, however, be on the lookout for some other > mails on the specifics of class method dispatch. If we are going to > do it, we need to do it right. How about: method bark (Dog ::K:) { ... } Where ::K must hold a class that is a subclass of Dog. Or 'is a subtype of', or 'does', or whatever the most correct term is in this context. (I seem to recall Damian mentioning something like this on the list somewhere, but I might have misunderstood him and made it up myself.) I do notice, though, that most of these class-method forms don't stand out very well--maybe something like 'classmethod' might be best after all, particularly if class methods aren't heavily used. Stuart
Re: [P6L] Closed Classes Polemic (was Re: What the heck is a submethod (good for))
On Thu, Oct 13, 2005 at 06:13:09PM -0700, chromatic wrote: > I just don't want people who merely write a module or class to be > able to prevent people who actually use that module or class from > using, extending, or poking around in it. Sounds kind of like Linus's opinion of close-source modules. If they exist and work, he's not going to break them, but he's not going to do *anything* to specially support them. -- Chip Salzenberg <[EMAIL PROTECTED]>
Re: Closed Classes Polemic (was Re: What the heck is a submethod (good for))
On Fri, 2005-10-14 at 02:18 +0200, Yuval Kogman wrote: > On Wed, Oct 12, 2005 at 13:08:27 -0700, chromatic wrote: > > Closed classes should not exist. > > > > At least, they should only exist if the person *running* Perl 6 wants > > them to exist -- never if merely the class writer wants to close them. > In theory I agree, and I hope that will be the defacto way of doing > it, but if perl 6 gets compiled portably to many different > bytecodes (which it seems like it will) someone somewhere will write > a backend which allows people to encrypt, and people will use it. > > I think this is something we need to accept, even if it isn't > something we like. I don't care if people encrypt their code. I don't have to use it. I just don't want people who merely write a module or class to be able to prevent people who actually use that module or class from using, extending, or poking around in it. No Java "final", unless you're the one running the program. -- c
Re: Closed Classes Polemic (was Re: What the heck is a submethod (good for))
On 10/13/05, John Macdonald <[EMAIL PROTECTED]> wrote: > Just because you can't make locking perfect does not mean it > has no value. Acme::Bleach it is!
Re(vised): Proposal to make class method non-inheritable
Well, I suspected there would not be much support for my initial proposal on class methods, but I felt I had to try. Not being the type of person who gives up easily, I want to revise the proposal (incorporating some of the ideas in the responses). I propose that class methods are inheritable, but have the following behaviors/attributes: 1) Autogenerated Class attribute accessors will be submethods. This means that this code: class Foo { our $.bar; } will be functionally identical to this code: class Foo { our $.bar; submethod bar (Class $c:) { $.bar } } This will ensure that class methods which are specifically tied to some kind of state within the class will not be inherited. At least not by default, if you want that behavior, then you can do this: class Foo { our $.bar; method bar (Class $c:) { $.bar } } 2) Class methods be defined more specifically I think that "method (Class $c:) { ... }" is kind of ugly, and if we use eigenclasses to implement class methods, is not even correct. Ideally we have some kind of way to represent Larry's "Dog but undef" concept. This could be thought of as being the prototypical instance (for those who like prototype based OO), and it would also be the invocant for all class methods for Dog. So anyway, here are a few ideas, in no particular order: method bark (::Dog $d:) { ... } # not sure if this notation is already taken or not method bark ($Dog $d:) { ... } # not sure I like this one myself, but to me it helps to re- enforce the singleton nature of the class instance method bark (Dog) { ... } # this would be similar to functional languages where the parameter matches a value, not the type of a value. # The user would then be forced to use $?CLASS inside (this one is probably too much B&D) classmethod bark { ... } # you can't get more specific than this :) Okay, thats all for now, however, be on the lookout for some other mails on the specifics of class method dispatch. If we are going to do it, we need to do it right. Thanks, Stevan
Re: Thoughs on Theory.pm
David Storrs wrote: While I like the idea, I would point out that 1000 tests with randomly generated data are far less useful than 5 tests chosen to hit boundary conditions. I come from a hardware verification background. The trend in this industry is driven from the fact that the computer can generate (and) run 1000 random tests more quickly than a human can write 5 directed tests. And a quick question: just what are the boundary cases of "a+(b+c)==(a+b)+c" for a generic Ring type? Of course, in the hardware world we give hints (constraints) to the generators to bias it towards interesting cases. Plus the tools use coverage data to drive the tests towards uncovered code (not entirely automatic). Finally, we have tools that can spend 48+ hours analyzing a small block (statically) to find really good set of tests.
Re: Proposal to make class method non-inheritable
On Oct 13, 2005, at 4:45 PM, TSa wrote: No, not that class has no state, but that with the currently specced classes we have inherited behaviors (class methods) but they do not inherit the accompanying state (class attributes) as well. I see this as potentially very problematic. What do you mean with "not inheriting class state"? I would think that beeing an instance of a class, an object should have access to the shared class data, but it is not part of the per object state. Or do you mean that class data is not accessable to the instances at all? I would hope that this is 'hidden' in the scopes where the class's parts are defined but of course accessable lexically from class support code there. I mean that classes do not inherit class state along subclass lines. Take this code for instance: class Foo { has $.bar; } every instance of Foo I create has it's own copy of $.bar. Now I subclass it: class Bar is Foo {} every instance of Bar has it's own copy of $.bar as well. Now look at this from the class attribute perspective. class Foo { our $.baz; # class data here,.. not instance data } Foo has a single copy of $.baz in it's internal namespace. Now subclass it: class Bar is Foo {} Bar does not have it own copy of $.baz, in fact Bar's ability to access Foo::{$.baz} (or however it would be spelt) is not more special than any other class in the system. The point I am trying to make is that class data is unique to the class itself, and subclasses of said class do not have any special priviledges or access to that data (leaving auto-generated accessors out of the picture for now). This is different though from how class methods behave, which seems to me to be problematic. Stevan
Re: Closed Classes Polemic (was Re: What the heck is a submethod (good for))
On Wed, Oct 12, 2005 at 13:08:27 -0700, chromatic wrote: > Closed classes should not exist. > > At least, they should only exist if the person *running* Perl 6 wants > them to exist -- never if merely the class writer wants to close them. In theory I agree, and I hope that will be the defacto way of doing it, but if perl 6 gets compiled portably to many different bytecodes (which it seems like it will) someone somewhere will write a backend which allows people to encrypt, and people will use it. I think this is something we need to accept, even if it isn't something we like. -- () Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418 perl hacker & /\ kung foo master: /me sneaks up from another MIME part: neeyah! pgpDwgwZYGNe6.pgp Description: PGP signature
Re: Thoughs on Theory.pm
On Oct 13, 2005, at 6:45 PM, Dave Whipp wrote: I started thinking about the "in general, unverifiable programmatically" bit. While obviously true, perhaps we can get closer than just leaving them as comments. It should be possible to associate a unit-test-generator with the theory, so I can say: [...] And then say "for type T, please generate 1000 random tests of T using axioms of Ring". In an ultra-slow debug mode, the aximons could be propagated as post conditions on every public mutator of T, so that we test them continuously in a running application (or tes suite). While I like the idea, I would point out that 1000 tests with randomly generated data are far less useful than 5 tests chosen to hit boundary conditions. --Dks
Thoughs on Theory.pm
(ref: http://svn.openfoundry.org/pugs/docs/notes/theory.pod) >theory Ring{::R} { >multi infix:<+> (R, R --> R) {...} >multi prefix:<-> (R --> R){...} >multi infix:<-> (R $x, R $y --> R) { $x + (-$y) } >multi infix:<*> (R, R --> R) {...} ># only technically required to handle 0 and 1 >multi coerce: (Int --> R) {...} >} > > This says that in order for a type R to be a ring, it must > supply these operations. The operations are necessary but > not sufficient to be a ring; you also have to obey some > algebraic laws (which are, in general, unverifiable > programmatically), for instance, associativity over > addition: C<(a + b) + c == a + (b + c)>. I started thinking about the "in general, unverifiable programmatically" bit. While obviously true, perhaps we can get closer than just leaving them as comments. It should be possible to associate a unit-test-generator with the theory, so I can say: theory Ring(::R) { ... axiom associative(R ($a, $b, $b)) { is_true( ((a+b)+c) - (a+(b+c)) eqv R(0) ); } ... } And then say "for type T, please generate 1000 random tests of T using axioms of Ring". In an ultra-slow debug mode, the aximons could be propagated as post conditions on every public mutator of T, so that we test them continuously in a running application (or tes suite).
Re: Proposal to make class method non-inheritable
HaloO, Stevan Little wrote: On Oct 11, 2005, at 8:47 PM, Larry Wall wrote: You seem to be arguing that a class has no state, but my view is that, in the abstract, a class encompasses the state of *all* its objects. It just hasn't picked one particular object to be at the moment. I love this notion because that makes the type that the class represents the potential state it would reach when *all* distinguishable instances were realized---which needs a lot of memory for many classes. But the bit class/type e.g. has exactly two distinguishable states! Well and more then these two will never be needed if the algebraic, boolean type is build with !, && and ||. Negation just exchanges the half of the type that is in use, the former one is returned into potentiality, that is, it leaves the programs actuality. The binary connectives leave false and true in the program respectively as soon as both booleans have entered the program! That is (1 && 0 == 0) and (0 || 1 == 1) dual each other, just as the unrealized potential state of a class duals the actually realized state of the instances of the class in any particular moment. Here's a nice magic square picture of the idea: -Class .. ::Classmeta space ** | /| | / |The diagonal line splits the potential(-) from | / |the actual(+) instances. Undef and the ::Class |/ |are the "singularities" of the class. The state | /|of the class moves up the diagonal through instance | / |creation, while the GC moves it towards Undef. | / | ** Undef .. +Classvalue space No, not that class has no state, but that with the currently specced classes we have inherited behaviors (class methods) but they do not inherit the accompanying state (class attributes) as well. I see this as potentially very problematic. What do you mean with "not inheriting class state"? I would think that beeing an instance of a class, an object should have access to the shared class data, but it is not part of the per object state. Or do you mean that class data is not accessable to the instances at all? I would hope that this is 'hidden' in the scopes where the class's parts are defined but of course accessable lexically from class support code there. --
Re: Closed Classes Polemic (was Re: What the heck is a submethod (good for))
On Thu, Oct 13, 2005 at 03:01:29PM -0400, Rob Kinyon wrote: > > I think this is an opportune time for me to express that I think the > > ability to close-source a module is important. I love open source, > > and I couldn't imagine writing anything by myself that I wouldn't > > share. But in order for Perl to be taken seriously as a commercial > > client-side language, it must be possible to close the source. I > > started writing a game with a few friends last year, and as we were > > picking our implementation strategy, using Perl as the primary > > "sequencing engine" for non-time-critical tasks was immediately > > discounted when I commented that anybody can look at your perl source > > if they want to. > > I'd be interested in finding out how this is reasonably feasible for, > given that you just said a disassembler for Parrot is going to be > relatively simple due to the level of introspection Perl is going to > require. When I added the original encryption mechanism for perl (in early perl 3 days) I knew that it would not be an absolute ban to stop people from recreating my company's original source (and that was long before B::Deparse came along, of course). I certainly knew how to beat the encryption; and anyone with half a clue would know that it could be beaten. (Clue: perl has to be able to read the unencrypted code. It wasn't hard to find the right place in the perl source to insert a print statement that would dump out code that had been decrypted.) However, anyone who took the effort to recreate that source from encrypted form would *know* that any use of that decrypted source was not authorized by the copyright owners. This was considered by that company to be an adequate protection. Any infringement that did occur would clearly be a deliberate misuse and could be prosecuted with a reasonable assurance of success. (No such infringement was ever found - either anyone who considered it decided it would be too much work, or no-one was interested enough to consider it, or quite possibly there were one or more instances where it was decrypted for the challenge of "beating" the encryption but not in any way that lead to an obvious competitive misuse.) Just because you can't make locking perfect does not mean it has no value. --
Re: Closed Classes Polemic (was Re: What the heck is a submethod (good for))
> I think this is an opportune time for me to express that I think the > ability to close-source a module is important. I love open source, > and I couldn't imagine writing anything by myself that I wouldn't > share. But in order for Perl to be taken seriously as a commercial > client-side language, it must be possible to close the source. I > started writing a game with a few friends last year, and as we were > picking our implementation strategy, using Perl as the primary > "sequencing engine" for non-time-critical tasks was immediately > discounted when I commented that anybody can look at your perl source > if they want to. I'd be interested in finding out how this is reasonably feasible for, given that you just said a disassembler for Parrot is going to be relatively simple due to the level of introspection Perl is going to require. Of course, given that Parrot is the ultimate interoperability swiss army knife, one could envision a language without the introspection Perl requires (such as C) that would target Parrot quite nicely. (Isn't Carrot the name for this push? I haven't kept up with the Parrot list.) Then, disassembling that bytecode back to its original form becomes much less desirable. > Of course, there is no argument there for allowing closed-source > *modules*, just complete applications. But I'm sure you could fish > one out involving dynamic loading, or modding, or whatever you want to > call it. The argument that was made was for closing modules, not applications. Specifically, a DB vendor might be more comfortable providing a DBD for their product(s) if they could close the source.
Re: What the heck is a submethod (good for)
On Oct 13, 2005, at 9:47 AM, Matt Fowles wrote: On 10/13/05, Brent 'Dax' Royal-Gordon <[EMAIL PROTECTED]> wrote: Luke Palmer <[EMAIL PROTECTED]> wrote: Okay, I seriously have to see an example of a submethod in use. Likewise. As far as I've seen, submethods are a kludge wedged in for cases where you're actually calling all the way up the inheritence tree. Personally, I've always thought a "cascade method" syntax would be better for that: post method BUILD($foo, $bar) { ... } pre method DESTROY() { ... } Cascade methods would be called (before|after) the indicated method in a superclass was called. I don't think there is a need to restrict it to the wrapping superclasses methods only, there is no reason that you could not also have them wrap a local method too if you wanted. This might actually be a legitimate use for a submethod too. pre method foo () { ... } # this is inherited submethod foo () { ... } # this is not inherited post method foo () { ... } # this is inherited I could see this construct being quite useful in a "Template Method" pattern sort of way. Their return values would probably be thrown away. I think they might actually be a sort of syntactic sugar for inserting `call` in the method body, but that's an implementation detail, really... I have always wondered about the absence of these. CLOS has them and they look quite useful. CLOS has "before", "after" and "around" method qualifiers actually. AFAIK, the return values of these methods are thrown away too, as Brent suggests. One thing to keep in mind is that CLOS has generic functions instead of the usual methods-attached-to-a-class scheme. It also has no (simple) means of calling superclass methods and capturing the return values (at least AFAIK, I am sure someone has hacked the abilities, but I don't think it is part of the spec). The method qualifiers were added to CLOS to allow for this kind of behavior. Since Perl 6 does not suffer from this same issue, method qualifiers are not *needed* like they are in CLOS. That said, they are a nice bit of syntactic sugar (as Brent points out). Maybe this could be done with traits? method BUILD ($foo, $bar) is post { ... } method DESTROY () is pre { ... } Or possibly with some kind of name-mangling: method BUILD:post ($foo, $bar) { ... } method DESTROY:pre () { ... } Stevan
Re: What the heck is a submethod (good for)
All~ On 10/13/05, Brent 'Dax' Royal-Gordon <[EMAIL PROTECTED]> wrote: > Luke Palmer <[EMAIL PROTECTED]> wrote: > > Okay, I seriously have to see an example of a submethod in use. > > Likewise. As far as I've seen, submethods are a kludge wedged in for > cases where you're actually calling all the way up the inheritence > tree. Personally, I've always thought a "cascade method" syntax would > be better for that: > > post method BUILD($foo, $bar) { ... } > pre method DESTROY() { ... } > > Cascade methods would be called (before|after) the indicated method in > a superclass was called. Their return values would probably be thrown > away. I think they might actually be a sort of syntactic sugar for > inserting `call` in the method body, but that's an implementation > detail, really... I have always wondered about the absence of these. CLOS has them and they look quite useful. Was it an intentionaly decision to omit this type of multi method? Matt -- "Computer Science is merely the post-Turing Decline of Formal Systems Theory." -Stan Kelly-Bootle, The Devil's DP Dictionary
Re: What the heck is a submethod (good for)
Luke Palmer <[EMAIL PROTECTED]> wrote: > Okay, I seriously have to see an example of a submethod in use. Likewise. As far as I've seen, submethods are a kludge wedged in for cases where you're actually calling all the way up the inheritence tree. Personally, I've always thought a "cascade method" syntax would be better for that: post method BUILD($foo, $bar) { ... } pre method DESTROY() { ... } Cascade methods would be called (before|after) the indicated method in a superclass was called. Their return values would probably be thrown away. I think they might actually be a sort of syntactic sugar for inserting `call` in the method body, but that's an implementation detail, really... -- Brent 'Dax' Royal-Gordon <[EMAIL PROTECTED]> Perl and Parrot hacker