Computer Science Canada Scheme as an introductory language |
Author: | chrisbrown [ Tue Aug 04, 2009 10:32 am ] |
Post subject: | Scheme as an introductory language |
By now I'm sure most of you know that Scheme is UWaterloo's language of choice for first-year CS students. For someone with a few years of prior experience and an aptitude for programming, a language like Scheme is a godsend with its unfailing consistency and simplicity. However, I question its effectiveness as an introductory language for the same reasons that make it so elegant: it is too simple. What I've gathered from my novice peers is that Scheme is relatively easy to learn, but when the course switches over to C or Python, things fall apart. The recursion mentality becomes so ingrained that basic concepts like for loops seem unnatural. The difference between sort(list) and list.sort(), while easily deciphered even by rookie imperative programmers, is such a stretch for native scheme students that any love for coding quickly starts to fade. In theory, I think Scheme might be the perfect beginning language. However, there are many languages out there, each with their own quirks and subtleties, and Scheme fails to prepare the student for any of them. Of course, I may be missing the bigger picture. These are just my observations among the select group that I worked with through first year. I just think fails to convey the nature of programing; it would be better suited to those with some prior mainstream experience who can appreciate its beauty. |
Author: | jbking [ Tue Aug 04, 2009 11:22 am ] |
Post subject: | Re: Scheme as an introductory language |
Would you rather the school go back to having Pascal be the first year language? IIRC, Scheme came up in my second year course when I had it back in them olden days of the mid 1990s. The question of what kind languages to teach initially is a rather valid question that I'm not sure has a simple answer. Object-Oriented and imperative would seem a good starting point but that is what I had for my starting point back in high school. |
Author: | Tony [ Tue Aug 04, 2009 12:09 pm ] |
Post subject: | RE:Scheme as an introductory language |
It's not even full Scheme, but a subset of Scheme; and it offers all the functionality required for the curriculum. One of the main advantages of using Scheme, is that is levels out the playing field for the incoming high school students. Computer Science is horribly nonstandard at the high school level, to a point where many schools don't even offer a class. Also, I think it would be easier to Scheme programmers to make a connection that loops are tail-end recursion, than it would be for imperative programmers to figure out recursion. I've certainly met students having trouble with the latter. |
Author: | Prabhakar Ragde [ Thu Aug 13, 2009 7:36 pm ] |
Post subject: | Re: Scheme as an introductory language |
Perhaps I can comment, since I designed the two first-year CS courses at UW to which you're referring. Your observations are accurate but I question your conclusions. Every university teaching introductory CS has to cope with diverse backgrounds of incoming students. Waterloo has the added burden of requiring two CS courses of several hundred non-CS Math majors every year (including future accountants and actuaries). Historically, the Math Faculty has encouraged early flexibility -- in the period when UW made its reputation for Math and CS, students didn't select their major until after first year. While that has been eroded in recent years, I would argue that it is in the best interests of both students and the institution to preserve it. The Pascal period (1987-1997) that jbking refers to was probably a golden age for this arrangement. Students reluctantly taking CS didn't necessarily come to like it, but it didn't overwhelm them, either, and students planning to major in CS were reasonably well prepared. The move to Java (1997-2008), and the concurrent infiltration of OO concepts into high-school courses (formerly, this material was not taught before second year university) changed both sides of that balance. Non-majors were for the most part overwhelmed, and majors tended to learn to tweak provided examples that they did not fully understand, rather than programming from scratch. (This was partly due to the "objects-first" approach used, and partly because understanding even the simplest Java programs requires rapid assimilation of some fairly complicated and ill-motivated concepts.) Even worse, the syntactic demands of Java obscured the concepts of computer science that were supposed to be taught in first year. I found that my students in senior courses not only could not think algorithmically, they could not implement algorithms explained to them in English or pseudocode. When I decided in 2003 to offer an alternative, I looked around, and chose Scheme not only because it facilitated implementation of concepts rather than obscuring them, but because of an excellent textbook (How To Design Programs) and an excellent educational IDE (DrScheme). Initially, students who learned Scheme had to then learn Java in a hurry to match the existing courses. What I didn't anticipate (but should have) was that even after the Java courses went away (in 2008, because the Math Faculty finally noticed the failure rates going through the roof after the elimination of Grade 13), instructors in subsequent courses would remain at best indifferent (and at worst hostile) to the approach taken in first year. Students still had to learn C or Python in a hurry. I've heard it said that one's second programming paradigm is the hardest. So students who know Java struggle with Scheme in their first term, and students who don't struggle with C or Python in their second term. If the only goal of first year was "learn a mainstream imperative programming language", then we could just start everyone in Python, as U of T does. Students would never have to seriously learn functional programming; we could put three weeks of it in a second-year course, as jbking had, or leave it for an optional senior-level course in programming languages. That would leave them impoverished, but most of them would never know what they were missing. I rejected Python in 2003, and argued against it in 2008, for a number of reasons: no good textbooks, no good educational IDE, too many powerful operations obscuring efficiency, and no structures (records) without all the complexity of objects. But even if these could be fixed, I no longer believe (as I did by default during the years I taught the Pascal course that jbking took) that the imperative paradigm is the right one to teach first. The fact that a variable can take on many values over the course of a computation makes reasoning about programs more difficult. I sometimes illustrate this to students by writing a simple for loop with a couple of assignment statements that is supposed to implement a simple computation that everyone understands when it is done on the board. But it doesn't, and neither does a tweak or two that look convincing when I propose them. Loops aren't as simple as everyone seems to think. Tony is right that the connections between functional and imperative approaches (such as loops being a particular form of tail recursion) can be made with enough time. But there isn't quite enough time in the second half of first year. Hence the compromise of CS 136 (the "introducing C" second course for CS majors) which doesn't do quite enough in showing how functional programming can scale past toy problems and doesn't give students quite enough practice in imperative programming. Already in this summer term I further compromised by moving some of the introduction of C language features earlier, before a full explanation (as is typically done in a first programming course, but as is *not* done with Scheme in CS 135 in the first term) in order to have more assignments devoted to practice in C. CS 135 is pretty much my ideal first course. CS 136 is not my ideal second course. It has as much of the ideal as I can manage, but not enough to be truly satisfying. Perhaps after a few years, the School of CS will conclude that Scheme is pretty but pointless, and switch over to Python (or worse, C++ for majors). That would be a shame, because Waterloo has always been different (even when, as with objects-first Java, it was the wrong kind of difference) and after such a switch, we would pretty much be doing what every other university in Canada does. |
Author: | btiffin [ Thu Aug 13, 2009 9:33 pm ] |
Post subject: | RE:Scheme as an introductory language |
I've said it before, I'll likely yell it again. 1) Assembler - simple, but in assembly 2) C - just because 3) Forth or COBOL or Prolog or Lisp or BASIC or just opining Cheers |
Author: | Prabhakar Ragde [ Fri Aug 14, 2009 9:21 am ] |
Post subject: | RE:Scheme as an introductory language |
My choice would be to follow a first course using Scheme with two parallel and coordinated courses, one "going down" towards the machine (memory model, C, assembler) and one "going up" towards increased abstractions (OO, algebraic data types, type inference, type classes, using two or more new languages). |
Author: | chrisbrown [ Fri Aug 14, 2009 9:49 am ] |
Post subject: | Re: Scheme as an introductory language |
Interesting points. I've heard the "level the playing field" mentality echoed by many of the instructors, but that's as far as they cared to elaborate. Thanks for explaining the reasoning behind it. I agree the parallel high/low level courses would be a good idea, but they would really only apply to CS majors. I think Scheme would be effective for the transition to abstraction, but no so much for the memory model. If you ask me (but no one ever does), I would say let non-CS math majors stick with Scheme as it is taught now - dropping Python - since the functional paradigm complements the functional nature of mathematics. For CS students, I say start with Scheme but introduce mutation early on, and save abstraction (lambda, ALFs) for the high-level follow-up, and C for the low. |
Author: | Prabhakar Ragde [ Fri Aug 14, 2009 6:51 pm ] |
Post subject: | RE:Scheme as an introductory language |
But introducing mutation renders the substitution model much less effective. It really forces the introduction of the memory model, and understanding Scheme in this model is harder because of the extra layer of indirection needed to handle dynamic types. The other problem with getting to mutation early is that it plays such a minor role in idiomatic Scheme. Yes, you can write C-like code in Scheme, but what's the point? We originally ended 135 with mutation of lists and structures. Over time, we de-emphasized mutation in Scheme, to the point where now it is touched on in 136 mainly to initially motivate the memory model and the study of C. While I disagree with some aspects of how the current 116 implementation takes non-majors from Scheme to Python, I don't disagree with the idea of this transition. Python is a good stepping stone to any imperative language that a non-major may have to grapple with in a later course or work situation. |