寫腳本易,寫程序難。

看看 perl 之父 larry wall 指點江山


介紹兩個英文翻譯網站,可能會有幫助。


www.zhuaniao.com

www.dict.cn


Programming is Hard, Let's Go Scripting...

By Larry Wall on December 6, 2007 12:00 AM

I think, to mostpeople, scripting is a lot like obscenity. I can't define it, but I'll know itwhen I see it. Here are some common memes floating around:

    Simple language

    "Everything is a string"

    Rapid prototyping

    Glue language

    Process control

    Compact/concise

    Worse-is-better

    Domain specific

    "Batteries included"

...I don't seeany real center here, at least in terms of technology. If I had to pick onemetaphor, it'd be easy onramps. And a slow lane. Maybe even with some optionalfast lanes.

Easy Onramps

But basically,scripting is not a technical term. When we call something a scripting language,we're primarily making a linguistic and cultural judgment, not a technicaljudgment.

I see scriptingas one of the humanities. It's our linguistic roots showing through. Sospeaking of roots...

The Past

Suppose you wentback to Ada Lovelace and asked her the difference between a script and aprogram. She'd probably look at you funny, then say something like: Well, ascript is what you give the actors, but a program is what you give theaudience. That Ada was one sharp lady...

Since her time,we seem to have gotten a bit more confused about what we mean when we sayscripting. It confuses even me, and I'm supposed to be one of the experts.

So I'm afraidall I can do is give you my own worm's eye view of the past, the present, andthe future. Let me warn you that I am not without a few prejudices here andthere.

BASIC

Now, however itwas initially intended, I think BASIC turned out to be one of the first majorscripting languages, especially the extended version that DEC put onto itsminicomputers called BASIC/PLUS, which happily included recursive functionswith arguments. I started out as a BASIC programmer. Some people would say thatI'm permanently damaged. Some people are undoubtedly right.

But I'm not going to apologize for that. All language designers have theiroccasional idiosyncracies. I'm just better at it than most. :-)

RSTS BASIC/PLUS

Anyway, when Iwas a RSTS programmer on a PDP-11, I certainly treated BASIC as a scriptinglanguage, at least in terms of rapid prototyping and process control. I'm sureit warped my brain forever. Perl's statement modifiers are straight out ofBASIC/PLUS. It even had some cute sigils on the ends of its variables todistinguish string and integer from floating point.

But you could doextreme programming. In fact, I had a college buddy I did pair programmingwith. We took a compiler writing class together and studied all that fancystuff from the dragon book. Then of course the professor announced we would beimplementing our own language, called PL/0. After thinking about it a while, weannounced that we were going to do our project in BASIC. The professor lookedat us like were insane. Nobody else in the class was using BASIC. And you knowwhat? Nobody else in the class finished their compiler either. We not onlyfinished but added I/O extensions, and called it PL 0.5. That's rapidprototyping.

Unix?

I remember oneday our computer center got a letter from Bell Labs telling us that we couldget a tape of Unix V6 for cheap, only $100 because they were coming out shortlywith V7. We all looked at each other and said, Why would we ever want to usethis thing called Unix? We have RSTS.

JAM (no not that one)

My firstscripting language was written in BASIC. For my job in the computer center Iwrote a language that I called JAM, short for Jury-rigged All-purposeMeta-language. Story of my life...

JAM was an inside-outtext-processing language much like PHP, except that HTML hadn't been inventedyet. We mostly used it as a fancy macro processor for BASIC. Unlike PHP, it didnot have 3,000 functions in one namespace. We wouldn't have had the memory, forone thing.

LISP

For good or ill,when I went off to grad school, I studied linguistics, so the only computerlanguage I used there was LISP. It was my own personal McCarthy era.

Is LISP acandidate for a scripting language? While you can certainly write things rapidlyin it, I cannot in good conscience call LISP a scripting language. By policy,LISP has never really catered to mere mortals.

And, of course,mere mortals have never really forgiven LISP for not catering to them.

Pascal, Ada

Once I got intoindustry, I wrote a compiler in Pascal for a discrete event simulator, andslavered over the forthcoming Ada specs. As a linguist, I don't think of Ada asa big language. Now, English and Japanese, those are big languages. Ada is justa medium-sized language.

Unix, shell

After severalyears I finally became acquainted with Unix and its various scriptinglanguages. OK, to be more precise, BSD, and csh.

BSD, csh

Yeah, yeah, Iknow. More brain damage...

I also learned alittle C.

C

That's because alittle C is all there is. I'm still learning those libraries though.

shell + awk + sed + find + expr...

But thefrustrations of Unix shell programming led directly to the creation of Perl,which I don't really have time to tell. But essentially, I found that shellscripting was intrinsically limited by the fact that most of its verbs are notunder its control and hence largely inconsistent with each other. And the nounsare impoverished, restricted to strings and files, with who-knows-whattypology.

C xor shell

More destructivewas the mindset that it was a one-dimensional universe: you either programmedin C or you programmed in shell, because they're obviously at opposite ends ofthe One True Continuum. Perl came about when I realized that scripting did notalways have to viewed as the opposite of programming, but that a singlelanguage could be pretty good for both. That opened up a huge ecological niche.Many of you have seen my old clamshell diagram, with the two dimensions ofmanipulexity and whipuptitude.

Tcl

After Perl cameTcl, which in a sense is a purer scripting language than Perl. Perl justpretends that everything is a string when it's convenient, but Tcl reallybelieves that as a controlling metaphor. The string metaphor tends to have badperformance ramifications, but that's not why Tcl languished, I think. Therewere two reasons for that.

First, Tclstayed in the Unix mindset that controlling tools was the opposite of creatingtools, so they didn't optimize much. The fast parts can always be written in C,after all.

The secondreason was the lack of a decent extension mechanism, so you ended up withseparate executables for expect, incr-tcl, etc.

I must say,though, that I've always admired Tcl's delegational model of semantics. But itfell into the same trap as LISP by expecting everyone to use the One TrueSyntax. Speaking of the One True Syntax:

Python

After Tcl camePython, which in Guido's mind was inspired positively by ABC, but in the Pythoncommunity's mind was inspired negatively by Perl. I'm not terribly qualified totalk about Python however. I don't really know much about Python. I only stoleits object system for Perl 5. I have since repented.

Ruby

I'm much morequalified to talk about Ruby--that's because a great deal of Ruby's syntax isborrowed from Perl, layered over Smalltalk semantics. I've always viewed Rubyas a much closer competitor for Perls ecological niche, not just because of theborrowed ideas, but because both Perl and Ruby take their functionalprogramming support rather more seriously that Python does. On the other hand,I think Ruby kind of screwed up on its declaration syntax, among other things.

*sh

Meanwhile, theBourne shell was extended into the Korn shell and bash. I didn't have much todo with those either. Thankfully. I will say that the continued evolution ofthe shell shows just how crufty a language can get when you just keep adding onad hoc syntactic features.

PHP

We've also seenthe rise of PHP, which takes the worse-is-better approach to dazzling newdepths, as it were. By and large PHP seems to be making the same progression ofmistakes as early Perl did, only slower. The one thing it does better is packaging.And when I say packaging, I don't mean namespaces.

JavaScript

Then there'sJavaScript, a nice clean design. It has some issues, but in the long runJavaScript might actually turn out to be a decent platform for runningPerl 6 on. Pugs already has part of a backend for JavaScript, though sadlythat has suffered some bitrot in the last year. I think when the new JavaScriptengines come out we'll probably see renewed interest in a JavaScript backend.

Monad/PowerShell

I've looked abit at Microsoft's Monad, and I'm pleased to note that it has object pipes likePerl 6. I just hope they don't patent it.

Lua, AppleScript

There are otherscripting languages in wide use. Sadly, I must confess I never looked closelyat Lua or AppleScript, probably because I'm not a game designer with a Mac.

Actually, Isuspect it runs deeper than that, which brings us up to the present time.

The Present

When I look atthe present situation, what I see is the various scripting communities behavinga lot like neighboring tribes in the jungle, sometimes trading, sometimeswarring, but by and large just keeping out of each other's way in complacentisolation.

I tend to takean anthropological view of these things. Many of you here are Perl programmers,but some of you come from other programming tribes. And depending on yourtribal history, you might think of a string as a pointer to a byte array ifyou're a C programmer, or as a list if you're a functional programmer, or as anobject if you're a Java programmer. I view a string as a Text, with a capitalT.

Text

I read that wordfrom a postmodern perspective. Of course, the term Postmodern is itselfcontext-sensitive. Some folks think Postmodernism means little more than theEmpowerment of the Vulgar. Some folks think the same about Perl.

But I takePostmodernism to mean that a Text, whether spoken or written, is an act ofcommunication requiring intelligence on both ends, and sometimes in the middletoo. I don't want to talk to a stupid computer language. I want my computerlanguage to understand the strings I type.

Perl is apostmodern language, and a lot of conservative folks feel like Postmodernism isa rather liberal notion. So it's rather ironic that my views on Postmodernismwere primarily informed by studying linguistics and translation as taught bymissionaries, specifically, the Wycliffe Bible Translators. One of the thingsthey hammered home is that there's really no such thing as a primitive humanlanguage. By which they mean essentially that all human languages are Turingcomplete.

When you go outto so-called primitive tribes and analyze their languages, you find thatstructurally they're just about as complex as any other human language.Basically, you can say pretty much anything in any human language, if you workat it long enough. Human languages are Turing complete, as it were.

Human languagestherefore differ not so much in what you can say but in whatyou must say. In English, you are forced to differentiatesingular from plural. In Japanese, you don't have to distinguish singular fromplural, but you do have to pick a specific level of politeness, taking intoaccount not only your degree of respect for the person you're talking to, butalso your degree of respect for the person or thing you're talking about.

So languagesdiffer in what you're forced to say. Obviously, if your language forces you tosay something, you can't be concise in that particular dimension using yourlanguage. Which brings us back to scripting.

How many waysare there for different scripting languages to be concise?

How many recipesfor borscht are there in Russia?

Languagedesigners have many degrees of freedom. I'd like to point out just a few ofthem.

early binding / late binding

Binding in thiscontext is about exactly when you decide which routine you're going to call fora given routine name. In the early days of computing, most binding was donefairly early for efficiency reasons, either at compile time, or at the latest,at link time. You still tend to see this approach in statically typedlanguages. With languages like Smalltalk, however, we began to see a differenttrend, and these days most scripting languages are trending towards laterbinding. That's because scripting languages are trying to be dwimmy (Do What IMean), and the dwimmiest decision is usually a late decision because you thenhave more available semantic and even pragmatic context to work with. Otherwiseyou have to predict the future, which is hard.

So scriptinglanguages naturally tend to move toward an object-oriented point of view, wherethe binding doesn't happen 'til method dispatch time. You can still see thescars of conflict in languages like C++ and Java though. C++ makes the defaultmethod type non-virtual, so you have to say virtual explicitly to get latebinding. Java has the notion of final classes, which force calls to the classto be bound at compile time, essentially. I think both of those approaches arebig mistakes. Perl 6 will make different mistakes. In Perl 6 allmethods are virtual by default, and only the application as a whole can tellthe optimizer to finalize classes, presumably only after you know how all theclasses are going to be used by all the other modules in the program.

single dispatch / multiple dispatch

In a sense,multiple dispatch is a way to delay binding even longer. You not only have todelay binding 'til you know the type of the object, but you also have to knowthe types of all rest of the arguments before you can pick a routine to call.Python and Ruby always do single dispatch, while Dylan does multiple dispatch.Here is one dimension in which Perl 6forces the caller to beexplicit for clarity. I think it's an important distinction for the programmerto bear in mind, because single dispatch and multiple dispatch arephilosophically very different ideas, based on different metaphors.

Withsingle-dispatch languages, you are basically sending a message to an object,and the object decides what to do with that message. With multiple dispatchlanguages, however, there is no privileged object. All the objects involved inthe call have equal weight. So one way to look at multiple dispatch is that theobjects are completely passive. But if the objects aren't deciding how to bind,who is?

Well, it's sortof a democratic thing. All the routines of a given name get together and hold apolitical conference. (Well, not really, but this is how the metaphor works.)Each of the routines is a delegate to the convention. All the potentialcandidates put their names in the hat. Then all the routines vote on who thebest candidate is, and the next best, and the next best after that. Andeventually the routines themselves decide what the best routine to call is.

So basically,multiple dispatch is like democracy. It's the worst way to do late binding,except for all the others.

But I really dothink that's true, and likely to become truer as time goes on. I'm spending alot of time on this multiple dispatch issue because I think programming in thelarge is mutating away from the command-and-control model implicit in singledispatch. I think the field of computation as a whole is moving more toward thekinds of decisions that are better made by swarms of insects or schools offish, where no single individual is in control, but the swarm as a whole hasemergent behaviors that are somehow much smarter than any of the individualcomponents.

eager evaluation / lazy evaluation

Most languagesevaluate eagerly, including Perl 5. Some languages evaluate allexpressions as lazily as possible. Haskell is a good example of that. Itdoesn't compute anything until it is forced to. This has the advantage that youcan do lots of cool things with infinite lists without running out of memory.Well, at least until someone asks the program to calculate the whole list. Thenyou're pretty much hosed in any language, unless you have a real Turingmachine.

So anyway, in Perl 6 we're experimenting with a mixture of eager andlazy. Interestingly, the distinction maps very nicely onto Perl 5'sconcept of scalar context vs. list context. So in Perl 6, scalar contextis eager and list context is lazy. By default, of course. You can always forcea scalar to be lazy or a list to be eager if you like. But you can say thingslikefor 1..Inf as long asyour loop exits some other way a little bit before you run into infinity.

eager typology / lazy typology

Usually known asstatic vs. dynamic, but again there are various positions for the adjustmentknob. I rather like the gradual typing approach for a number of reasons.Efficiency is one reason. People usually think of strong typing as a reason,but the main reason to put types into Perl 6 turns out not to be strongtyping, but rather multiple dispatch. Remember our political conventionmetaphor? When the various candidates put their names in the hat, whatdistinguishes them? Well, each candidate has a political platform. The planksin those political platforms are the types of arguments they want to respondto. We all know politicians are only good at responding to the types ofarguments they want to have...

There's anotherway in which Perl 6 is slightly more lazy than Perl 5. We still havethe notion of contexts, but exactly when the contexts are decided has changed.In Perl 5, the compiler usually knows at compile time which arguments willbe in scalar context, and which arguments will be in list context. ButPerl 6 delays that decision until method binding time, which is conceptuallyat run time, not at compile time. This might seem like an odd thing to you, butit actually fixes a great number of things that are suboptimal in the design ofPerl 5. Prototypes, for instance. And the need for explicit references.And other annoying little things like that, many of which end up as frequentlyasked questions.

limited structures / rich structures

Awk, Lua, andPHP all limit their composite structures to associative arrays. That has bothpluses and minuses, but the fact that awk did it that way is one of the reasonsthat Perl does it differently, and differentiates ordered arrays from unorderedhashes. I just think about them differently, and I think a lot of other peopledo too.

symbolic / wordy

Arguably APL isalso a kind of scripting language, largely symbolic. At the other extreme wehave languages that eschew punctuation in favor of words, such as AppleScriptand COBOL, and to a lesser extent all the Algolish languages that use words toindicate blocks where the C-derived languages use curlies. I prefer a balancedapproach here, where symbols and identifiers are each doing what theyre bestat. I like it when most of the actual words are those chosen by the programmerto represent the problem at hand. I don't like to see words used for meresyntax. Such syntactic functors merely obscure the real words. That's one thingI learned when I switched from Pascal to C. Braces for blocks. It's just rightvisually.

Actually, thereare languages that do it even worse than COBOL. I remember one Pascal variantthat required your keywords to be capitalized so that they would stand out. No,no, no, no, no! You don't want your functors to stand out. It's shouting thewrong words: IF! foo THEN! bar ELSE! baz END! END! END! END!

Anyway, inPerl 6 we're raising the standard for where we use punctuation, and wherewe don't. We're getting rid of some of our punctuation that isn't reallypulling its weight, such as parentheses around conditional expressions, andmost of the punctuational variables. And we're making all the remainingpunctuation work harder. Each symbol has to justify its existence according toHuffman coding.

Oddly, there'sone spot where we're introducing new punctuation. After your sigil you can adda twigil, or secondary sigil. Just as a sigil tells you the basic structure ofan object, a twigil tells you that a particular variable has a weird scope.This is basically an idea stolen from Ruby, which uses sigils to indicate weirdscoping. But by hiding our twigils after our sigils, we get the best of bothworlds, plus an extensible twigil system for weird scopes we haven't thought ofyet.

We think aboutextensibility a lot. We think about languages we don't know how to think aboutyet. But leaving spaces in the grammar for new languages is kind of likereserving some of our land for national parks and national forests. Or like anarchaeologist not digging up half the archaeological site because we know ourdescendants will have even better analytical tools than we have.

Really designinga language for the future involves a great deal of humility. As with science,you have to assume that, over the long term, a great deal of what you think istrue will turn out not to be quite the case. On the other hand, if you don'tmake your best guess now, you're not really doing science either. Inretrospect, we know APL had too many strange symbols. But we wouldn't be assure about that if APL hadn't tried it first.

compile time / run time

Many dynamic languages can eval code at run time. Perl also takes it theother direction and runs a lot of code at compile time. This can get messy withoperational definitions. You don't want to be doing much file I/O in your BEGINblocks, forinstance. But that leads us to another distinction:

declarational / operational

Most scriptinglanguages are way over there on the operational side. I thought Perl 5 hadan oversimplified object system till I saw Lua. In Lua, an object is just ahash, and there's a bit of syntactic sugar to call a hash element if it happensto contain code. Thats all there is. They don't even have classes. Anythingresembling inheritance has to be handled by explicit delegation. That's achoice the designers of Lua made to keep the language very small and embeddable.For them, maybe it's the right choice.

Perl 5 has always been a bit more declarational than either Python orRuby. I've always felt strongly that implicit scoping was just asking fortrouble, and that scoped variable declarations should be very easy to recognizevisually. Thats why we have my. It's short because I knew we'd use it frequently. Huffman coding. Keepcommon things short, but not too short. In this case, 0 is too short.

Perl 6 has more different kinds of scopes, so we'll have moredeclarators like my and our. But appearances can be deceiving. While the language looks moredeclarative on the surface, we make most of the declarations operationallyhookable underneath to retain flexibility. When you declare the type of avariable, for instance, you're really just doing a kind of tie, in Perl 5terms. The main difference is that you're tying the implementation to thevariable at compile time rather than run time, which makes things moreefficient, or at least potentially optimizable.

immutable classes / mutable classes

Classes in Javaare closed, which is one of the reasons Java can run pretty fast. In contrast,Ruby's classes are open, which means you can add new things to them at anytime. Keeping that option open is perhaps one of the reasons Ruby runs so slow.But that flexibility is also why Ruby has Rails.

Perl 6 willhave an interesting mix of immutable generics and mutable classes here, andinteresting policies on who is allowed to close classes when. Classes are neverallowed to close or finalize themselves, for instance. Sorry, for some reason Ikeep talking about Perl 6. It could have something to do with the factthat we've had to think about all of these dimensions in designing Perl 6.

class-based / prototype-based

Here's another dimension that can open up to allow both approaches. Someof you may be familiar with classless languages like Self or JavaScript.Instead of classes, objects just clone from their ancestors or delegate toother objects. For many kinds of modeling, it's actually closer to the way thereal world works. Real organisms just copy their DNA when they reproduce. Theydon't have some DNA of their own, and an @ISA array telling you which parentobjects contain the rest of their DNA.

The meta-objectprotocol for Perl 6 defaults to class-based, but is flexible enough to setup prototype-based objects as well. Some of you have played around with Moose inPerl 5. Moose is essentially a prototype of Perl 6's object model. Ona semantic level, anyway. The syntax is a little different. Hopefully a littlemore natural in Perl 6.

passive data, global consistency / active data, local consistency

Your view of dataand control will vary with how functional or object-oriented your brain is.People just think differently. Some people think mathematically, in terms ofprovable universal truths. Functional programmers don't much care if they strewimplicit computation state throughout the stack and heap, as long as everything looks pureand free from side-effects.

Other peoplethink socially, in terms of cooperating entities that each have their own freewill. And it's pretty important to them that the state of the computation bestored with each individual object, not off in some heap of continuationssomewhere.

Of course, someof us can't make up our minds whether we'd rather emulate the logical SherlockHolmes or sociable Dr. Watson. Fortunately, scripting is not incompatible witheither of these approaches, because both approaches can be made moreapproachable to normal folk.

info hiding / scoping / attachment

And finally, ifyou're designing a computer language, there are a couple bazillion ways toencapsulate data. You have to decide which ones are important. What's the bestway to let the programmer achieve separation of concerns?

object / class / aspect / closure / module / template / trait

You can use anyof these various traditional encapsulation mechanisms.

transaction / reaction / dynamic scope

Or you canisolate information to various time-based domains.

process / thread / device / environment

You can attachinfo to various OS concepts.

screen / window / panel / menu / icon

You can hideinfo various places in your GUI. Yeah, yeah, I know, everything is an object.But some objects are more equal than others.

syntactic scope / semantic scope / pragmatic scope

Information can attach to various abstractions of your program, including,bizarrely, lexical scopes. Though if you think about it hard enough, yourealize lexical scopes are also a funny kind of dynamic scope, or recursionwouldn't work right. A state variable is actually more purely lexical than a my variable,because it's shared by all calls to that lexical scope. But even statevariables get cloned with closures. Only global variables can be truly lexical,as long as you refer to them only in a given lexical scope. Go figure.

So really, mostof our scopes are semantic scopes that happen to be attached to a particularsyntactic scope.

You may bewondering what I mean by a pragmatic scope. That's the scopeof what the user of the program is storing in their brain, or in some surrogatefor their brain, such as a game cartridge. In a sense, most of the web pagesout there on the Internet are part of the pragmatic scope. As is most of thedata in databases. The hallmark of the pragmatic scope is that you really don'tknow the lifetime of the container. It's just out there somewhere, and willeventually be collected by that Great Garbage Collector that collects allinformation that anyone forgets to remember. The Google cache can only last solong. Eventually we will forget the meaning of every URL. But we must notforget the principle of the URL. That leads us to our nextdegree of freedom.

use Lingua::Perligata;

If you allow alanguage to mutate its own grammar within a lexical scope, how do you keeptrack of that cleanly? Perl 5 discovered one really bad way to do it,namely source filters, but even so we ended up with Perl dialects such asPerligata and Klingon. What would it be like if we actually did it right?

Doing it rightinvolves treating the evolution of the language as a pragmatic scope, or as aset of pragmatic scopes. You have to be able to name your dialect, kind of likea URL, so there needs to be a universal root language, and ways of warping thatuniversal root language into whatever dialect you like. This is actually nearthe heart of the vision for Perl 6. We don't see Perl 6 as a singlelanguage, but as the root for a family of related languages. As a family, thereare shared cultural values that can be passed back and forth among sibling languagesas well as to the descendants.

I hope you'reall scared stiff by all these degrees of freedom. I'm sure there are otherdimensions that are even scarier.

But... I thinkits a manageable problem. I think its possible to still think of Perl 6 asa scripting language, with easy onramps.

And the reason Ithink its manageable is because, for each of these dimensions, it's not just abinary decision, but a knob that can be positioned at design time, compiletime, or even run time. For a given dimension X, different scripting languagesmake different choices, set the knob at different locations.

You can't even think about X!
There's only one way to do X!
There's more than one way to do X!
There are too many ways to do X!

You mayrecognize some slogans in here.

Curling Up

So I'm notsuggesting that all scripting languages have to take all these dimensions intoaccount, even if Perl 6 tries to. The scripting paradigm is not any one ofthese dimensions. According to various theories the universe may be laid out inten or twenty dimensions, but generally we get by with only about three and ahalf of those dimensions. The rest are said to be curled up. Maybe we live in ascripting universe.

Most of thescripting languages we call Perl 6 will have most of these dimensionscurled up most of the time. But unlike the real universe, where it takes hugemachines to uncurl these dimensions, we'll make the dimensions uncurl just bykeeping our declarations straight. Well, we'll try. And where that fails, we'llrely on the culture to keep things straight.

For example, that's exactly what happened already with Perl 5. Wehave the declarations, usestrict; use warnings;. But it's the culture that decided toenforce the use of them. So much so that we've decided that they should be thedefault for most of Perl 6. It was one of those decisions by the hive. Inthis case the swarm turned out to be smarter than the language designer. Andthat's as it should be.

The Future

Well, so what'sthe future of scripting?

In my completely unbiased opinion, that would be Perl 6. :-)

Seriouslythough, it's always safe to predict that the ecological landscape will end upwith many small languages and a few dominant ones. Some languages likeAppleScript have particular ecological niches and are unlikely to grow out ofthem. Other languages get used outside their original niche. There will alwaysbe the generalists, like crows and mockingbirds, and the specialists, like penguinsand dodos. (Well, maybe not always the dodos...)

Among the generalists, the conventional wisdom is that the worse-is-betterapproach is more adaptive. Personally, I get a little tired of the argument: Myworse-is-better is better than your worse-is-better because I'm better at beingworser! Is it really true that the worse-is-better approach always wins? WithPerl 6 we're trying to sneak one better-is-better cycle in there and hopeto come out ahead before reverting to the tried and true worse-is-better approach.Whether that works, only time will tell.

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章