Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Re: Apocalypse 12

by webfiend (Vicar)
on Apr 17, 2004 at 18:22 UTC ( [id://345999]=note: print w/replies, xml ) Need Help??


in reply to Apocalypse 12

Ouch. I have a bit of a headache as well, and I am only on page 5. It's okay, it's okay, I can keep going. This Apocalypse has me veering wildly between "this will be really really cool" and "this will be a total nightmare to maintain". Sometimes in the same paragraph. Occasionally in the same sentence.

Okay, break time over. Back to trying to digest this thing...

Replies are listed 'Best First'.
Re: Re: Apocalypse 12
by TheDamian (Vicar) on Apr 18, 2004 at 06:11 UTC
    Hmmmmmm. Given that Larry and the rest of us worked very hard to design a syntax and semantics that specifically *improves* the maintainability of OO Perl code, we'd certainly appreciate feedback on those bits you feel will still be total nightmares to maintain. If nothing else, I'd like to get a handle on what people are troubled by in A12, so I can better address their concerns in E12.
      I think that the main thing that concerns people about A12 is just that there are a lot of pieces involved, and they are not sure what you do and do not have to worry about. One message that people really need to hear loud and clear is that they don't need to understand all of them since the changes DWIM. For instance all of the stuff about lexical namespaces etc can be forgotten since if you don't use it, you won't be burned by anyone else using it, and if you do use it, then it does what you'd expect.

      Another major concern is confusion about how traits differ from roles and classes differ from types (really, subtypes, but type is the keyword chosen at the moment). I admit to considerable confusion on traits vs roles until Larry said that a trait is a role on the class. As soon as I knew how the mechanism is supposed to work, I could see the difference. Stated in my own words, A role grants extra methods to objects that are given that role. The role does nothing until you call the methods that it provides, so it is relatively unobtrusive. We say, 'Foo does Bar;' to indicate that you have those methods. But if there is a role on your Class, that role could easily arrange to do whatever it wanted when you were being created. In other words it could have changed what you are, which is why we say, 'Foo is Bar;'. That far more intrusive thing is called a trait. As for classes vs types, while I can describe what a type is, I'm significantly less clear on what practical role is anticipated for them.

      As for my areas of actual concern, they exist but I don't think that E12 is going to be able to address them. Here are a few:
      1. Having read the discussion of how roles will be implemented with multiple inheritance, how well will the role/trait stuff play with people declaring the current inheritance model?
      2. My major concern about any mix-in kind of design (including inheritance and roles) is that people can wind up having methods available and have no idea where the method came from. I'm hoping that there will be a limited number of very useful traits and roles that are built in (or at least widely used) and people don't go about building too many of their own. That will let me amortize the cost of learning them over a lot of usage. This is not, however, fundamentally a language design issue but an education one.
      3. I'd like to understand the proposed aliasing mechanism better than I do. I understand the need (particularly when cooperating across languages), but I'd like to understand how it will be done.
      4. The proposal that we have multiple versions of modules loaded at the same time scares me. I cannot help but think that it is an inherently fragile thing to attempt, particularly if someone does anything dynamic. Problems comes in many flavours, and I'm not sure which bothers me most. Here is a sample.
        • How can the feature help if developers have not specified versions for dependencies? I'm in the habit of just saying "use X", so do most people. Most do likewise. If most of CPAN follows suit, then this great feature will never assist me in the real world because I'll depend on some module that requires some specific version of another module, and the specific version was never specified. Relying on developer behaviour is fragile.
        • How do you handle versioning of proxied modules? For instance suppose that module A dynamically loads any of a number of modules, including B, behind the scenes on behalf of C. (Consider a plugin architecture to see why someone might do this.) How do you address version dependencies between C and B?
        • When will bugs go away? If module X is used by many others, and an annoying bug in it is fixed in module X, people can keep running into that bug until every other module has been updated to say that they work with the newer version of module X. This delay can be rather frustrating for the person who is trying to remove the bug on their local system.
        • What code am I REALLY running? When debugging, one of the more frustrating bugs to track down is when the code that you are running is not the code that you are looking at. Been there, done that. When you load multiple versions of the same software at the same time, this multiplies.
        • Where's my data? When you load CGI.pm, behind the scenes it can read in all of STDIN. (It has to for a POST.) So now a poor web developer has 2 modules, which require different versions of CGI.pm. One gets the data, and the other gets confused. As does the developer who is trying to figure out why CGI.pm just broke. This becomes an issue any time a module has to interact with external resources.
        • What about C libraries? So I'm using a nice XS module, and then go to load 2 versions of it. But each wants a different version of a .dll or .so (either platform, same issue). Unless you figure out how to make the versioning trick work down to the C level, it is going to break on lots of important modules.
        • Feeling bloated? While I'm hardly the first to argue for efficiency over everything else, loading multiple versions of the same software at the same time is a problem. Particularly if the module is supposed to do something like hold my database handle so that I don't need extra database connections...
      5. When I first heard about the idea of trying to support having multiple versions of software on your system, I thought that it was a fundamentally broken idea. No, I don't want the added complexity when I think that it will fail, and complicate my life in the process. That opinion hasn't improved with time...
        4. The proposal that we have multiple versions of modules loaded at the same time scares me. I cannot help but think that it is an inherently fragile thing to attempt, particularly if someone does anything dynamic. Problems comes in many flavours, and I'm not sure which bothers me most. Here is a sample.
        The current library mess is just as fragile in other ways. The whole point of this is to reduce that fragility without inducing additional fragility, and I believe we can.
        * How can the feature help if developers have not specified versions for dependencies?
        If nobody ever specifies a version requirement, we're no worse off than we are now.
        * How do you handle versioning of proxied modules?
        By making sure the interface can be as specific or generic as needed, I suspect. Allowing multiple coexisting versions (where possible) only makes this less fragile in my estimation.
        * When will bugs go away?
        There are a lot of folks who prefer known bugs to unknown bugs. You should know--I particularly had the financial market folks in mind here, having been informed that they like to lock down the versions of *everything* forever. The Perl 6 approach lets them lock down two different versions of the same thing where those versions don't collide dynamically.
        * What code am I REALLY running?
        Shouldn't be a problem within the debugger, which will know which version you're in. If you're poking around the Perl library, I would hope that different versions of the same thing would be stored close enough together that you can at least see that you have a choice.
        * Where's my data?
        Yes, this is a known issue. The basic question is how to mark the modules that can or can't share resources with other versions. And what should be the default...
        * What about C libraries?
        Another known issue, or the same one. Oddly, this shouldn't be a problem with .NET, which is taking the same tack as Perl 6 here, I believe.
        * Feeling bloated?
        Again, that's the external "can't share" problem. Part of the metainfo of a module has to be whether it can coexist with other versions of itself. A database handle is obviously something that can't be shared easily.
        When I first heard about the idea of trying to support having multiple versions of software on your system, I thought that it was a fundamentally broken idea. No, I don't want the added complexity when I think that it will fail, and complicate my life in the process. That opinion hasn't improved with time...
        I think it will solve a real problem for the people who need it solved, and stay out of the way of other people. Especially if we don't botch it.
        My goodness. Such a lot of stuff in one article. I will try to address the concerns separately.
        1. Having read the discussion of how roles will be implemented with multiple inheritance, how well will the role/trait stuff play with people declaring the current inheritance model?
        Should be no problem at all. The internal MI implementation of roles is hidden from view. That's part of what's "funny" about it.
        3. I'd like to understand the proposed aliasing mechanism better than I do. I understand the need (particularly when cooperating across languages), but I'd like to understand how it will be done.
        Me too. :-) I suspect it will involve allomorphic references, but hopefully only at a low-level that can be hidden from the languages in question.

        Certainly there are lots of issues to deal with here. Even what you name your exceptions changes across languages...

        2. My major concern about any mix-in kind of design (including inheritance and roles) is that people can wind up having methods available and have no idea where the method came from. I'm hoping that there will be a limited number of very useful traits and roles that are built in (or at least widely used) and people don't go about building too many of their own. That will let me amortize the cost of learning them over a lot of usage. This is not, however, fundamentally a language design issue but an education one.
        I expect this one to be solved culturally, as you say. Plus it will help to have tools to tell people where their methods came from--when they want to know that, and not sooner.

        I agree wholeheartedly with your reservation regarding versioning.

        Any library, module or class exports two things. It's interface, and it's implementation. Whilst the implementation can go through versions, the interface cannot.

        Once defined, even before implementation, an interface becomes fixed. If the interface later varies, it becomes an new interface. Anything written to comply with the old interface will need to be adapted to use the new one, no matter how small the change.

        You can dress the new version's name up by applying a version number to the old name, but that simply means that the name of the new interface looks superficialy, but misleadingly similar to the old one.

        Even if the new interface is a proper superset of the old interface, it still means that code using either are forced into making loadtime or runtime tests to determine which version of the interface they have access to. In the case of existing code, connecting to the new version, if it remains unmodified, there is the possibility of conflict between new features of that new interface and existing features or extensions added by the pre-existing caller.

        In the case of new code that doesn't now whether it will have the new or old version of the interface at runtime, it must then add code to test for teh availability of the new features and either fail if it doesn;t have them r supply alternatives.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail

      My overall first impression is that Perl 6 will be much better than for Perl 5 for building really large systems, so I'd like to see some examples in E12 illustrating how Perl 6 scales better.

      So far, I like it a lot. The only thing that has caused me to pull a face is the whitespace-changing semantics in the Methods section where Larry commented:

      Yes, this is different from Perl 5. And yes, I know certain people hate it. They can write their own grammar.

      This scares me enough to always put parens around function calls (which I mostly do in Perl 5 anyway). So, if you can unscare me, that would be nice. :-)

        This scares me enough to always put parens around function calls
        You know what's really scary? Depending on how you place your parens, that might not save you. Say you want to call a method (does the new rule count for subroutine calls as well?) which takes an argument, and add 1 to the result. Just like in Perl5, you use parens:
        obj.method ($arg) + 1;
        In that case, you might as well have not put the parens there - it's equivalent to:
        obj.method ($arg + 1);
        If you want to be save, and not depend on unnatural (unnatural in the sense that all major programming languages I know don't have their expressions change meaning depending whether there's a space before an opening paren or not) whitespace rules you have to use an extra set of parens:
        (obj.method ($arg)) + 1;

        Abigail

      To be honest, it's mostly just a reaction to new things. I'm always a little grumpy before I absorb stuff.

      • Submethods throw me a little, but I expect to get the hang of it.
      • New funny characters ($.instancedata and %:classstuff for starters) throw a little more for the folks who like to refer to Perl as line noise.
      • Not drinking enough coffee when you're really used to it can induce mild headaches as well. Doesn't have anything to do with Perl 6, but might have had something to do with my attitude this morning.

      The (admittedly somewhat snide) comment about maintainability was not about the look of Perl 6 OO itself, which I am looking forward to using and abusing. The comment was based on thinking about what potential impact this might have on the code of folks who like to use every language feature in every file of code they write. But I've had my coffee now, and I've had time to think about it, and I'm okay.

      I just want to get in there and start using Perl 6. Not approximations from the Perl6 modules of CPAN, but the actual language. I think I'll go play with Parrot for a little bit :-)

      Update: Yeah, playing with Parrot. Where there's a lovely Perl 6 implementation. The new problem is that it's almost 3am and I really should be in bed. Just ... you know ... disregard pretty much the whole thing.

        disregard pretty much the whole thing.
        Well, no. It provides some useful hints as to where there are genuine fears, uncertainties, and doubts. As do the other replies in this subthread. Much appreciated.
        The comment was based on thinking about what potential impact this might have on the code of folks who like to use every language feature in every file of code they write.
        That *is* an issue. But we've taken the view that there's no way to legislate against that kind of...err...over-enthusiasm. Restricting its feature set doesn't stop fanatics from abusing a language. If anything, it encourages them.

        On the other hand, the professional programmer – like the professional auto mechanic – needs a wide range of tools. Some are very general, and used all the time; most are highly specialized and only occasionally needed. But when those highly specialized tools *are* needed, they can make a huge difference in how easily, quickly, and competently an unusual task can be accomplished.

        Perl 5's OO took the minimalist approach. It used the pliers of packages, the screwdriver of subroutines, and the hex-key of hashes to do most of its work. And that was fine.

        But it meant that when you really needed the electroplater of encapsulation, the compressor of composition, the multigrips of multiple dispatch, the die grinder of delegation, or the router of redispatch, then you had to cobble together your own (or else download "an approximation from the...modules of CPAN" ;-).

        In designing Perl 6 we wanted to provide the complete OO toolset: better standard tools for everyday work, and much better specialized tools for unusual situations. Even if that means that some folks will misuse our lovely new counter-reciprocating 3/4 Whitworth flange-wrench as a hammer.

        *That's* a problem that can only be addressed by educators, not toolsmiths.

      I started reading Apocalypse 12, and at first I liked what I saw. Not having instance variables is the root of all Perl5 OO evil, and perl6 will fix that.

      Then I read about the whitespace sensitive rules and I said, yeah, whatever and lost interest. If you want a maintainance nightmare, program in a language where the value of an expression changes depending whether there's whitespace between tokens or not.

      Abigail

        program in a language where the value of an expression changes depending whether there's whitespace between tokens or not.

        Like Perl 5?

        print 3 . 5; print 3.5; print "$foo{bar}"; print "$foo {bar}";
        And more. Still, I think you should not do the yeah-whatever thing. Instead of losing interest, read on to see this part:
        And yes, I know certain people hate it. They can write their own grammar.
        He means you.

        Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

        The closest example to this that I've run into is extremely close. When Perl changed the interpretation of "print (" to be the same as "print(", I found that the problems clearly increased, and stayed up even long after the change. So I enthusiastically support Perl6's idea to not allow whitespace in a few key places where whitespace has no good reason to be.

        Putting whitespace between a hash and the '{' makes as much sense to me as wanting to write "10 . 45 e - 12" because it is "easier to read" (no, actually wanting spaces in some numbers makes more sense to me).

        Not all whitespace improves readability. "$foo {bar}" looks like a scalar followed by something and causes me to fault and backtrack in my parsing of the code when I can't figure out why the code even compiles. Why have you crouded $ and foo so close together? That must be hard for you read. q-:

        I realize that the tokenizer considers the tokens to be '$', 'foo', then '{' for that case but considers '10.45e-12' to be single token. But my "tokenizer" sees '$foo{' as a single conceptual token and breaks the number into '10.45' and 'e-12'.

        - tye        

        When I heard of your whitespace issues with Perl6 in earlier Apocalypses, I thought you were over-reacting. But after reading Apoc. 12, I'm ready to jump on board (though perhaps not with the same vigor).

        Though I've never seen a language that is completely free of whitespace restrictions, it's usually because the designers could only go so far in getting rid of it. I don't like seeing it put intentionally into a language.

        (Perhaps my only exception is OCaml, where function parameters are seperated by whitespace. You've got to seperate them with something, and I don't think making the choice between seperating with 0x20 instead of 0x2C is a big deal. I haven't used it enough, though, to see if it makes a difference in real code.)

        ----
        : () { :|:& };:

        Note: All code is untested, unless otherwise stated

        We need to start a club, my friend. You can be the VP of Whitespace Bitching and I'll be the VP of Indirect Syntax Bitching. Anyone else want to sign up? :-)

        ------
        We are the carpenters and bricklayers of the Information Age.

        Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      I've been looking forward to A12 for a while and I don't think I'm disappointed. - There's plently of stuff I haven't grokked yet - but the stuff I do really excites me.
      The only concern I have at the moment, is the many references to compiler optimizations, as below...

      It might be objected that this will slow down the parameter binding algorithm for all methods favored with an implicit *%_, but I would argue that the binding code doesn't have to do anything till it sees a named parameter it doesn't recognize, and then it can figure out whether the method even references %_, and if not, simply throw the unrecognized argument away instead of constructing a %_ that won't be used. And most of this "figuring out" can be done at compile time.
      Will Perl6 not still have eval? - Will this not have an impact on any compiler optimizations that I don't explicitly ask for?
      e.g. What if the above method's 'extra' arguments are thrown away, but auto-genereated code inside an eval tries to reference it? How can the compiler ever be sure enough to make that optimization except in the most trivial example?
      method foo { return 1 }
      However, I don't know a thing about compilers, so I don't know what I'm talking about - just giving you feedback on what I'm "troubled by" ;)
        Yes, Perl 6 will certainly have eval, and yes, it will certainly disable certain kinds of optimizations--just as it does in Perl 5. That's the nature of the beast. And if you're going to compile a program for your PDA, the size of the executable may grow dramatically if you use eval, since it then has to include the compiler.

        It's just that eval, like goto, is the most general thing in its class. You never want to use either of those when there is a more specific construct that does what you want. Just as we've added various controlled forms of goto over the years, we've looked at the various uses of eval over the years and abstracted out various common operations like aliasing, symbolic references, and closure generation.

        As for all the references to optimizations, don't sweat it. It's something language designers and implementors are supposed to worry about, and that concern leaks through at times. But most users shouldn't have to worry about it, at least until they have a bit of code they need to make run faster.

        The block form of eval (like your example) can be parsed at compile time along with everything else. I think where the optimizer is going to have to be careful is if you use the string form of eval. In that case, some stuff just won't get optimized that otherwise could be. So the performance-is-vital people will be telling us not to use string eval, and I can safely ignore them if I don't care about optimization :-)


        ;$;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$;[-1]->();print

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://345999]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (6)
As of 2024-04-18 04:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found