On Scheme

Thoughts on Scheme and teaching Scheme

Archive for April, 2006

Real Criticisms of Scheme

Posted by Peter on April 30, 2006

Recently I have noticed a tendency in the Common Lisp community to criticize Scheme, possibly to make the Scheme community look equally bad in its handling of such viewpoints. So to head off silly and/or baseless attacks on Scheme I have created a brief list of things that Scheme actually does have problems with. Maybe someone will even turn them into a SRFI eventually, when we reach some kind of a consensus as to what the best solutions are. Remember these are problems with the language, not an implementation. Even if a specific implementation has fixed them it doesn’t fix the language itself. The language needs to address such issues so that the implementations don’t become too fragmented.

Types can be used to catch stupid programmer errors (the kind mere mortal make all the time, i.e. “which order do those parameters go in again?”) at compile time as well as to optimize away unnecessary run-time checks. Unfortunately the only types that Scheme supports are purely run-time. A type system also makes overloading functions based on the type of their parameters possible (efficiently, checking all parameter types on each call is not efficient), which can be extremely useful.

The macro system, although being nice for having hygienic safety and pattern matching, is at times cumbersome. It should be easy to create Common Lisp style macros when you want them. The macro system is also poorly documented (in my opinion).

The module system doesn’t support versioning well, nor does it support module “trees” (i.e. modules which have sub-modules declared within them). The fact that you can’t set! variables provided by modules feels arbitrary as well.

Scheme doesn’t have objects integrated into the language itself. Although I personally have argued that this can be considered a positive feature (see: here), I admit it can be annoying when to work on five different projects you have to learn five different object systems.

Trapping errors thrown at runtime, such as type errors, can be cumbersome and implementation dependant. Additionally there is no built-in syntax for providing the try-catch features available in other languages, although you can define your own with continuations.

Once again threads should be provided by the language, not by implementations.

Multiple Values
The values construct is cumbersome to work with. It requires special procedures to handle multiple values when it should be as simple as (f (p)) if f expects two parameters and p returns two values.

Lack of Compiler Hinting
This has partly been addressed under the problems with types, but as a whole Scheme lacks methods of hinting to the compiler what you are trying to do so it can optimize rationally. For example if defun was made part of the language we might allow the compiler to make the assumption that symbols created with defun could not be set!, and thus such functions could be inlined safely, ect.

Too Minimalist
Many of these problems resolve to the complaint that Scheme is too minimalist for its own good. Problems with types, threads, errors, objects, and modules are all symptoms of Scheme’s desire to be simple. Minimalism is good of course, because it makes the language easy to learn, implement, and optimize, but it has to be balanced with functionality, so that implementations don’t diverge to far when they are forced to implement features that the language doesn’t support.

Why use Scheme if has all these problems?

From this long list of faults you may think that I am encouraging you to drop Scheme. Many of these deficiencies have been resolved by individual implementations, which means that you can work as though they had been resolved, although there is a possibility that eventually you will have to update you code to bring it in line with the official solutions. Also Scheme still has some cool features that make it shine in comparison with Common Lisp, for example real continuations, guarantees of tail call optimization (no need for nasty do loops), and of course it is a Lisp-1. Additionally there is a formal process for revision, the SRFI, which allows the community to have their input, ensuring that Scheme improvements are really improvements, not fiat from some language deity. Even though these problems are currently open hopefully Scheme can later implement the best solutions to them, leaving the language as elegant as it is currently, unlike the solutions in Common Lisp, which often feel like hacks (just my opinion). If anyone does propose a SRFI to address one of these issues I would be grateful if they would let me know.


Posted in Exploring Scheme | 7 Comments »

Shameless Self Promotion

Posted by Peter on April 29, 2006

I have just started another blog which will focus on my other passion in life, philosophy. This is the only time I will mention that blog here, since I know for many of you philosophy and computer science don’t exactly overlap much.

Posted in Uncategorized | Leave a Comment »

Don’t Be An Expert

Posted by Peter on April 28, 2006

In this post I am going to share a lesson I learned too late with you: never become an expert in anything. Be good at it, but not an expert.

Who is an expert?

Not every programmer is an expert with the tools (environments and languages) they use. For convenience let us call someone an expert when they have mastered a large percentage of the features of the tool they are using, which means not only do they know that these features exist and what they do, but they are familiar with the specific details (for example a Java expert would be familiar with most of the standard libraries, and for the most used parts of the language they would also know possible causes of exceptions and the exact type of exception thrown, as well as the relevant class hierarchy). The expert probably owns books on the subject as well, and has invested money in commercial solutions if they are available (once again, an expert Java programmer has likely bought at least one expensive Java development tool and a whole shelf load of Java books). Personally I don’t think I am an expert in any language, but I am somewhat of an expert with respect to Windows programming. I have invested money in Visual Studio, and am well acquainted with the Win32 API, DirectX, device driver programming, as well as many other diverse topics.

Problems with being an expert

The primary problem with being an expert is that when you have reached this level every task is easiest using the tools you are already an expert with. For example I once dabbled in Perl, but despite Perl’s reputation at being great at dealing with text it took me longer to make a parser for a particular file format in Perl than in C++. This doesn’t mean that Perl is bad, it just means that I am too much of an expert in C++. Once you become an expert it becomes hard to pick up new languages and tools because to pick up these new tools you must work on projects with them. However it is always faster for you to use your old tools, and thus you don’t begin projects using the new tool you were initially interested in, as it always seems more important to get the project done than learn something new; after all you can always learn it later. Thus in the end you remain an expert in what you already know and only expand your horizons when it is literally impossible to accomplish what you want with your preferred tools.

Experts are harmful to the community

As you may know Windows Vista is going to be making a gradual move to a new API. As a Windows “expert” my gut reaction is be opposed to this move. It means I will have to recode my projects, relearn all the intricate details I have picked up, and repurchase new versions of my tools. If Windows was run by the community I am sure that the old API would have been supported forever. Fortunately for progress in Windows it’s not, but there are other languages and tools that are run by such a community. Here I am obviously making an oblique reference to Common Lisp. Common Lisp experts have invested money in the commercial tools, and much like me and Windows they are reluctant to leave that investment behind. Unlike me and Windows however they have a say in what changes are made with respect to Common Lisp, and thus can ensure that the language remains basically static.* Another example of an expert dominated community may be emacs, which hasn’t changed significantly for many years, but since I don’t personally use emacs I can’t say for sure.

How can I stop being an expert?

Good question, and if I knew the answer I would probably be running Linux on my other machine at the moment. I mean I could go and work on my new Lisp implementation under Linux, but that would mean learning how to use gcc, and how to: inline assembly, write naked functions, create dynamically shared code objects, create libraries, manipulate files, do multi-threading, figure out the object file format, invoke the linker within a program, write an installer, and many more tasks that I can already do without too much thinking in Windows. In fact learning how to do these things in Linux would probably take as long as the project itself. I think to myself “maybe I can port it when it is done,” but in reality when it is done I will want to either make improvements or start a new project, not port it to an operating system I rarely use, and thus the cycle reinforces itself. If you have any ideas on how to solve this problem feel free to voice them.

* How do they have such a say if the language has commercial implementations? Couldn’t the company implement new features? The reason the commercial implementations remain basically static is thus: if they wanted to do something radical, like change CLOS, the experts, who are the majority of their customers, would leave for one of the other vendors. Thus the companies are forced to make only little extensions that don’t break the standard.

Posted in Uncategorized | 1 Comment »

Actual Code

Posted by Peter on April 27, 2006

I know it seems like my blog has turned into a place for me to talk without actually accomplishing anything. To remedy this I am releasing a working draft of my asynchronous garbage collector. Unfortunately for you it is written in C++, and is meant to be compiled in windows. (Bless me father, for I have sinned. It has been 2 function calls and a continuation since my last garbage collection.) Porting it shouldn’t be that hard if you want to. Anything that is platform dependant is conveniently located in platform_dependant.cpp. Also you need to define the symbol GC_COUNT_POINTERS if you want the sample to compile. Finally I make use of the hash_map and hash_set classes, which may not be part of your compiler’s stl.

How it works

In this system there are two types of references, hard and soft. A hard reference means that you guarantee that the reference will not become part of a cyclic data structure. Usually you want to acquire a hard reference to an object you are using directly. Soft references are references from one object to another. If a cyclic data structure made up of soft references occurs the garbage collector will be able to collect it. When you alter an object’s member pointers you must call gc->ReferenceSoft and gc->DereferenceSoft as appropriate on the pointers as appropriate. Finally when altering member pointers of an object that has existing references pointing to it you must surround the code altering it with gc->BeginEdit and gc->FinishEdit calls.

For more specific details I suggest that you check out the example provided. Note that the functions defined in the sample do not reflect how I actually expect to define Lisp functions (in terms of parameters).

Source is available from Sourceforge (see sidebar ->) under “Garbage Collector”.

Posted in C/C++, Exploring Scheme, Windows | Leave a Comment »

Theory and Application

Posted by Peter on April 25, 2006

No one seems to like the computer science curriculum offered at universities. The complaints I hear most often are that there isn’t enough theory, and that there isn’t enough practical application of concepts. Initially I thought that these goals were mutually exclusive, and that people complained simply because they were taking the wrong kind of courses. However, when you look at what actually is taught, you come to realize that some courses manage to leave out both theory and application when they could easily have had both. Before I show how both theory and practice can work together I probably need to defend the importance of each to computer scientists.

Let’s talk about theory first. When I think of theory I think immediately of math, and I think this connection tends to scare away some students. The theory side of computer science, ideally, deals with computation as an abstract process, which can be studied in order to prove, often with math, what is the best solution for a given problem. For example, theory teaches how to analyze algorithms under different conditions for speed and space efficiency. The theory side also encompasses topics such as how to mathematically model networks, lambda calculus, information theory, ect. In all honesty learning theory isn’t much fun, but it is necessary. The most important consequence of theory is that it encourages new “practical” advancements. For example the theory of lambda calculus gave birth (partly) to Lisp. Knowing more about information theory will help you design better network transport protocols and compression schemes. Advancements can be made without a theoretical background, but they tend to be made slowly with many revisions. Ideally theory can tell you directly what the best solution to a problem is, allowing you to implement that best solution in the beginning, not after 15 beta versions.

Practical knowledge however is also important. Obviously without actual programming experience you can’t put any of your wonderful theoretical knowledge to use. Programming and other practical applications also give insights into the capabilities of current software and hardware. Often the physical limits of the computer will determine what theories can be made into a real system, and you won’t be familiar with these capabilities unless you deal with them regularly. Finally, the desire to actually implement something is an excellent vehicle for learning more about computer science in general. For example I first learned how networks functioned before I even went to college because I was trying to create a chat program (in order to cheat on the computer science exams, but that is another story).

When I look over the classes offered at my affiliated university I notice some gaping holes, in both the applied and theoretical curriculums. The most noticeable missing applied class is one on debugging, which has always struck me as odd. Programmers can waste a lot of time trying to find bugs, I know I do, but for some reason students aren’t taught how to debug and are expected to learn on their own. As a result students new to programming often spend more time trying to find errors in their programs than they do writing them. In the theoretical side of the curriculum a class on information theory is clearly missing. Information theory has its fingers in every aspect of computer science, because from one point of view all any program does is manipulate information. Once again universities seem reluctant to actually teach students this material, expecting students to pick it up on their own.

Ideally application and theory should go hand in hand in the classroom. For example if you were teaching a class on mathematical approach to networks, with regards to speed, connectivity, ect it would be reasonable to have the students implement some of the best models that result from the mathematical study. Likewise purely practical classes, say a class on XML, could be enriched by applying that practical knowledge to an abstract domain, for example implementing abstract syntax trees in XML. Instead what we have are mediocre classes that do neither. For example take a look at any text book on operating systems. Inside you will find plenty of general information, but you will not find any code, not even pseudo-code. Nor will you find any theoretical underpinnings for why operating systems work the way they do. Instead these books stick to giving outlines on topics such as “what is a file system?”. Classes on networking, hardware, artificial intelligence, and many others, all follow this pattern, with students being exposed to little theory and less concrete application of the concepts.

Of course if you are a self motivated computer science student this won’t be too much of a problem for you. Now that you know what kinds of things your education is lacking it is easy enough to learn them from the internet (for the most part). Of course if you aren’t a self motivated student then this isn’t much help, but then again if you aren’t a self motivated student why are you in computer science?

Posted in Teaching Scheme | 2 Comments »