47

I find myself repeatedly annoyed by having to teach freshmen about special language rules (like array-to-pointer decay) that have absolutely nothing to do with programming in itself. So I wondered:

What is the programming language with the smallest number of special language rules, where everything is first class and can be composed without annoying technical restrictions? Wouldn't such a language be the perfect teaching language?

Moderator Note

We're looking for long answers that provide some explanation and context. Don't just list a language: please explain why you think the language answers the question. Answers that don't explain anything will be deleted. See Good Subjective, Bad Subjective for more information.

10
  • 1
    Try using Unlambda - there's close to a smallest possible number of language building blocks. A little bit more serious answer: Scheme (R5RS specifcally).
    – SK-logic
    Aug 25, 2011 at 11:23
  • @SK-logic, Unlambda isn't orthogonal because I=SKK. The ultimate in orthogonal languages are single-instruction languages like Jot and RSSB. Aug 25, 2011 at 11:58
  • 11
    @Peter - I don't think he strictly means minimal. A minimal language just ends up with all the extra definitions in the library, so the students have to learn them either way. The way I read this question is "what language best follows the principle of least surprise?".
    – user8709
    Aug 25, 2011 at 14:30
  • 1
    @Peter Taylor: could you provide an example where Timtowtdi conflicts with orthogonality?
    – keppla
    Aug 26, 2011 at 10:05
  • 1
    I think “orthogonality” is a poor choice of words here. As Peter and Steve have established, what you really mean is “principle of least surprise”, or some closely related quality. Aug 26, 2011 at 12:42

9 Answers 9

54

When it comes to 'very few rules', I would argue, Lisp or Smalltalk would win. The bare Syntax can be written on one beer tab.

But in my experience, the simplicity of Lisp and Smalltalk does not mean they are simple to understand and easy to teach. While not the 'pure' way, in my experience the to-do-list-style of imperative languages is the easiest to grasp for newbies.

Therefore, I would suggest Python, Ruby or something of similar abstraction: You find (nearly) every basic concept in them (OK, no pointers), but you don't need to understand it from the start to make something working.

18
  • 33
    impressive work measuring syntax in units of a beer tab.
    – psr
    Aug 25, 2011 at 17:03
  • 3
    And don't forget Perl. Lot more Perl out there than most people think, and the user community is huge. Aug 25, 2011 at 21:45
  • 20
    Perl may be very powerful, but a guy who finds it the easiest path to programming must have the equivalent of Indiana Jones's temples' tunnels as main corridor from his bedroom to his showers...
    – Kheldar
    Aug 25, 2011 at 21:58
  • 9
    Perl's syntax could fit on a beer tab, provided you drink enough beer. Aug 26, 2011 at 9:18
  • 4
    @Randal, the question asks for an orthogonal language. Perl's philosophy is to be non-orthogonal - "there's more than one way to do it". Aug 26, 2011 at 10:02
42

I'd say LISP, or Scheme or a language from that family would be the most orthogonal. With let, lambda, define, if, cons, list, and ( ) you can teach pretty much anything that you'd want to in an intro course. There's also no need for preprocessing directives or int main() and stuff like that which students just include but don't see a reason for.

In my intro CS courses, we did a lot of really cool things with Scheme: implement a Turing machine, implement a TC-201 computer, write a context free grammar, use recursion, write merge and insertion sort, implement adders, and tons of other stuff.

I had done Java in AP comp sci before college, but Scheme was great because I could cut the clutter and focus on the actual concepts in my program. It was a great class and I'd highly recommend you try it for your teaching.

7
  • 5
    Agree. Racket (formerly PLT Scheme) is a slightly-more-friendly Scheme variant which our school uses with great success in introductory classes.
    – NickAldwin
    Aug 25, 2011 at 15:53
  • 3
    What about Haskell? I do not know much of Haskell, but I would expect it to be an orthogonal language.
    – Giorgio
    Aug 25, 2011 at 17:25
  • 4
    @Giorgio: Haskell syntax is quite more complicated, though only a subset could be exposed I guess. The very fact that you have to interact with IO monads from the beginning to get any interesting program is a tad annoying given the OP objective. Aug 25, 2011 at 17:44
  • 4
    For "orthogonal," I vote for Scheme, particularly the Racket implementation. Racket's environment is designed to make a learner's path easier than something like raw Common Lisp. The language is clean, with few rules, indeed. Long ago, MIT decided to use Scheme for teaching Freshman students, using the book, SICP. Those students who survived seem to perform quite well out in the marketplace. However, this approach will not directly teach students how to write commercial-grade code in the most commonly-used languages. Aug 25, 2011 at 19:56
  • 2
    Yes! The fact that Scheme is radically different from most "real" languages lets you focus on programming and not on APIs. Learning Scheme is like the "wax on, wax off" of coding; seems like a waste of time until you realize you have a deeper understanding of the computer than before.
    – benzado
    Aug 25, 2011 at 21:22
17

Pascal was specifically designed to teach programming. It's easy to learn (it was one of the first programming languages I learned).

2
  • 3
    I also learnt to program using Pascal and I find it is a very clean language. The only non orthogonal feature I can think of is the syntax of the writeln() and readln() procedures, which have a variable number of arguments and allow to specify formatting.
    – Giorgio
    Aug 25, 2011 at 17:24
  • I found it a very frustrating language. But I may be projecting, since I had a very, very bad instructor.
    – greyfade
    Aug 25, 2011 at 20:23
14

Logo: it's still alive and kicking!

; draws a triangle
FORWARD 100
RIGHT 120
FORWARD 100
RIGHT 120
FORWARD 100
RIGHT 120

It might seem more like a toy then a programming language, but it wouldn't be a bad first step for a lot of people. The syntax is very simple, but the turtle provides a more concrete form of feedback than most languages/environments. Trying to create a specific shape is a great way to learn the process of thinking ahead to solve a problem.

If you have an aversion to turtles, though, I really think Scheme is the way to go.

2
  • 1
    Believe it or not, Logo is a Lisp, just like Scheme. Most users don't get far enough beyond simple looping & turtle graphics to learn this. Feb 28, 2013 at 19:58
  • @SeanMcSomething That's interesting, given the focus on side-effects (moving the turtle) rather than evaluation of expressions.
    – benzado
    Mar 4, 2013 at 6:37
10

I would propose both SML and Haskell. Orthogonality has been a principal design point for both. In particular, the core of SML (that is, the portion of the language not concerned with modularity) is pretty much a typed lambda calculus. As a result, most language features are driven by types and the types in turn drive the introduction and elimination forms for the values. This is pretty much ideal.

There are a few non-type-theoretic warts in both languages (eqtypes in SML, seq in Haskell) but they still beat the pants of anything else out there in terms of bizarre interactions of unrelated language features.

8

Whatever the choice, I would strongly urge teaching a “real” language. Teaching toy languages works for some people, but for others it’s very, very frustrating due to the disconnect to the real world. Some people need real-world relevance as a motivation for learning, and it’s not our place to judge this learning strategy (in fact, that’s a common misconception).

This disqualifies languages such as Logo, but also domain-specific languages such as Processing. While the latter is extremely useful for certain things (e.g. producing info graphics), the use is too restricted for most uses (and thus most users). This also excludes Gofer, a useless Haskell subset. It also excludes Pascal because although the latter has been used in real projects, it just isn’t relevant any more and simply lacks essential features (e.g. built-in strings).

Of the practical languages, I’d agree with those already mentioned: modern Lisp or Scheme dialects, Haskell, Python or Ruby. Personally, I’d probably use Python but all those choices have their share of advantages and disadvantages.

8
  • 2
    It is a fallacy to claim that teaching a "real" language is the way to provide real-world relevance. It is the teacher's job to show how the "toy" language relates to real-world skills. Learning to juggle by starting with knives does not mean you are learning more relevant juggling skills.
    – benzado
    Aug 26, 2011 at 19:50
  • 3
    @benzado You misunderstood my point. If you learn a toy language you have to transfer your skills to make them relevant to real-world problems. My whole point was that this transfer is an additional indirection that actively prevents some people from learning. Different people learn in wildly different ways, and some people really need this immediacy. Learning to juggle with knives isn’t the same thing. The real analogy would be with learning to program by writing a live missile guiding system as the first project, and I never suggested that. Aug 27, 2011 at 9:06
  • 3
    I get your point. We just disagree. I think the transfer is important, it requires that the student has a deeper understanding than one who has a successful guessing strategy (e.g., one who "solves" word problems by picking out numbers and plugging them into the formulas in the beginning of the chapter). In other words, if they can't transfer what they learned, they never learned it in the first place. To keep students motivated, you just have to choose the right problems, which is important regardless of language, "real" or "toy".
    – benzado
    Aug 29, 2011 at 16:01
  • @benzado Transfer is important, no argument there. But it’s a whole ’nother disciplin that needs to be taught, and some students don’t possess it. Besides, the “deeper understanding” part is also true, but also besides the point: this is already an advanced state that needs to be reached. Once the students have learned “it”, they can transfer it. But first they need to learn, and in order to do that, some students need relevance. Transfer comes later. Aug 29, 2011 at 16:16
  • In math edu (where I have a tiny amount of experience), "Learning without Understanding" is a big problem: a focus on how to do it without why. My claim is that if you teach the concepts of programming, a toy language will do fine, and if you succeed, the transfer to a "real" language won't be hard. (If transfer is hard, you taught procedures, not concepts.) A toy environment doesn't prevent people from learning, but it does requires good lesson planning to be engaging. (I like this thread but I think we've crossed over into discussion territory and the moderators will be displeased.)
    – benzado
    Aug 29, 2011 at 19:03
7

Tcl has 12 rules that govern the entire language.

[1] Commands. 
[2] Evaluation. 
[3] Words. 
[4] Double quotes. 
[5] Argument expansion. 
[6] Braces. 
[7] Command substitution. 
[8] Variable substitution.
[9] Backslash substitution.
[10] Comments. 
[11] Order of substitution. 
[12] Substitution and word boundaries.

There are very few special cases or reserved words or characters.

4

What is the programming language with the smallest number of special language rules, where everything is first class and can be composed without annoying technical restrictions? Wouldn't such a language be the perfect teaching language?

To expand on my comment, in Jot everything is first class (because it's a lambda calculus) and can be composed. There is only one instruction. It's an absolutely awful teaching language.

In general, Turing tarpits have very few special rules and require you to understand the fundamentals of computation very well before you can do anything. The perfect teaching language allows students to experiment without pulling out all of their hair, so higher level abstractions are actually a good thing.

4
  • Thank you for introducing me to the term 'turing tarpit', i always needed a term for this kind of simplicity.
    – keppla
    Aug 26, 2011 at 9:52
  • I agree that students should be able to experiment, but requiring understanding before you can "do anything" seems like the whole point of teaching.
    – benzado
    Aug 26, 2011 at 19:52
  • @benzado, I agree that the point of teaching is to impart understanding. But with most people you have to start with the basic concepts, let them get their heads round that, and then teach them intermediate concepts. So you want a language where someone who understands a little bit can write programs which do a little bit. There's a reason that most programming courses don't start out by teaching Turing machines or Minsky register machines. Aug 26, 2011 at 20:18
  • 1
    Right, I think we differ on what "do a little bit" means. If you want to (for example) appease the "show me how to make video games" contingent, you can do some things, but they will get to a point because they can't make progress and get frustrated, and then you have to go back to the "boring parts" so they can gain the understanding to move forward. At this point, they are already frustrated in a bad way and may just give up; on the other hand, doing the "boring parts" first and building upwards means continual progress. But obviously you don't start with a strip of semi-infinite tape.
    – benzado
    Aug 26, 2011 at 20:44
2

The most important features in a langage you learn are:

  • principle of least surprise (PASCAL)

  • readability (Ada)

In my opinion, the second trumps the first, since reading code is even more important than writing it.

Now again, I write C#, Java, Objective-C and Javascript for a living, all of which have horrible quirks :D

Still if I had to choose one langage to start with, I'd go for C#. It's relatively easy to read, has few serious surprises in itself (they are most often hidden in MS tools/frameworks...) and a massive amount of code to be read and documentation, both of which are essential to learning well.

5
  • If it's just for the readability, and not for the static typing and safety of ada, Python and Visual basic (yeah, i know, not the cool kids way) have a similar clutter free syntax, imho.
    – keppla
    Aug 26, 2011 at 9:51
  • Yes I agree with you, but "if it compiles in Ada, it should run". Doesn't prevent logic errors though, as Ariane V can tell :D
    – Kheldar
    Aug 26, 2011 at 9:53
  • I've been thinking whether static typing is useful for beginners or not. It gives more support (like training wheels) but this can be seen both as good thing and a bad thing. It pushes some responsibility away from student to type system.
    – Aivar
    Nov 30, 2011 at 11:11
  • @Kheldar, no programming language can prevent management f***ups like the one that was responsible for the Ariane V failure. You should do your homework on this one. Oct 3, 2013 at 12:26
  • @JohnR.Strohm that was exactly my point: sometimes it's not the language, it's the engineering flow (eg, management) that's flawed. You could have worded your comment less aggressively though, in my opinion.
    – Kheldar
    Oct 4, 2013 at 9:32

Not the answer you're looking for? Browse other questions tagged or ask your own question.