Programming is Hard, Let's Go Scripting...
by Larry Wall
|
Pages: 1, 2, 3
compile time / run time
Many dynamic languages can eval code at run time. Perl also takes it the other direction and runs a lot of code at compile time. This can get messy with operational definitions. You don't want to be doing much file I/O in your BEGIN blocks, for instance. But that leads us to another distinction:
declarational / operational
Most scripting languages are way over there on the operational side. I thought Perl 5 had an oversimplified object system till I saw Lua. In Lua, an object is just a hash, and there's a bit of syntactic sugar to call a hash element if it happens to contain code. Thats all there is. They don't even have classes. Anything resembling inheritance has to be handled by explicit delegation. That's a choice 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 or Ruby. I've always felt strongly that implicit scoping was just asking for trouble, and that scoped variable declarations should be very easy to recognize visually. Thats why we have my. It's short because I knew we'd use it frequently. Huffman coding. Keep common 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 more declarators like my and our. But appearances can be deceiving. While the language looks more declarative on the surface, we make most of the declarations operationally hookable underneath to retain flexibility. When you declare the type of a variable, for instance, you're really just doing a kind of tie, in Perl 5 terms. The main difference is that you're tying the implementation to the variable at compile time rather than run time, which makes things more efficient, or at least potentially optimizable.
immutable classes / mutable classes
Classes in Java are 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 any time. 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 will have an interesting mix of immutable generics and mutable classes here, and interesting policies on who is allowed to close classes when. Classes are never allowed to close or finalize themselves, for instance. Sorry, for some reason I keep talking about Perl 6. It could have something to do with the fact that 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. Some of you may be familiar with classless languages like Self or JavaScript. Instead of classes, objects just clone from their ancestors or delegate to other objects. For many kinds of modeling, it's actually closer to the way the real world works. Real organisms just copy their DNA when they reproduce. They don't have some DNA of their own, and an @ISA array telling you which parent objects contain the rest of their DNA.
The meta-object protocol for Perl 6 defaults to class-based, but is flexible enough to set up prototype-based objects as well. Some of you have played around with Moose in Perl 5. Moose is essentially a prototype of Perl 6's object model. On a semantic level, anyway. The syntax is a little different. Hopefully a little more natural in Perl 6.
passive data, global consistency / active data, local consistency
Your view of data and control will vary with how functional or object-oriented your brain is. People just think differently. Some people think mathematically, in terms of provable universal truths. Functional programmers don't much care if they strew implicit computation state throughout the stack and heap, as long as everything looks pure and free from side-effects.
Other people think socially, in terms of cooperating entities that each have their own free will. And it's pretty important to them that the state of the computation be stored with each individual object, not off in some heap of continuations somewhere.
Of course, some of us can't make up our minds whether we'd rather emulate the logical Sherlock Holmes or sociable Dr. Watson. Fortunately, scripting is not incompatible with either of these approaches, because both approaches can be made more approachable to normal folk.
info hiding / scoping / attachment
And finally, if you're designing a computer language, there are a couple bazillion ways to encapsulate data. You have to decide which ones are important. What's the best way to let the programmer achieve separation of concerns?
object / class / aspect / closure / module / template / trait
You can use any of these various traditional encapsulation mechanisms.
transaction / reaction / dynamic scope
Or you can isolate information to various time-based domains.
process / thread / device / environment
You can attach info to various OS concepts.
screen / window / panel / menu / icon
You can hide info 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, you realize lexical scopes are also a funny kind of dynamic scope, or recursion wouldn'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 state variables 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, most of our scopes are semantic scopes that happen to be attached to a particular syntactic scope.
You may be wondering what I mean by a pragmatic scope. That's the scope of what the user of the program is storing in their brain, or in some surrogate for their brain, such as a game cartridge. In a sense, most of the web pages out there on the Internet are part of the pragmatic scope. As is most of the data in databases. The hallmark of the pragmatic scope is that you really don't know the lifetime of the container. It's just out there somewhere, and will eventually be collected by that Great Garbage Collector that collects all information that anyone forgets to remember. The Google cache can only last so long. Eventually we will forget the meaning of every URL. But we must not forget the principle of the URL. That leads us to our next degree of freedom.
use Lingua::Perligata;
If you allow a language to mutate its own grammar within a lexical scope, how do you keep track 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 as Perligata and Klingon. What would it be like if we actually did it right?
Doing it right involves treating the evolution of the language as a pragmatic scope, or as a set of pragmatic scopes. You have to be able to name your dialect, kind of like a URL, so there needs to be a universal root language, and ways of warping that universal root language into whatever dialect you like. This is actually near the heart of the vision for Perl 6. We don't see Perl 6 as a single language, but as the root for a family of related languages. As a family, there are shared cultural values that can be passed back and forth among sibling languages as well as to the descendants.
I hope you're all scared stiff by all these degrees of freedom. I'm sure there are other dimensions that are even scarier.
But... I think its a manageable problem. I think its possible to still think of Perl 6 as a scripting language, with easy onramps.
And the reason I think its manageable is because, for each of these dimensions, it's not just a binary decision, but a knob that can be positioned at design time, compile time, or even run time. For a given dimension X, different scripting languages make 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 may recognize some slogans in here.
Curling Up
So I'm not suggesting that all scripting languages have to take all these dimensions into account, even if Perl 6 tries to. The scripting paradigm is not any one of these dimensions. According to various theories the universe may be laid out in ten or twenty dimensions, but generally we get by with only about three and a half of those dimensions. The rest are said to be curled up. Maybe we live in a scripting universe.
Most of the scripting languages we call Perl 6 will have most of these dimensions curled up most of the time. But unlike the real universe, where it takes huge machines to uncurl these dimensions, we'll make the dimensions uncurl just by keeping our declarations straight. Well, we'll try. And where that fails, we'll rely on the culture to keep things straight.
For example, that's exactly what happened already with Perl 5. We have the declarations, use strict; use warnings;. But it's the culture that decided to enforce the use of them. So much so that we've decided that they should be the default for most of Perl 6. It was one of those decisions by the hive. In this case the swarm turned out to be smarter than the language designer. And that's as it should be.
The Future
Well, so what's the future of scripting?
In my completely unbiased opinion, that would be Perl 6. :-)
Seriously though, it's always safe to predict that the ecological landscape will end up with many small languages and a few dominant ones. Some languages like AppleScript have particular ecological niches and are unlikely to grow out of them. Other languages get used outside their original niche. There will always be the generalists, like crows and mockingbirds, and the specialists, like penguins and dodos. (Well, maybe not always the dodos...)
Among the generalists, the conventional wisdom is that the worse-is-better approach is more adaptive. Personally, I get a little tired of the argument: My worse-is-better is better than your worse-is-better because I'm better at being worser! Is it really true that the worse-is-better approach always wins? With Perl 6 we're trying to sneak one better-is-better cycle in there and hope to come out ahead before reverting to the tried and true worse-is-better approach. Whether that works, only time will tell.
Showing messages 1 through 8 of 8.
- language complexity
2007-12-10 12:26:05 suitti [Reply]
About a million years ago, i recall attempting to teach someone BASIC. They'd written a few short bits, and wanted to know how to use a computed GOTO. I coached that ON GOTO wasn't used that much, but that knowing what problems it solved was a good idea. One could use such a thing for a case statement, but an if-else chain can do the same. So, what is it for? The documentation only talked about what it does.
So, Perl 6 has a couple dozen conceptual dimensions. And each of these dimensions is an order of magnitude harder to grok than ON GOTO. And the fact that these elements appear in other languages does not help the newbie. The barrier to entry can look impassable. Worse, if the newbie's task in life is maintenance, they may find that they have to learn the entire language, not just the bits that solve problems they might have. It's hard to imagine how they'll cope. But they might.
Worse still, these language features are, IMO, oversold and misrepresented, more often than not. This trend might have started with Lisp, which predates FORTRAN. Lisp may have started out being good at lists, but why were people who were interested in AI interested in lists? AFAICT, they weren't, exactly, interested in lists.
A trend in languages is to take a new language feature and make it mandatory. Take object orientedness. For example, "Hello, World", in Java must create a class with a method. Perl doesn't suffer here. So maybe there's hope for Perl 6. Perhaps the complexity can be addressed with documentation. It is hard to imagine. Perl 5, for many, is a copy and paste language already. Too hard to actually write, novice programmers have a list of idiom snippets and paste them into their new scripts and then edit. This seems due to terseness and the large number of overall language concepts.
I've done quite a bit of Perl, but have resisted investigating Perl 6, despite a recent quest to check out languages. I've been quite happy with Perl 5. A recent 750 line 'script' wrestles a 6 and 7 (it's dynamic) dimensional hash to the ground. So dense, it's probably unmaintainable, but flexible enough it might not need it. It would have been thousands of lines of Java. I don't think of it as a script.
I should note that i neither like nor dislike Perl - it's a force of nature, like Gravity. But i like C, and dislike Java. That's probably because i like computers - the ultimate obsequious servants, and C is closer to them.
My quest of late, has been for a language with speed and a small footprint. Half gigabyte JVMs make me tired. I thought maybe LISP might fit in under 100 KB, since it's origin is in the 50's, and the 'giga' prefix hadn't been invented. But, like Perl, it takes a factor of 500 hit in performance compared with C. Benchmarks lie, though that's another topic*. And even C has given into bloatware. Some Linux systems don't ship with a static version of libc, so a simple do loop takes 1.5 MB of virtual memory. Shared libraries can't be pruned, so you get everything, even if you use nothing. Maybe the answer is Forth, with C as a fallback.
Bloat has taken on a life of it's own. In 1995, i had a 486 laptop with 16 MB RAM and 170 MB disk. It had Linux with X Windows, Perl, gcc, emacs, a web browser, apache, and postgress loaded and 70 MB of free disk, despite 16 MB of swap. That let me write database backed web apps. Now, i have a shirt pocket sized device with 64 MB RAM, and 2 GB of, uhm, file store, running Linux. But less RAM is free, and apps are bigger, so i'm not there yet. It's currently missing a database and a web server.
One benchmark for a language is to learn it enough to write some stuff in it, wait ten years, and see if it still makes sense without undo effort. BASIC passes this test. Lisp and APL and Forth do not. Oddly, C seems to, though to be fair, there has been no ten year gap. I've had a five year break with Perl, and it's borderline. Scripts stay readable, but the skill to write disappears. YMMV.
*Despite benchmarks of longer running Perl apps being up to 1000 times slower than C on the same machine, web page apps tend to be less than ten times slower, even without compiled Perl, modperl, or other tricks, despite Perl's compile-on-the-fly startup overhead. So these simple benchmarks lead one to incorrect conclusions.
- I give up, Perl 6 it is
2007-12-07 22:31:26 tuomoks [Reply]
How could I not after this "In my completely unbiased opinion, that would be Perl 6". Very well written and a funny "unbiased" opinion. I'm not a Perl person but this almost convinces me to come one. My first program was 40 years and 5 months ago and my experience of languages is much same except I wouldn't call Perl syntax friendly (as APL or Lisp, heh!) Give me Algol type syntax (definition fits to one page, Burroughs wrote an operating system with that) combined with Lisp (how many languages can bootstrap them self?) and I'm happy. Not millions of API's, please, I have to use xxx number of languages every day and it is really a pain! Just common methods. Dreaming. This article is fun and IMHO should be required reading not matter what language you use.
- There we go!
2007-12-07 13:19:50 vergil66 [Reply]
Thanks Rachel! Now I'm reading the rest.
Peace,
Chris
- Can't read beyond Page 1
2007-12-07 10:53:29 vergil66 [Reply]
For some reason, I am unable to view pages 2 and 3 (and I've tried with 3 different browsers).
Just a thought.
Peace,
Chris- Can't read beyond Page 1
2007-12-07 16:41:02 rgbingham [Reply]
...same here... Pages 2 and 3 still aren't appearing... --Ray
- Can't read beyond Page 1
2007-12-08 06:06:26 rachel.j [Reply]
Ray,
Give it another try, it should be working now.
If you're still having the same problem, please email help@oreillynet.com
Thanks,
Rachel
Web Producer, Perl.com
- Can't read beyond Page 1
- Can't read beyond Page 1
- Tcl has evolved
2007-12-07 05:39:16 mjanssen [Reply]
Regarding your remarks about Tcl, Tcl has evolved considerably. Two address the two specific points you mention:
> First, Tcl stayed in the Unix mindset that controlling tools was the opposite of creating tools, so they didn't optimize much. The fast parts can always be written in C, after all.
Tcl uses internal representations for strings, so for instance if you use a string as a list, Tcl will use the internal list representation. This greatly improves performance. See http://wiki.tcl.tk/shimmering for a more detailed explanation.
> The second reason was the lack of a decent extension mechanism, so you ended up with separate executables for expect, incr-tcl, etc.
The current Tcl versions are very easy to extend; Incr-Tcl and Expect are extensions that can be loaded in the same interpreter now. One could even argue that the current Tcl extension mechanism is superior to many other scripting languages, because:
1) The C-API is very straightforward. Wrapping a C library is very easy.
2) Tcl uses a stubs mechanism which allows extensions to be loaded into different interpreter versions. For instance most extensions that were built for 8.4, will work without any recompilation in 8.5
- Lua tables are both
2007-12-07 04:21:17 Bogus [Reply]
Mr. Wall is as funny and entertaining as always, but I think he does have one thing wrong: Lua tables are not only associative arrays, but also indexed arrays (not only by definition but also implementation).
This way, Lua tables are easily the richtest structure I could think of. But maybe that's just me. ;-)


