Archive | Education RSS feed for this section

Learn to program in 20+ easy steps

22 Jul

As it stands, my comprehensive Introduction to Programming series is organized into parts as follows:

1) A first language

To program, you must learn a programming language, so we start by introducing a language called Pigeon. Pigeon is a language created expressly for students in that it features as simple a grammar as I believe possible while still reflecting the concepts found in “real” languages. Learning Pigeon first should make later tackling your first real language much easier.

2) Numbers

Computers are deeply mysterious until you understand how information is represented as bits. We start with numbers because their bit representation is used as a basis for representing other kinds of data.

3) Text

Text is represented using what are called character sets. The most commonly used character sets are ASCII and Unicode.

4) Images

In this part, we briefly discuss some elementary concepts of computer graphics.

5) Hardware and operating systems

Here we cover essential concepts in computer hardware and operating systems.

6) Languages and tools

There is a wide array of programming languages in existence. We’ll survey the most popular ones and discuss their major differences. We’ll also discuss the associated tools, e.g. debuggers.

7) The Javascript language

The popular language Javascript (not to be confused with Java, another popular language) is very close semantically to Pigeon, so it’s a natural choice for our first real language.

8) The Internet and the web

Here we’ll discuss the basic structure of the Internet and the protocols on which it runs.

10) Structured data formats

Structured data is data in which individual pieces of data (numbers, pieces of text, etc.) are related together in an organized way. A person, for instance, can be represented as structured data: a name (text), an age (number), an address (text), etc. We have standard formats for such data such as XML (Extensible Markup Language) and JSON (Javascript Object Notation), among others.

11) HTML and CSS

Webpages are documents comprised primarily of HTML (Hypertext Markup Language) and CSS (Cascading Style Sheets). We’ll also cover the role of Javascript in webpages.

12) The Unix command line shell

Before graphical user interfaces, computer users interacted with the computer using a command line shell—basically, an interactive programming language in which each command the user types is immediately executed. Today, shells are still powerful tools used by programmers and system administrators. In this unit, we’ll focus on the shell language used most commonly in Unix systems, BASH (the Bourne Again Shell). We’ll also discuss the command-line programs commonly available on Unix systems and discuss how these programs can be tied together through the shell.

13) Assembly language

Assembly language represents the lowest level of programming. Here we’ll cover assembly language for x86 processors using the NASM assembler.

14) The C language

The C programming language is one of the oldest and most influential languages still in use today. Unlike most other languages (including Pigeon and Javascript), C gives programmers a fine degree of control over the hardware, making it suitable for writing systems software (such as operating systems, like the Linux kernel) and for programs requiring high performance, such as the latest computer games.

15) Data structures and algorithms

There are only so many fundamental ways of organizing data. We’ll discuss these data structures and the algorithms associated with them.

16) Object-oriented programming

Object-oriented programming is a style of programming in which the programmer, rather than focusing on action,  focuses on establishing types of data and the actions associated with those types. This style is strongly encouraged in a number of so-called “object-oriented languages”, including Java.

17) The Java language

Since the late 1990′s, Java has been the most commonly used programming language. Java’s success has spawned an imitator from Microsoft called C# (“C sharp”), which differs in many details but is fundamentally similar. We cover Java instead of C# mainly because Java is somewhat simpler and still more popular.

18) Encryption, security, and compression

We’ll discuss the basics of encryption, security, and compression, which aren’t nearly as arcane as you might imagine.

19) Graphical interfaces

To write a program with a GUI (graphical user interface), a programmer uses a library called a GUI toolkit. We’ll focus on one such toolkit for Java called Swing.

20) Version control

When we write code, it’s very nice to be able to keep track of all of our changes such that we can always go back to an earlier version when we mess something up. It’s also really important to coordinate our changes with others working on the same code. For these reasons, programmers use programs called version control systems to manage their code. We’ll focus on two popular such programs, Subversion (abbreviated as “svn”) and Git.

21) Databases

A database is a specialized program for storing large amounts of data in a way that can be searched and retrieved efficiently. Databases are used everywhere: for instance, a popular website like Amazon.com uses databases to store product and customer information. The most commonly used databases are relational databases, meaning they structure data in the style of the relational model. The programs we write typically communicate with a relational database using a query language called SQL (pronounced “sequel”, Structured Query Language).

22) Regular expressions

Regular expressions (sometimes abbreviated as “regex”) are a sophisticated tool for finding patterns of characters in text. For instance, using a regular expression, I could easily remove from a text all instances of the word “curry” following the word “lemon”.

23) The Clojure language

Many regard Lisp as the most elegant of all languages, and Clojure is a particularly elegant recent variant of Lisp. Clojure gives us an opportunity to introduce functional programming, a style of programming in which we avoid “state change” as much as possible.

24) Automating the build process

The whole process of translating source code and data files into a working program is called the build process. In most software projects, we end up building the project many times over as we develop the code, fix bugs, and change features, so it makes sense that we automate this whole process as much as possible. In this part, we’ll discuss popular build tools, such as the Unix make program.

A beginner’s first programming language

27 May

I’ve finally put together and posted the video of part 1 of my introduction to programming. This first part presents a simple programming language to users in about 70 minutes.

UPDATE: I’ve also now added the second part, which covers representing numbers as bits.

The remaining eight or so parts will have to wait until I devise a better process for turning my slides and narration into video.

Clojure introduction video; Pigeon on hiatus

19 Apr

I’ve created an hour long introduction video to Clojure, a new dialect of Lisp.

I’ve also decided to leave unfinished my implementation of Pigeon, my pedagogic programming language, even though it would take a trivial amount of work to complete. I now think that it’s not really important for students to actually run Pigeon code; in fact, I think it best to discourage students from writing anything beyond a trivial amount of code in Pigeon lest they waste time rather than just moving on to later material.

Instead, my focus now is on creating a course of videos for total newbs to programming, totaling about 10 hours and running in this sequence:

  • A first language (a run through of Pigeon)
  • Numbers (how numbers are represented as bits)
  • Text and images (how they are represented as bits)
  • The system (hardware and OS basics)
  • Language and tools survey
  • Javascript (sans browser)
  • The internet and the web
  • HTML / CSS / Javascript (in browser)
  • The command line and Unix environment
  • C
  • Data structures and algorithms
  • OOP
  • Java
  • Encryption, security, and compression
  • GUI Toolkits (Swing?)
  • Version control
  • Databases

I’m processing the audio and video for the first two, but that leaves a lot of work as I only have sketches of the remaining parts.

Technical writing is hard

16 Jun

Having spent a lot of time in the last 3 years writing programming education material, I recognize just about everything said here. (The section “Writing clearly” is the interesting one.)

Look, ma, no lesson plan

21 May

Just about everything I described in my talk about what goes wrong in education goes wrong at nearly every step in this 10-minute video. I don’t mean to pick on this guy, but he’s the top Google video result for “python tutorial”, and that makes me sad. Sure, sure, I should forgive a high school student who is very likely just passing on his own miseducation, but his video makes a useful example of how tutorial-based programming education so commonly goes so very wrong.

Video of talk on Pigeon

18 May

Last month at LugRadio Live USA 2008 in San Francisco, I gave a talk discussing programming education and Pigeon, my learner’s programming language. Videos of all the talks at LugRadio Live are going up. Below is my talk, which you can also download. (I occasionally mumble a few key words. Sorry.)

The current status of Pigeon is that I still haven’t bothered to put the finishing touches on it for it to be actually usable, as I’m currently working on the material for students to learn Python after learning Pigeon. Until I give learners some plausible place to go after Pigeon, I figure I can put off finishing up Pigeon itself.

if !johnny.canRead() then…

4 Feb

The state of educational programming languages.

Ideally, a proper programming education would start with a thorough discussion of how data is represented as bits, followed by a brief tour of encryption, compression, information theory, data structures, search/sort algorithms, and machine architecture. Unfortunately, students are just too impatient to start their education properly, having approached the topic of computing with the desire to get their computers to do something, preferably something neat, preferably something now. This is where educational languages should come in: students should be able to learn a simplified language in a week or two of lessons with no prerequisite material, thereby satisfying their curiosity of what programming is at least like. Learning a quick-and-painless language should make students more receptive to covering some of the theoretical basis of computing while also preparing students for learning their first ‘real’ language, whether it be C, Java, Python, Scheme, Javascript, Ruby, Haskell, whatever.

In the before time…

Today’s learners of programming typically start out with Javascript, PHP, Python, Ruby, Java, C, C++, or C#. Things used to be different. For much of the 80′s and 90′s, newbies to programming were directed to languages typically thought of as learner’s languages, such as BASIC and Pascal, though these languages weren’t necessarily designed explicitly for education. Why did languages like these fall out of favor as educational tools? Most likely for the same reason they fell out of general use: they simply got old and out of date. Practicing programmers begin to look upon superseded languages like they do old code—as distracting, bothersome clutter. In turn, the neophytes take their cues from practicing programmers and insist they be taught a “real” language, and in the end, it’s just very hard for a language to gain and maintain wide adoption as an educational tool when no one wants to do any real programming in it.

While some may mourn BASIC and Pascal, I think people’s estimation of these languages is blinded by nostalgia. Pascal, in particular, overstayed its welcome in the classroom. By the mid 90′s, you might as well have taught C in place of Pascal, for C had sufficiently matured that it was essentially Pascal with pointers, different syntax, and no silly distinction between “procedures” and functions. Moreover, by 2000, the only* easily available implementation of Pascal for students to run on their own computers was (and is) Free Pascal, which actually supports a much changed dialect of Pascal, the result of cross-pollination with Delphi. The added complexity was bad enough, but then the Pascal text books simply didn’t keep up, thereby compounding Pascal’s fate: if new programmers don’t learn the Pascal in actual use, they won’t continue to use Pascal once they’ve learned it, leaving the language stuck in a death spiral.

(*There are actually Pascal implementations other than Free Pascal still available, but they too all significantly diverge from the classic Pascal of classrooms.)

BASIC suffered from an even worse fracturing problem and was eventually wholly overtaken by Visual Basic, which came to be seen as the modern BASIC even though it bore only superficial resemblance to the BASIC of 1980′s nostalgia. Visual Basic saw decent up take in the classroom, but as Microsoft took VB from 3.0 to 6.0, the language got more and more complex until, finally, today’s VB.NET is an almost entirely pointless syntactical variant of C#, a language just as complex as Java and C++.

What now?

Among the languages in use today, the best candidates for starter languages are the dynamic languages: Javascript, PHP, Ruby, and Python. Javascript and PHP, however, can be quickly discounted:

  1. Both Javascript and PHP lack a real read-eval-print interactive prompt.
  2. Non-programmers are most familiar with programs as things which they install and run on their machine, and so they’re going to feel something is missing if they can’t see how the language you’re teaching them is used to write such programs. Unfortunately, Javascript is stuck in the browser. Even if you teach Rhino, you’ll still have to tell neophytes a very strange story they likely won’t understand about how their Javascript program is executed and how this qualifies as general-purpose programming. Similarly, PHP is so heavily skewed towards its niche of server programming, it’s basically useless for client-side programming. So, with either Javascript or PHP, the instructor must make a Solomonic decision between leaving students in the dark about how their programs run or burdening and distracting students with a confusing back story.

So it comes down to Ruby and Python. Many will say the choice between the two is just a matter of taste, but I feel Ruby’s latent Perl-isms makes Python obviously better suited for neophytes. However, despite Python’s exemplary cleanliness, it’s still a quite complicated thing from the neophyte’s perspective. There’s a reason O’Reilly’s Learning Python is 746 pages long, and I just don’t think learners should be confronted in any way with subject matter like:

  • multiple inheritance
  • ‘bound’ vs. ‘unbound’ methods
  • old vs. “new” classes
  • functions within functions
  • list comprehensions
  • generators
  • packages
  • operator overloading
  • exception handling
  • creating custom iterators
  • internal dictionaries
  • a complicated hierarchy of scope with (limited) closure

Of course any sensible introductory Python course will hold off on these topics or avoid them altogether, but simply trying to ignore features of a language has costs, as the complexities and corner cases of a system have a way of intruding into the more pristine areas. For one thing, a student might accidentally write syntax which the compiler interprets as a (successful or unsuccessful) attempt to use a feature the student isn’t even aware exists; the result is mysteriously misbehaving code or a mysterious error message from the compiler. Perhaps worse, learners of a language will not be shielded from features they don’t understand when using their most important learning resource, the internet. Lastly, while Python is certainly a one-way-to-do-it language in comparison to Perl, it still offers conveniences for expert users, conveniences that will only paralyze learners with distracting stylistic decisions.

So perhaps we’d do better starting learners with a language explicitly designed for education. Yes, I did start by saying that the now-dead learner’s languages died because no one wanted to do any actual programming in them, but the main problem there was that Pascal and BASIC grew into complicated languages: they didn’t start life as explicitly learners-only languages and so ended up stuck in a no-man’s land between ‘two-week intro to programming’ and ‘full application-programming tool’. However, there still remains the problem of learners wanting to bypass learning a tool they’re going to immediately drop, so an educational language has a tricky balancing act to perform: the language should be simple enough to be fully learned in one or two lessons so that students don’t complain about learning “all this stuff” they aren’t going to use…but not so simple that the language isn’t enough like a real language to help students understand their first real language…but not too much like a real language that anyone would want to actually use the thing for real work.

Dark horses

Outside the mainstream, we have more educational language options. The most notable among them are:

  • Squeak (Smalltalk)
  • Scheme
  • Haskell
  • Alice
  • Scratch
  • Logo
  • Phogrom

And here’s what’s wrong with these languages:

  • Squeak, Scheme, and Haskell are real languages used by real programmers for real work. This is bad. Real means complex. Annoyingly complex in annoying ways. No matter how elegant in conception these languages may be at their core, their corners lurk with ugly realities, and you can’t assume that learners can’t see the corners or can just ignore them. For the learner, more corner cases means more possibilities to consider, more mental dead ends, more detritus to sift through to establish a clear picture. Sure, you could teach a relatively clean subset of Java, but the subset you teach will be scattered here and there in the 1200-page Java book your student picks up. Sure, you could teach Haskell while ignoring its convoluted syntactical conveniences, but the compiler’s warning messages won’t be so friendly to your student. Sure, you could stick to just one dialect of Scheme, but Dr. Scheme will confuse your student with a list of umpteen different dialects from which to choose. For learners, these 1200-page books, cryptic error messages, and fractured sets of dialects are frightening and discouraging.
  • Squeak has a problematic relation with the operating system: Smalltalk has never reconciled itself to the OS, stubbornly refusing to let the programmer create programs that take advantage of the OS’s already existing mechanisms for interfacing with users: the filesystem, the console, and (proper) windowed applications. Whatever the merits of this kind of programming, like with Javascript, Smalltalk presents a very confusing situation to learners, most of whom are hoping one day to write Doom 8; Doom 8 is not going to be written in Smalltalk, and even the greenest newbie programmer will be able to smell that about Smalltalk. Furthermore, I believe that a learner’s language should partly disregard files and entirely disregard consoles and GUI’s; Smalltalk does that, but it does so by replacing those things with its own complications, complications which end up as just more stuff to sift through in the documentation (see above).
  • Alice and Scratch attempt to sidestep the syntax issue in a novel manner: rather than using text for code, the Alice and Scratch editors have users drag code fragments and fit them together like puzzle pieces: the pieces only fit together in syntactically proper ways, so syntax errors aren’t possible. I actually think this might be a great idea for training students in the syntax and semantics of real languages, such as Java. However, this does mean that the Alice and Scratch dev environments feature a lot more buttons than they otherwise would. More importantly, if these languages’ syntaxes were simple enough in the first place, the benefit of drag-and-drop editing would be negligible.
  • Alice, Scratch, and Phogrom all suffer to one degree or another from the “naturalistic language fallacy“: by attempting to have their code read like English, they end up greatly complicating their languages and obscuring the underlying formality, thereby failing in an important regard to prep students for real languages. There’s a reason most English-speakers struggle to learn English grammar: it’s an awkward attempt to fit formal rules on a complex, organic system. Doing the opposite—massaging a formal system into English—doesn’t clarify anything, either. (The biggest offender in terms of naturalism is actually AppleScript, a language some misguidedly hold up as appropriate for learners. Like Dylan, AppleScript, is an example of Apple favoring apparent simplicity over actual simplicity; such bargains are sometimes worth it, and more often than not Apple finds the right balance, but the result with AppleScript is disastrous.)
  • Explicitly educational languages present themselves as intertwined to a particular API: Logo is the language in which you do turtle graphics; Alice, Scratch, and Phogrom are languages in which you do simple 3D- or sprite-based graphics and sound. Simple graphics-oriented API’s are a great idea, especially for teaching programming to younger students, yet there’s something wrong when the API is presented as indistinct from the language proper. In real languages, everything useful aside from basic arithmetic and logic is punted into libraries, and this is how it should be. First, multi-module programming brings with it the essential concept of namespaces. Second, without the barrier between core and domain-specific functionality, the distinction gets blurred in students’ minds.

Here there be dragons

Some topics should simply be avoided in a learner’s first exposure to programming, whatever the language. These topics include:

1) Inheritance and other static-y object-oriented features

Java and C++ support OOP the way they do for the sake of compile-time checks and efficiency (relative to languages with dynamic object systems, at least). These features introduce a plethora of rules in those languages, the sum complexity of which distract from the essential ideas in OOP: encapsulation, polymorphism, and inheritance. In a dynamic language, these ideas can be conveyed by convention using regular functions and dictionaries: plain functions are used as constructors and methods; dictionaries are used as the objects; methods take the object as their first parameter; and constructors return a dictionary with the right instance and method members. For example, a method call ends up looking like:

obj.foo(obj, 3)  // call the foo method of obj with an argument 3

This may be more verbose, but it’s explicitly constructed out of already existing mechanisms. Inheritance relationships would be ‘faked’ by simply giving one type all the same methods as another, e.g. A is a subtype of B because it has all the right fields and methods. Duck typing, essentially. A student introduced to OOP as a set of conventions rather than new language mechanisms has a better chance of seeing the point of the whole thing and so is less likely to fall into common newbie traps, such as using inheritance for the sake of using inheritance.

2) Shells

Shells seem to be problematic in programming education. For one thing, every shell tutorial I’ve ever seen outright fails to make clear the distinction between shell code and program invocations in the code. For example:

ls -a > foo

While “> foo” is part of Bash syntax, Bash doesn’t see “ls -a” as anything but a command it doesn’t recognize, so it looks for a program named “ls” in its search path, and it loads and executes ls, passing the string “-a” as the argument fed to the char* args parameter of main() of the ls process.

Got that? Well, if you don’t understand this, you don’t understand the first thing about shells. But it’s REALLY FREAKING HARD to start learners off by explaining all this. So we don’t explain it. Rather than really teaching Bash or other shells, we just give students a few example shell commands, wave our hands, and trust that students will eventually figure out what’s really going on. Few students catch on quickly, and many never do, including some that go on to program professionally.

The solution to this situation is to formally cover shell languages as topics in their own right rather than as incidental to instructing students in how to use a compiler. At the very least, then, shells should not be introduced at all until it’s time to give them proper treatment.

(Not only are shells conceptually tricky to explain, the complexity of Bash syntax distracts learners from the essential concepts. The long term solution is to replace Bash as the default shell with something with a proper expression-based syntax—something like Python or Ruby, perhaps—rather than a command-based syntax, even if it means some common tasks would be a bit more verbose to type. Bash is a horribly twisted pile of historical happenstance that is just no longer worth its few minor typing-efficiency advantages.)

3) OS concepts

Key pieces of every language’s standard library deal with operating system matters like files, processes, and threads. Like with shells, these are complicated subjects in their own right: by introducing these OS concepts intertwined with a language, you’re muddling the clear presentation of both.

a = new Hope()

Enough about how to do programming education wrong. What about getting it right? Well, I have a lot of opinions on that front too. So many, in fact, I created my own language, Pigeon. The design philosophy behind Pigeon can be summed up by a few slogans:

  • Get in, get out. Pigeon is designed to be fully learnable in 3-4 hours. Once the student fully understands every rule of Pigeon, they should write trivial programs in it for maybe 4-8 days, and then they should move on to learning a real language (especially Python). Pigeon is simple enough that it would be ridiculous to offer a full term course devoted to it, even at a high school or middle school. (At the very least, you should be embarrassed to attend an institution that offers a programming course with Pigeon in the title.)
  • The explanation is the design. No other consideration is as important as bare simplicity—both syntactical and semantic—and simplicity is best measured by asking the question, ‘How must this be explained?’ The shorter and clearer the explanation, the simpler the language*. Currently, the Pigeon tutorial is just over 20 pages; I don’t foresee it ever growing past 30.

(*Of course, the simplest possible language would be a minimal notation for a Turing machine, e.g. Brainfuck. While that might actually have educational value, the goal here is to set learners on the path to learning real-world languages.)

Pigeon sticks to the features common to almost all modern languages:

  • expressions
  • functions
  • local and global variables
  • branching and looping
  • recursion
  • arrays and associative arrays
  • modularization across files

(Global variables and recursion are not themselves essential at this point in the learner’s education, but they help establish the concept of local scope.)

The Pigeon program is a bare-bones text-editor window with a sub-window for printing standard output. Clicking ‘Run’ translates the code currently in the text-editor window into a Python module and then executes it. This is all done in about 1,000 SLOC using Python 2.5 with wxWidgets.

Currently, the only output accessible in Pigeon is the standard output window, and the only input is a bare bones pop-up dialog. As explained above, the decision to omit file handling is deliberate. However, one thing I would like to add is a simple interface to wxWidgets’s canvas to allow learners to play with simple 2D drawing. If you’re interested in contributing code to the project, that—or some other kind of simplified input/output mechanism—would be a good place to start.

Another big way to help the project is to concoct simple programming exercises, as I’ve neglected this important area.

If you’d like to contribute, ask for project member status in the comments here so you can edit the wiki. (You must have a gmail account for this.

Learn more about Pigeon:

The current Pigeon download is not usable, so don’t bother with it yet. Something apparently got buggered when I packaged the zip together (hey, it worked on my machine!). I’m putting off a fix until I get the time to add cross-platform filepath support (I developed on Windows without bothering about Unix) and also the time to update the language to match the documentation (I’ve neglected the code since I posted 0.1 in October, for I’ve been focusing on writing docs instead, over which time I changed my mind about a few things). Aside from those few things, I’m sure some things in the code will look hideous from the perspective of a three month hiatus and will demand refactoring. I also haven’t gotten around to putting my svn repository on Google Code, so that will be the first thing I do when I tie up these loose ends sometime this February.

Idiots at the Gates

4 Nov

In discussions of programming education, the argument is often made that learning to program shouldn’t be made easier. This is the Let’s Filter Out the Idiots argument, common also to the fields of law and medicine (or so I’m told). The idea, basically, is that the discipline must retain a face of esotericism to the outside world as a barrier, the passage through which marks a rite of passage for initiates, thus preserving standards within the profession. I’ll concede that there are actually a couple good justifications for a general attitude of anti-idiotarianism:

  • First, law, medicine, and computing are genuinely complex fields, so a large degree of esotericism is unavoidable.
  • Second, in these fields, a little knowledge can be a dangerous thing. In fact, in the case of doctors and lawyers, the purpose of the face of esotericism is likely not at all to avoid creating bad doctors and lawyers—their certification processes are sufficiently rigorous to avoid that—but rather to discourage laymen from thinking that they can practice amateur medicine and law. There may be an element of protectionism to this, but it’s mostly a good idea. Even programmers have legitimate cause to fear amateurs, for amateur programmers tend to create Frankenstein systems, messes which create problems for everyone involved (see this example of a near miss).

However, the anti-idiotarian arguments for maintaining educational barriers to entry are bogus:

  • First, keeping the first phase of education difficult is supposedly necessary to weed out the incompetents, but this is backwards: if people are getting certified who shouldn’t, the problem lies with the certification standards, not the number or quality of the people pursuing certification. (Of course, programmer certification remains problematic, but that’s a whole other issue. See here and here.)
  • The second bogus argument goes like this: in any field, to be much good at what you do, you need a solid grasp of the next two or three layers of abstraction beneath where you primarily work, e.g. decent web developers understand the basics of HTTP, DNS, caching, database performance issues (if not the implementation details), etc, and beyond that they have a working conception of operating systems and general programming tools; essentially, you can’t be a good programmer if you treat your tools and development platform like magic. But, if the technoratti consensus is correct, this, sadly, sums up what’s wrong with a very large percent of people out there who call themselves programmers. So far this is all very true, but then some go on to claim that enabling easier entry to the field necessarily means enabling the next wave of push-button “programmers”. This is wrong. What makes such people bad or “fake” programmers is that they don’t understand essential aspects of programming and computer science, not how they acquired what knowledge they do (or don’t) have.

The zealous anti-idiotarians are missing the point. Making the basics of the field easier to learn benefits everyone, sparing pain for the incapable and hyper-competent alike: those who lack the disposition can get out earlier while those who stay can cover more material in less time, and just maybe a few capable students won’t get discouraged as they otherwise might by the overwhelming minutia of the practice of programming.

The Gettysburg 5-paragraph Essay

3 Aug

Lincoln retouchedThere were only five known drafts of the Gettysburg Address until the recently discovered power-point version. Here now is the long lost 5-paragraph essay version:

The United States is an equality nation formed eighty-seven years ago. WOOSH! BANG! KAPOW! Now we’re fighting over it on this battlefield. I think we should make some part of this field a memorial graveyard.

First, it is a good idea to do this.

Second, we can’t do this. Because we suck compared to the guys who died here.

Lastly, no one cares what we say, but we should do this anyway.

In conclusion, I think we should make some part of this field a memorial graveyard, because otherwise the guys who died here died for nothing. If we just keep at it, we’ll get to keep Iraq Pennsylvania.