You may have seen in an earlier post that I have taken up a diversion this evening, and one side effect is that I’m learning Scheme. Scheme is a variant or dialect of Lisp, which, developed in 1958, is the second oldest high-level programming language in widespread use…second to Fortran, which I do not intend to learn any time soon. So basically…I’ve gone to some level of old school that probably shouldn’t be visited by most people.
First and foremost…if it’s at all possible, I love VS.Net even more now. The modern IDE is truly an amazing animal…I remember console-coding Pascal and BASIC…but only just. The modern IDE is the number-one productivity tool we have today.
Second – I now have an inkling of the level of programmer out there making functioning stuff with tools like this. I can see after just a couple of hours that this type of programming requires much more planning and precision up front to be productive, unlike in c# where I can type a bunch of code…read over it…see if it compiles….make changes to a single line…etc. Try it out. You’ll see what I mean.
So…Scheme. First the basics. Everything I’m about to say is based on all of about 2 hours of learning the language and the tool, so there may be better things out there that I’m not aware of yet.
I’m using the MIT/GNU Scheme. There is a Win32 version there, as well as a decent language and environment reference that I’ve been working off of. Download, install, and run the thing named….”Scheme”.
Basically what appears to be happening is you get this shitty console with no buffer (once the screen scrolls it’s lost) and no windows editing capability. Yay.
First thing to get out of the way. This thing will not do red squiggly underlines if you make a typo or do something wrong. There is no built-in error checking. If you screw up, you do it over.
Language-wise, it’s pretty easy to get up and running. There are two basic types to get started with: character and number. You have standard math operators + – * /
Syntactically…it gets weird.
Every expression is evaluated in a parentheses pair. (<expr>)
Operators are all prefix. So. To evaluate 1 + 3 you would have (+ 1 3). 1–3 = (– 1 3).
Order of operands is the same as it would be if the operator were between them. So if you want to evaluate 1 – 3 you do (– 1 3) and if you want to evaluate 3 – 1 you do (– 3 1).
It’s a little picky about whitespace. So be careful not to do (-1 3) or it gets all pissed off and throws out these totally non-debuggable error messages. yay.
There are boolean expressions as well, you have > < and =. Boolean expressions return the literal #t for true and #f for false. Evaluating these expressions also works with the operands in the order you would expect were the operator between them. This threw me off a little at first because I was reading (> x 0) as “if greater than x is zero” (or, “if zero is greater than x”) rather than the correct way which is “if x is greater than zero”. Might have just been me…but it didn’t immediately make sense to me.
Conditionals are present. There are two forms I’ve learned so far. You have “if” to handle one case with only two possible results. if x then y else z. it works like this (if (> x 0) (– x 1) (* x 4)). That reads as “if x is greater than zero subtract one from x, otherwise multiply x by 4”.
There’s also cond, which works kind of like a switch…case but really more like the VB Select…Case in that you can evaluate multiple expressions. So I could break it down like: (cond ((< x 0) (+ x 1)) ((= x 5) (+ x 3)) ((> x 100) x)) which is “if x is less than zero, add one. if it’s 5, add 3, and if it’s greater than 100, leave it”.
Defining variables is done thusly (define x 5) will create a variable called x and initialize it to 5. As far as I can tell…you pretty much have to initialize your variables when you define them. Granted I’m only a couple hours into it.
Defining procedures (functions) is done similarly. So say you want to make a function called square to square an input value. It comes out as:
(define (square x) (* x x))
and to use it you would just say (square 5) and get the expected 25.
Because there is no on-the-fly error checking, you don’t have to define things before you use them. So say you wanted to make a sumofsquares function to take two numbers and sum the squares. You could do this:
(define (sumofsquares x y) (+ (square x) (square y))) even if you hadn’t defined square yet. Then you define square and you’re good to go. Variable scoping in these cases is local to the define statement.
Scheme does support recursion, my simple test to try it out (I guess I could have just read the next section and seen it, but the example was talking about square roots, and that’s a classic case of recursion when you use Newton’s method…so I tried it out to play).
(define (recursetest x) (if (> x 0) (recursetest (– x 1)) (= x 0)))
I’ve learned a little about string manipulation, but it’s kind of annoying at least where my knowledge stands right now, so I’ll leave that for later.
So that’s basically where I’m standing right now with Scheme. So far, the corporate developer in me wonders how useful this is since I don’t know how to interact with external data, or even compile and reuse code. But I’ll update you on that as I learn it, and at the moment, I’m kinda happy with my progress so far with this completely foreign language.