Re: DBI v2 - The Plan and How You Can Help
Maxim Sloyko wrote: I don't think this solves the problem, because what I usually want is the user to be able to use the application, but unable to see the DB password. So the user should have read permission set for the file, but on the other hand he shouldn't. It's not not a problem for Web App, though. Storing passwords encrypted, decrypting before using doesn't cover this? I've played around with Crypt::CBC (and different ciphers) for this sort of thing but admittedly have not applied this to any production systems yet. You still have a key somewhere to hide/obscure. You can also use Perl source filters to totally encrypt the source -- something else I've done but not in production. Just some things you may want to look at ... -- Steve Sapovits [EMAIL PROTECTED]
Re: Submethods
Stevan Little wrote: The concept of non-inherited infrastructural methods is fairly simple to accomplish in the meta-model, by just giving submethods their own dispatch table inside the metaclass. However where I am somewhat confused is in how and when they get called. I think the question is posed a bit confusingly. Since as you point out, when the invocant is clear, calling the (sub)method is an easy lookup in its vtable with subsequent call. Take this example for instance: class Foo { method bar () { ... } submethod bar () { ... } } Is this an error (Synopsis 12 seems to indicate it is *not* an error)? The only inconvenience I see is that the name Foo::bar is not unique. The sigil doesn't disambiguate because in both cases it is Foo::bar. Furthermore the :() is used only to distinguish different sigs, not the Code subtype behind the name. Hmm, or is this a special cased two-entry MMD table? One entry for bar:(Foo) and one for bar:(MetaClass[Foo])? When I call bar() on an instance of Foo, which is called? The method? or the submethod? Is it somehow dependent upon the calling context? (called from within the class, or from outside the class). Take for instance, this example: class Foo { method bar () { ... } submethod bar () { ... } method baz ($self:) { $self.bar() # which one does this call? } } I think this is pretty clear. There is exactly one class object Foo but many instances. The submethod can only be called on the Foo class object which is available through the .meta method. Thus to call the submethod one needs $self.meta.bar(). I doubt the usefullness of falling back to submethod lookup in the class chain when an object doesn't have the method. There's actually no syntactical distinction possible because of: my $object = new Foo; my $meta = $object.meta; $meta.bar() # calls submethod but looks like method call I guess the type of $meta is Ref of Class or somesuch. Regards, -- TSa (Thomas Sandlaß)
Re: SMD is for weenies
Yuval Kogman [EMAIL PROTECTED] writes: On Fri, Jul 01, 2005 at 13:42:34 +1200, Sam Vilain wrote: Yuval Kogman wrote: As I understand it SMD is now not much more than a mechanism to place a constraint on the MMD, saying that there can only be one method or subroutine with the same short name. Why is this the default? Otherwise you lose this quite useful warning if the signatures didn't match; method foo redefined at ... That's a good point... I'm guessing that the default warnings should have a warning for MMD methods which append to a short name without appearing immediately after each other in the same file. I agree with you MMD is very cool, and I use it a lot. But I don't mind clarifying the intent with multi; this overloading is considered by some to be surprising to new programmers. Prepending 'mutli' is not a problem when I have to type it. It's a problem when others won't type it. When 90% of the module code I'll be using is not MMD compatible, because MMD is not the default, I can't specialize other people's code without editing it (at runtime or at the source level). Overloading won't happen unless people overloading semantics are introduced, and that's exactly what I'd like to do to other people's code occasionally. Then write yourself a module, call it 'multiplicity' say, which would allow you to say use multiplicity; sub foo (...) {...} # foo is a multimethod, even if there's already a 'SMD' # foo in existence. It shouldn't even be that hard, just macroize sub/method/whatever to become multis that first check if there's already a singly dispatched sub with the same name and promoting to multi status if possible. Of course, if you use something like that, you're taking the risks on your own head, but you knew that as soon as you typed 'use multiplicity'. The important thing is that the dispatch and reflection system should be flexible enough to allow you to write something like this.
Re: Type variables vs type literals
HaloO Larry, you wrote: Well, there's something to be said for that, but my gut feeling says that we should reserve the explicit generic notation for compile time processing via roles, and then think of run-time lazy type aliasing Could you explain what exactly 'run-time lazy type aliasing' is? I mean what does it achieve and how does it compare to type instanciation and parametric contraint checking? as something a little different. So if you really want to write that sort of thing, I'd rather generalize roles to work as modules containing generic subs: role FooStuff[T] { sub foo (T $x, T $y) { } ... } Otherwise people are tempted to scatter generics all over the place, and it's probably better to encourage them to group similarly parameterized generics in the same spot for sanity. It also encourages people to instantiate their generics in one spot even if they're calling them from all over. [..] I think people should say does FooStuff[Int] and automatically alias all the routines to the Int form so we don't have to scatter :[Int] all over. Or if they just say does FooStuff, they get lazily-bound type parameters. I get that right, FooStuff can be instanciated without a class or object? Something like unary operator does? Into which scope do these role instanciations go? Does does *FooStuff[Int] mean global? : ::T $x := $obj; : my T $y = $x; : : The prime use of that feature is to ensure type homogenity for : temporary and loop vars in a certain scope. But the scope in the : above syntax is not apparent enough---to me at least. Actually, I was holding those up as bad examples of scope visibility, so I'm agreeing with you there. (Which is why I suggested that we require a my context, even if only implied by the formal paramter list.) : Thus I opt for an explicit : :subtype T of $obj.type; # or just $obj perhaps? :T $x := $obj; :my T $y = $x; Yuck. I think that completely obscures the lazy type binding. Plus you've managed to omit the my, so you've created a global subtype T. (Unless, as I'm leaning towards, we make such bare inner types illegal, and require my, our, or *.) The only thing I did was to replace the :: sigil with a subtype declaration. Does subtype always go into global scope? I thought that it requires a *name to go into global and our to go to the innermost module---or was that package? I mean even non-declared auto-vivified vars go into the immediately surrounding scope, or am I horribly mistaken? sub foo() { if (1) { $x = 'from above' } if (2) { say $x } # prints 'from above' even if no outer $x exists? say $x; # prints undef or 'from above' if outer $x } Up til now I assumed that ::T and plain T mean exactly the same if T is pre-declared/defined. The type sigil is only needed to defer the definition/binding. In a certain sense this is a hanging type reference similar to foo beeing a reference to Code. Which brings me to the question how to bind a type reference. I mean we have my fooref := foo which allows fooref() calls, right? How are type references derefed if not by dropping the sigil? ::TypeRef() perhaps? my ::TypeRef; # type variable? sub make ( ::Type, Type $value ) returns Type { if (::TypeRef != ::Type) { ::TypeRef = ::Type; } my Type $x; $x = $value; return $x; } my $i = make(Int, 17); my @a = make(Array, [1,2,3]); # single element array? # or three element array? my $e = make(Int 'string'); # type error in make? With the automatic binding of a ::Type variable to the type of it's argument the definition of make could be shortend to sub make ( ::Type $value ) returns Type { ... } and called like this my $i = make(17); which at least prevents type errors ;) Regards, -- TSa (Thomas Sandlaß)
Re: SMD is for weenies
On Wed, Jul 06, 2005 at 12:58:44 +0100, Piers Cawley wrote: Then write yourself a module, call it 'multiplicity' say, which would allow you to say use multiplicity; sub foo (...) {...} # foo is a multimethod, even if there's already a 'SMD' # foo in existence. It shouldn't even be that hard, just macroize sub/method/whatever to become multis that first check if there's already a singly dispatched sub with the same name and promoting to multi status if possible. Of course, if you use something like that, you're taking the risks on your own head, but you knew that as soon as you typed 'use multiplicity'. The important thing is that the dispatch and reflection system should be flexible enough to allow you to write something like this. The issue is cultural, not technical. If people expect SMD, use it, rely on it, MMD is just another esotheric feature. Newbies' code will not exploit. Most of CPAN will not be ready for it. I won't write me such a module because it'll be more headache than benefit - explaining to everyone that in my code I like everything MMD. What I'm claiming is that MMD like behavior should be the norm. When it's not appended with true multiness, it's functionally identical to SMD. The issue is that extending another person's module with a multimethod, and using type/parameter dispatch in order to help code evolve better over time will never be a good or normal thing to do if it feels kludgy. My claim is that it doesn't need to feel kludgy. A macro library kludging over a kludge is twice as kludgy as it was before. -- () Yuval Kogman [EMAIL PROTECTED] 0xEBD27418 perl hacker /\ kung foo master: /me does a karate-chop-flip: neeyah!! pgpxgy79xINw9.pgp Description: PGP signature
This week's summary
The Perl 6 summary for the week ending 2005-07-05 My, doesn't time fly? Another fortnight gone and another summary to write. It's a hard life I tell you! This week in perl6-compiler Where's everyone gone? It seems that most of the Perl 6 compiler development is being discussed at Hackathons and IRC, and summarized in developers' weblogs. What's a summarizer to do? For now, I'll point you at Planet Perl 6, which aggregates a bunch of relevant blogs. http://xrl.us/gn5n PGE now supports grammars, built-in rules Allison Randal raved about the totally awesome PGE grammar support. I doubt she's alone in her enthusiasm. http://xrl.us/gn5o Multiple implementations are good, m'kay? Patrick discussed the idea of a 'final' Perl 6 compiler, pointing out that it isn't clear that there needs to be a final compiler. So long as multiple implementations are compatible... http://xrl.us/gn5p Meanwhile, in perl6-internals New calling conventions Klaas-Jan Stol asked a bunch of questions about the new calling conventions and Leo answered them. http://xrl.us/gn5q Parrot Segfaults What's a tester to do? You find a bug that makes Parrot dump core, so you write a test to document the bug and make sure it gets fixed. But the test leaves core files lying about. It goes without saying that Parrot should never dump core without the active assistance of an NCI call or some other unsafe call blowing up in its face. Which makes it a little embarrassing that PIR code generated by Pugs can cause a parrot segfault, though that appears to have been caused by mixed up calling convention style in the generated call. http://xrl.us/gn5r http://xrl.us/gn5s - Brian Wheeler's segfaulting Pugs script Python PMCs Leo pointed out that the various dynclasses/py*.pmc parrot support PMCs don't yet support all the semantics that Python needs. He outlined some outstanding issues announced that, as calling conventions and context handling were changing he'd be turning off compiling py*.pmc for the time being. http://xrl.us/gn5t PGE bug It appears that the upcoming changes in Parrot's context handling tweak a bug in PGE. The discussion moved onto a discussion of PGE's implementation strategy, Nicholas Clark was keen to make sure it didn't repeat some of the Perl 5's regex engine's infelicities. While this discussion continued, Leo spent half a day with gdb and tracked down the problem, which turned out to be that a register wasn't getting initialized in the right place. http://xrl.us/gn5u Left-recursive grammars are bad m'kay? While experimenting with PGE grammars, Will Coleda managed to write a left-recursive grammar that blew Parrot's call stack with impressive ease. Luke apologized for things blowing up so spectacularly, but pointed out that left-recursive grammars weren't supported, and showed a rewritten grammar that didn't have the same problem (but which doesn't appear to match the same expressions). http://xrl.us/gn5v Coroutines Leo pointed to a summary of coroutines, and noted that we still hadn't defined the syntax of Parrot coroutines, especially with respect to argument passing. He discussed it with Matt Fowles and solicited a set of tests that expressed the semantics they came up with. http://xrl.us/gn5w ftp://ftp.inf.puc-rio.br/pub/docs/techreports/04_15_moura.pdf ParTcl, Perl6 Grammars Will Coleda announced that, thanks to Matt Diephouse's work, ParTcl (Tcl on Parrot) is now able to run part of tcl's cvs-latest test suite. The tests aren't fully native yet, they're currently driven through a Perl test harness and only passing 10% of the tests, but hopefully the situation will improve and ParTcl will end up able to run the tests completely natively (while passing far more of them). Congratulations on the work so far though. http://xrl.us/gn5x Python and Parrot Kevin Tew popped up to say that he too is working on a Python compiler targetting parrot and wondered how to handle things like Python's self parameter. Michal Wallace and Leo chipped in with suggestions. http://xrl.us/gn5y Another month, another release Has it really been a month? Seems so. Parrot walked through the traditional feature freeze, code freeze before being released on Sunday. The latest release is called 'Geeksunite', referencing the website that discusses Chip's problems with his former employer. You should definitely visit the Geeksunite site -- Chip needs our help. http://xrl.us/gn5z http://geeksunite.org/ -- Support your local Pumpking lower in default find_name scope Patrick posted a code fragment whose output surprised him -- it turned out that looking up lower as a name in the default scope returns an NCI object.
Re: Submethods (+ suggestion/proposal/idea)
Thomas, On Jul 6, 2005, at 10:19 AM, TSa (Thomas Sandlaß) wrote: S12 says in the section Submethods: A submethod is called only when a method call is dispatched directly to the current class. And without finding a reference I think it was said that the invocant of a submethod is a class object. I took that statement to mean that methods were not inherited, and that they can only be called from methods within the class they were defined. From this I have derived what I said. Nonetheless there seems to be some overlap in particular in the construction process which is characterized as involving an unitialized object. So in that case some macro magic might make the instance available to the submethod. But this will be a non-invocant parameter. This is a possibility, however, i think that submethods are more valuable if they dealt with invocants rather than just with classes (metaclasses). It seemed to me from A12 that submethods are meant to define an interface of some kind, the BUILD/DESTROY submethods being the perfect example. However this means that BUILDALL and DESTROYALL need to be fairly magical. I say this because BUILDALL would have to extract some kind of class list from it's invocant, and call $self.SomeClass::BUILD() on each class. And since BUILDALL is (supposedly) defined in Object, (and I assume it too is a submethod), it becomes critical (in some cases) for Object::new to be called. =begin RANT/SUGGESTION While I like the idea of infastructural methods, I think maybe we should place more restrictions on them. Ideally the object model itself would create a set of these interfaces. One for creation (BUILD/BUILDALL) and for destruction (DESTROY/DESTROYALL), and maybe a few others. And then the model itself would utilize them, but the user would not (easily) be able to add to these submethods. I think this would greatly simplify the concept of submethods, and also allow for more advanced users to add new interfaces to the object model. This could (theoretically) allow for low-level manipulation of the object model while still making it simple for not-as-advanced users to use it easily by just following the interface. For instance, here is a very simply and naive example of a persistant interface of sorts: Object.meta.add_submethod('FREEZE' = sub { ... }); Object.meta.add_submethod('THAW' = sub { ... }); Object.meta.add_submethod('FREEZEALL' = sub ($self:) { for $class - $self.meta.get_class_list() { $self.($class)::FREEZE(); } }); etc etc etc ... Then a user could simply define a FREEZE and THAW submethod in each of their classes they want to be persistent. Or something like that :) =end RANT/SUGGESTION Anyway, just a thought. Stevan But mind the sig! -- $TSa =:= all( none( @Larry ), one( @p6l ))
Re: Time::Local
Juerd wrote: I think the problem one has is much bigger even if a day *number* is ever displayed. Then beginning with 1 because that's where most humans begin counting, is wrong. It's a technical thing, and that should be kept as simple as possible, and as technical as possible, for easier compatibility with existing technical things. As a technical remark I like to point out, that you need 8 time points to define 7 days. Every day is bounded by two such time points---which are of course 24 hours apart. This is necessary to get the arithmetic right! Weekday arithmetic is modulo 7. Or put differently $week.end() - $week.start() == $week.length == 7 days must hold. If e.g. you start your week with Monday than this becomes $Sunday.end() - $Monday.start() == 7 days. The next order of precision in calender arithmetic is the hour *within* the day, then minutes and seconds. The weeks themselfs are subdivisions of years. And the scheme is not completely regular in e.g. the Gregorian calendar---but almost e.g in the Sym454 calendar which only has leap weeks. I think, that this type of integer with remainder arithmetic shows up in Perl6 in other places as well. E.g. chars in strings depending on the Unicode level and index arithmetic of arrays. Some unification of the underlying math would be nice, indeed. And that typically involves starting from 0 and the positive remainder pointing into the day. Regards, -- TSa (Thomas Sandlaß)
Re: Submethods
On Wed, Jul 06, 2005 at 04:19:40PM +0200, TSa (Thomas Sandlaß) wrote: : Stevan Little wrote: : You seem to indicate that submethods are not to be used on instances, : and instead to be used on the underlying metaclass. I did not see : anything of the sort in (Syn|Apoc)12 or in my (limited) search of the : mailing list. Can you point me to that information? : : S12 says in the section Submethods: A submethod is called only when a : method call is dispatched directly to the current class. Ah, you're reading a little too much into an imprecise statement. The intent is not to limit it to class methods--it's using current class to be inclusive of its members. It should say something more like A submethod is called only when a dispatcher decides to call a method via this exact class. This can be because a) this class, out of all the candidates, happens to be the class the dispatcher is currently thinking about, or b) the method call itself is qualified to specify which class to call explicitly (and for that particular class only, the constraint on exact class matching is relaxed as if it were an ordinary subroutine call). Or c) you call a submethod as an MMD function, in which case the first invocant of a submethod is constrained to be an exact class match, or resolve to an ordinary method. Or d) you call it as a qualified function name, in which case it's a simple function call. : And without finding a reference I think it was said that the invocant : of a submethod is a class object. You won't find that one because I don't think anyone ever said it. : From this I have derived what I said. Nonetheless there seems to be : some overlap in particular in the construction process which is : characterized as involving an unitialized object. So in that case : some macro magic might make the instance available to the submethod. : But this will be a non-invocant parameter. Nope, it's just the normal invocant. Submethods differ from ordinary methods only in not being derivable. (Well, and the fact that they often operate on partially instantiated objects, as you point out.) Now in the particular case of a CREATE submethod, you have to get the class because object isn't created yet. But generally you don't need to define one of those unless you don't want to use the built-in opaque type. So the usual course of events is that some constructor (probably called new) calls MyClass.bless(%args) and that in turn calls my $newobj = MyClass.CREATE(%args); $newobj.BUILDALL(%args) which, after calling all the ancestral BUILDs, calls $newobj.MyClass::BUILD(%args) or maybe $newobj.=MyClass::BUILD(%args) or possibly even MyClass::BUILD($newobj, %args) if it doesn't want to fail over to Object::BUILD in the absence of MyClass::BUILD. But all that's behind the scenes. The basic cargo cult version for naive users is, Write a 'BUILD' submethod if you want to initialize the attributes with dynamic data that can't be expressed with default values. And write your own constructor if you don't like the built-in default constructor. Just make sure your own constructor calls $class.bless(%args). Larry
Re: Submethods (+ suggestion/proposal/idea)
On Wed, Jul 06, 2005 at 11:28:47AM -0400, Stevan Little wrote: : It seemed to me from A12 that submethods are meant to define an : interface of some kind, the BUILD/DESTROY submethods being the perfect : example. However this means that BUILDALL and DESTROYALL need to be : fairly magical. I say this because BUILDALL would have to extract some : kind of class list from it's invocant, and call : $self.SomeClass::BUILD() on each class. And since BUILDALL is : (supposedly) defined in Object, (and I assume it too is a submethod), : it becomes critical (in some cases) for Object::new to be called. Most of these submethods will have a generic ordinary method backing them up in Object. But Object::new isn't where that magical call to BUILDALL happens. It's the SomeClass.bless that does it magically, and the default Object::new just happens to call .bless. : =begin RANT/SUGGESTION : : While I like the idea of infastructural methods, I think maybe we : should place more restrictions on them. Ideally the object model itself : would create a set of these interfaces. One for creation : (BUILD/BUILDALL) and for destruction (DESTROY/DESTROYALL), and maybe a : few others. And then the model itself would utilize them, but the user : would not (easily) be able to add to these submethods. But we want people to be able to add BUILD methods easily. : I think this would greatly simplify the concept of submethods, and also : allow for more advanced users to add new interfaces to the object : model. This could (theoretically) allow for low-level manipulation of : the object model while still making it simple for not-as-advanced users : to use it easily by just following the interface. Well, bear in mind that declarators like submethod are just disguised calls on some metaobject already. : For instance, here is a very simply and naive example of a persistant : interface of sorts: : : Object.meta.add_submethod('FREEZE' = sub { ... }); : Object.meta.add_submethod('THAW' = sub { ... }); : : Object.meta.add_submethod('FREEZEALL' = sub ($self:) { : for $class - $self.meta.get_class_list() { : $self.($class)::FREEZE(); : } : }); : : etc etc etc ... Well, sure, except you might want the methods in Object to be inherited, and use submethods only for specific overrides of the default. But the syntax seems a bit klunky. I suspect it's just something more like Object does FreezeThawDefault. : Then a user could simply define a FREEZE and THAW submethod in each of : their classes they want to be persistent. : : Or something like that :) I don't think that's terribly far away from what we've got already. Larry
Re: Time::Local
On Wed, 6 Jul 2005, Juerd wrote: I think the problem one has is much bigger even if a day *number* is ever displayed. Then beginning with 1 because that's where most humans begin counting, is wrong. It's a technical thing, and that should be kept as simple as possible, and as technical as possible, for easier compatibility with existing technical things. Calling Sunday 1 and not having a 0 would certainly upset and offend me. My weeks begin on Mondays, as do most people's weeks here. At the same time, I can accept any day as the first day if that first day is 0, because 0 is technical and internal anyway, not meant for humans. I'm sure lots of people would want an index 1 to be Sunday, if there is no index 0. This all is solved simply by NOT skipping 0, and using an arbitrarily chosen day for the first. Or, well, for compatibility, Sunday :) Computers and Perl count from 0. People count from 1. If something begins at 1, it is expected to be a people's thing. And with week days, this just doesn't work, as not everyone's week starts at the same day. On reflection, I realized it doesn't matter too much to me. In the end, I'm likely to need a higher-level interface than this to do something interesting (like print a day _name_ or calculate the second Sunday of the month) and that interface will just use the information Perl's builtins give it. -dave /*=== VegGuide.Orgwww.BookIRead.com Your guide to all that's veg. My book blog ===*/
Object Creation (was: Submethods (+ suggestion/proposal/idea))
Larry, Okay, I reviewed A12, and I think I have now managed to implement the proper object creation behavior in the meta model. Currently it is somewhat limited, but this is the order of events (as I understand it from A12). - First Object.new calls Object.bless passing all named arguments. - Object.bless then calls Object.CREATE which then returns a data structure for the instance (P6opaque only right now). - Object.bless then blesses this structure (since the prototype is in Perl5 it just passes the structure returned by CREATE into CORE::bless(), I am sure it will be different in the proper Perl6). - Object.bless then calls $instance.BUILDALL (again passing all the named params). - $instance.BUILDALL then does a post-order traversal of the class hierarchy calling BUILD on all classes (again passing in the named parameters). Of course CREATE, BUILDALL and BUILD are not proper submethods yet because Perl6::Object is not self defining yet. And it only supports 'P6opaque' right now, but I think I have the ordering of events correct, however, please correct me if I am wrong. Oh yeah, and all that silliness I wrote below,.. ignore it :) Thanks, Stevan On Jul 6, 2005, at 1:45 PM, Larry Wall wrote: On Wed, Jul 06, 2005 at 11:28:47AM -0400, Stevan Little wrote: : It seemed to me from A12 that submethods are meant to define an : interface of some kind, the BUILD/DESTROY submethods being the perfect : example. However this means that BUILDALL and DESTROYALL need to be : fairly magical. I say this because BUILDALL would have to extract some : kind of class list from it's invocant, and call : $self.SomeClass::BUILD() on each class. And since BUILDALL is : (supposedly) defined in Object, (and I assume it too is a submethod), : it becomes critical (in some cases) for Object::new to be called. Most of these submethods will have a generic ordinary method backing them up in Object. But Object::new isn't where that magical call to BUILDALL happens. It's the SomeClass.bless that does it magically, and the default Object::new just happens to call .bless. : =begin RANT/SUGGESTION : : While I like the idea of infastructural methods, I think maybe we : should place more restrictions on them. Ideally the object model itself : would create a set of these interfaces. One for creation : (BUILD/BUILDALL) and for destruction (DESTROY/DESTROYALL), and maybe a : few others. And then the model itself would utilize them, but the user : would not (easily) be able to add to these submethods. But we want people to be able to add BUILD methods easily. : I think this would greatly simplify the concept of submethods, and also : allow for more advanced users to add new interfaces to the object : model. This could (theoretically) allow for low-level manipulation of : the object model while still making it simple for not-as-advanced users : to use it easily by just following the interface. Well, bear in mind that declarators like submethod are just disguised calls on some metaobject already. : For instance, here is a very simply and naive example of a persistant : interface of sorts: : : Object.meta.add_submethod('FREEZE' = sub { ... }); : Object.meta.add_submethod('THAW' = sub { ... }); : : Object.meta.add_submethod('FREEZEALL' = sub ($self:) { : for $class - $self.meta.get_class_list() { : $self.($class)::FREEZE(); : } : }); : : etc etc etc ... Well, sure, except you might want the methods in Object to be inherited, and use submethods only for specific overrides of the default. But the syntax seems a bit klunky. I suspect it's just something more like Object does FreezeThawDefault. : Then a user could simply define a FREEZE and THAW submethod in each of : their classes they want to be persistent. : : Or something like that :) I don't think that's terribly far away from what we've got already. Larry
Dependency Injection
So, I got to thinking about stuff. One of the more annoying things about writing nicely decoupled objects and applications are those occasions where you want an object to be able to create objects in another class. Say you've provided a singleton interface to your logging system. The naive implementation goes something like: require Logger; has $.logger; method logger { $.logger //= Logger.new } method whatever { ./logger.debug(About to do stuff); .do_some_stuff; ./logger.debug(Did stuff); ... } But that's problematic because we've backed knowledge of the particular class that handles logging into our class. The bad solution to this is to subclass our class if we want a different Logger class (that conforms to the same interface). A slightly better solution is to parametrize the logger class name, probably with a class variable -- but doing that means you have to remember to set the variable for every class you use. Or you could use a global, but globals are bad... It'd be really cool if you could essentially write the naive implementation above and have your application/test/webserver harness decide which particular class will be taken to be the concrete implementation. Something like this: role Logger is Injected { method debug {...} method info {...} ... } Logger::DBI does Logger { ... } Logger::Debugger does Logger { ... } Then the harness that actually sets up the application would simply do use Logger::DBI :dsn..., :user..., :password and Logger::DBI would install itself as the default Logger class. The question is, how does one write Injected to make this work? Or what features do we need to be able to write Injected? Thinking about this, it shouldn't be too hard to implement 'Injected' in Perl 5: sub Injected::AUTOLOAD { no strict 'refs'; die If something's already been instantiated you're screwed if ref($_[0]) or $Injected::injecting; local $Injected::injecting = 1; my $target_role = $_[0] my @possibles = grep {/(.*)::$/ $1-isa($target_role)} keys %::; die Too many possibles if @possibles 1; if (@possibles) { *{$target_role\::} = *{$possibles[0]}; } else { my $default_package = $target_role-default_class; eval require $default_package or die Can't find a default package; *{$target_role\::} = *{$default_package\::}; } {$target_role-can($AUTOLOAD)}(@_); } NB, that's completely untested code, but it, or something like it, should work.
Re: DBI v2 - The Plan and How You Can Help
Maxim Sloyko wrote: But this is not the point. The point was that usage of some file with passwords by *DEFAULT* is not the way to go, IMHO. It raises more problems than it solves. Can you give an example of such a problem that wasn't already there? Just to be clear, the file would only need to contain passwords if the DBD requires them. Sam.
Re: Dependency Injection
Piers Cawley wrote: Then the harness that actually sets up the application would simply do use Logger::DBI :dsn..., :user..., :password and Logger::DBI would install itself as the default Logger class. The question is, how does one write Injected to make this work? Or what features do we need to be able to write Injected? Thinking about this, it shouldn't be too hard to implement 'Injected' in Perl 5: FWIW this is exactly what I would like to achieve with the Date objects; allowing code that doesn't care about which Date representation they want the ability to just say any Date representation. Sam.
Re: Dependency Injection
On Wed, Jul 06, 2005 at 11:47:47PM +0100, Piers Cawley wrote: : Or you could use a global, but globals are bad... Globals are bad only if you use them to hold non-global values. In this case it seems as though you're just going through contortions to hide the fact that you're trying to do something naturally global. You might argue that a singleton object lets you hide the implementation of the delegation from the world, but there's really not much to implement if you just want to tell the world that whenever the world says LOGGER the world is really delegating to LOGGER::DBI. Plus if you really need to reimplement you just vector the world through LOGGER::SELECTOR or some such. One nice thing about a variable is that you're guaranteed to be able to temporize it: temp $*LOGGER = pick_a_logger(); On the other hand, there's no reason a role can't play with a global variable, and arbitrate the use of the global among all the classes that want to delegate through the global. But a role is not allowed to function as its own singleton object, because roles don't define objects. On the gripping hand, the package holding the role's namespace is a perfectly fine spot for such singular information. Every named package/module/class/role/subtype is a kind of global singleton hash of the symbol table persuasion. But if globals are inherently bad, we should remove them from Perl 6. Hmm, this raises the question of whether a role-private class variable actually belongs in the class's or in the role's namespace: role Baz { our $:x; } FooBar does Baz; BarFoo does Baz; Does $:x end up being a private global in the Baz package or a global shared between the FooBar and BarFoo packages? That kinda goes along with the question of whether attributes in general belong more to the role or the class into which the role is composed. It seems like all those cases can be useful, so maybe we need a syntax to distinguish role attributes from class attributes. To think of it another way, which delarations are to be taken literally, and which generically? And which way should be the default? For this particular use, you want some semantics resembling: role LOGGER { role:our $:logger handles Any; role:submethod BUILD ($logger) { fail Logger already set if defined $:logger; $:logger = $logger; } ... Not necessarily recommending that syntax, of course. Could just default declarators to class semantics and force role declaratoins to be explicit: role LOGGER { our $:LOGGER::logger handles Any; submethod LOGGER::BUILD ($logger) { fail Logger already set if defined $:logger; $:logger = $logger; } ... But that seems a bit klunky, especially given the way package names and twigils interact. And don't even think about using $?ROLE there. Plus we've never let you use our on a qualified name before. This really seems to be somewhat orthogonal to everything else, so maybe we need some orthogonal syntax: role LOGGER { mumble our $:logger handles Any; mumble submethod BUILD ($logger) { fail Logger already set if defined $:logger; $:logger = $logger; } ... for some value of mumble that implies non-generic. Need to think about this some more. I *don't* think it's viable to make non-generic the default unless we do it only for variables. But then you'd be forced to write our BUILD ::= submethod ($logger) {...} to get a non-generic BUILD submethod, and that's more than a bit ugly. So I'm still mumbling... Larry
Re: SMD is for weenies
It's possible that we could do the following: 1) All subs (and methods) are considered multi 'under-the-hood'. 2) If the first declaration is explicitly 'multi', then you (or others) can provide additional overloads (using 'multi') that won't trigger warnings. 3) If the first declaration /doesn't/ use 'multi', then defining another sub/method of the same name triggers an error/warning. BUT, later declarations can override this by using some sort of special declaration. e.g. sub foo(Int $x) { ... } sub foo(Str $x) { ... } # error/warning multi sub foo(Int $x) { ... } multi sub foo(Str $x) { ... } # ok sub foo(Int $x) { ... } sub foo(Str $x) is overload { ... } # ok; not sure about the trait name This provides uniqueness checking for SMD subs by default, while still allowing hardcore hackers to overload other people's subroutines without their explicit consent. It's not as clean as Yuval's suggestion, but I think it might be more acceptable to folks who are used to SMD. Stuart