[long message, all skippable, and you can skim sections of less interest] Background, part 1:
This Fall I'll be teaching "my" undergrad PL course for the first time since Spring 2008. I'll be using Racket for 2-3 weeks of the course, both as an excellent example of a modern, dynamically typed, functional language with a trivial syntax, and as a vehicle for several specific topics, including various scope definitions, dynamic "vs" static typing, generative structs, very basic macros, some module stuff (particularly getting ADTs by putting a struct definition behind the interface), streams, and memoization (using mutation, likely mcons, for those last two). The course also uses SML (before) and Ruby (after). The course is ten weeks long (quarter system) and lower-level (after two quarters of introductory programming in Java). I quickly retreat to these facts when justifying why many great, crucial topics don't fit in the course. :) My most recent offering is here: http://www.cs.washington.edu/education/courses/cse341/08sp/ Usually other instructors teach the course. Only one follows my approach; for the rest we have this rough "peace agreement" (needs light updating, basically to reflect Racket != Scheme): http://www.cs.washington.edu/education/syllabi/341.html As a lower-level course, it's mostly "programming" rather than "languages" if you will. Background, part 2: Much has changed and improved in Racket since 2008, so I've been reading the User's Guide in preparation. I am very, very happy, and in fact plan to use the User's Guide as the primary resource for students beyond my own lecture notes/readings. I'll be updating all my materials to bring them up-to-speed to "modern racket", though as a lower-level course, most of "modern racket" isn't relevant. I submitted a "bug report" about something yesterday that quickly turned into a fantastic, interesting discussion that more properly belongs on this list. So I'm going to summarize the discussion so far before bringing up a couple new topics. Summary of topics so far: 1. My initial complaint was that andmap and ormap are misnamed because they are [short-circuiting] folds, not maps. Yet the User's Guide does not justify their names and the Reference Guide goes further and says they are "like map". But after further discussion, I concede that they are "like map" in a way that could be included in the docs: ignoring short-circuiting they are (list (f elt1) ... (f eltn)) where list is replaced by and or or. Another way to think about it is, they are /not/ maps, but the name andmap is saying "apply and to the map of f to the elements", and I simply wasn't parsing the identifier that way. 2. "Whatever you don't like you can fix by making your own language for the course:" This is indeed a fantastic feature of Racket, but one I plan not to use. There are advantages of sticking to full Racket, showing them a modern, well-documented language, without me tweaking it. 3. "You should really show them some typed racket." a. "It avoids the common misconception that static typing must mean Hindley-Milner" -- if only that were the misconception I'm working on, rather than "static typing must mean int[] and C or Java" :) In all seriousness, even if I left them with the impression that Racket was like its fully dynamic predecessors with no notion of a typed language or a contract system, you shouldn't be (too) mad at me. I surely leave them with equally egregious misimpressions of SML and Ruby since I'm not trying to "teach them the languages", though I am imparting the skill of being able to do something interesting and useful in a language you had never seen a week ago. b. "you can show them an untyped/typed interaction that is eye-opening for the better students and shows them something truly on the cutting edge of PL research" -- now this is very intriguing and sounds like a great addition to the lecture on static/dynamic typing. Hopefully Shriram (to call him out by name) will reply to the list with a fleshed out description of the example he uses for everyone's benefit -- I can probably connect the dots from what he said, but maybe not as well. 4. "Instead of streams, you should give them a proper sense of programming with laziness and lazy Racket is the way to do this": I've made a conscious decision not to teach them programming with laziness. I do teach idioms for delaying evaluation and memoization, and how using these correctly usually requires purity, but I couch it all in a strict evaluation model. Standard excuse: I have only 10 weeks, including their first taste of functional programming. 5. "Use boxes instead of mcons, they're more like SML references anyway": Or I might use mutable structs instead of mcons. We do so little with SML references (one call-back example) they won't see the connection either way. The point is I need to do some "safe updates" for things like memoization. Mutable pairs work pretty well there. New topics (more later as I'm not done reading): 6. In reading the User's Guide, I was pretty surprised that first (unlike car) raises an error on a non-list. I eventually looked over at the Reference Guide where I learned that list? is O(1) and I was able to connect the dots -- "aha, now /this/ is a pretty cool reason to make cons cells immutable beyond the basic 'set-cdr! is nasty' ". I recommend the User's Guide include a comment or footnote that first is an O(1) operation -- you can just point to the Reference Guide for any details. 7. I'm having trouble understanding modules and the rules about re-definitions. I need to re-read Chapter 6 for a third time, cook up from examples, and post a full message just on this topic. I think the User's Guide docs are partly to blame for my confusion. To pick on two examples I'm ready to discuss: a. Section 4.2 reports, "A module-level define can bind only identifiers that are not already bound within the module. For example, (define cons 1) is a syntax error in a racket module, since cons is provided by racket." Whether this is true perhaps depends on what you mean by "a racket module". A module written in the racket language seems to have no trouble re-defining cons internally at its top-level: #lang racket (define cons +) (cons 1 2) ; 3 b. The contracts chapter reports, "To experiment with multiple modules within a single module or within DrRacket’s definitions area, use the racket/load language. The contents of such a module can be other modules (and require statements), using the longhand parenthesized syntax for a module (see The module Form)." This would have been very good to know in the Modules chapter, or at the very least an explicit comment that racket modules can't contain other modules. (Sorry if I missed it.) That said, for simplicity, I'm tempted for my class to stick to racket and simply use multiple files for my modules examples -- if nothing else, it helps indicate that Racket isn't a toy language where everything goes in one file. --Dan _________________________________________________ For list-related administrative tasks: http://lists.racket-lang.org/listinfo/users