Climbing Mount SICP

I have decided to focus more on Clojure, and start working on How To Design Programs (aka “HtDP”), and then onto Structure and Interpretation of Computer Programs (aka “SICP”). HtDP is written by the founders of the Racket project, and SICP uses Scheme (one of the authors, Gerald Sussman, invented Scheme along with Guy L. Steele; I think Scheme was Steele’s PhD thesis).

I looked one last time into The Reasoned Schemer. I changed to a different KanRen library. More of the examples worked, but this book is really not coming together for me as quickly as the other ones did. I think I will put aside the “Little” books, at least for the time being. I think it might be time to get ready to climb Mount SICP.

Many people have said that SICP is a good way to “level up” (as the gamer kids put it). Many people have said it gave them something like the famous “Lisp enlightenment”, that it altered their perception of how to make software and made them better. As the Teach Yourself CS site put it: Because SICP is unique in its ability—at least potentially—to alter your fundamental beliefs about computers and programming. Not everybody will experience this. Some will hate the book, others won’t get past the first few pages. But the potential reward makes it worth trying.

SICP is an introductory CS text used at MIT. The general consensus is that you will get more out of it if you have been in software development for a few years. It is a bit much for most people right off the bat. I have been through Simply Scheme, which states in the last chapter that it is intended to prepare you for SICP. HtDP was made as an alternative to SICP; the authors felt that SICP requires a lot of higher math, and if they made a less math-heavy alternative they could introduce more people to CS and help them become better programmers.

One of the authors of Simply Scheme wrote an essay entitled “Why Structure and Interpretation of Computer Programs matters”. He states that unlike other introductory textbooks, SICP does not spend a lot of time on the syntax of a specific language, but instead teaches broader concepts. Someone at the local Clojure meetup once said to me that if you can work through the problems in SICP, “you can solve any problem with parentheses”. In other words, you learn how to design programs.

A few years back, MIT (and a few other schools using SICP) replaced Scheme and SICP with other texts that use Python. Sussman said there were a few reasons for this. One is that he and Harold Abelson (one of the other co-authors of SICP) were tired of teaching the course after more than 15 or so years. Another reason is that SICP was designed for programmers who would make systems from the ground of using smaller components. Now a lot of programming is just linking or wiring together components that are black boxes. Sussman called it “programming by poking”. You could contrast this with the SICP style of “analysis-by-synthesis”. The site Lambda The Ultimate has a post with a link to a now-extinct blog post, but there is a quote that summarizes the ideas nicely. There is also a link to a thread on Hacker News. This have come up several times on Hacker News and Reddit.

There is a section in the preface to Simply Scheme that covers this:

There are two schools of thought about teaching computer science. We might caricature the two views this way:

  • The conservative view: Computer programs have become too large and complex to encompass in a human mind. Therefore, the job of computer science education is to teach people how to discipline their work in such a way that 500 mediocre programmers can join together and produce a program that correctly meets its specification.
  • The radical view: Computer programs have become too large and complex to encompass in a human mind. Therefore, the job of computer science education is to teach people how to expand their minds so that the programs can fit, by learning to think in a vocabulary of larger, more powerful, more flexible ideas than the obvious ones. Each unit of programming thought must have a big payoff in the capabilities of the program.

(I think you could also call these the “business mindset”, and the “engineering mindset”: Do things in a way that the suits think they understand, or actually knowing what you are doing.)

Per a comment on the Lambda The Ultimate post, one of the authors of HtDP said that other departments sent students to their CS intro course to learn how to think. That is where I want to go. I feel that “programming by poking” is what I have been doing. I feel like I should be better at this than I am, and that there has to be a better way of doing things. Where “progress” isn’t just learning yet another vendor’s product.

Why not level up? Why settle for poor understanding? As one of the commenters on Hacker News put it: What about the people who make the black boxes? How do you know they know what they are doing? If you could learn to solve any problem with parentheses, why wouldn’t you?

The obligatory links (I have not gone through most of these):

You’re welcome.

Image from “Evangelia quattuor, pars”, an 11th century manuscript housed at the Bibliothèque nationale de France. Source gallica.bnf.fr / BnF; image assumed allowed under Public Domain.

2021-04-11 Update

I know I said I was going to focus on Clojure, but I looked at some other things in the past week.

I am looking into some Amazon certification for AWS. There is a big push to get certified at my current employer, and I would like to do something different.

I started the org-mode tutorial from Udemy.

I also looked at The Seasoned Schemer. I think that having already gone through Simply Scheme I may have gotten some of the concepts. A lot of it deals with recursion.

Chapter 12 dealt with “letrec”. letrec is like let, but instead of binding a name to a variable or data, you can bind a name to a function, and you can call that function recursively.

One thing this can allow you to do is it can relieve you of the need to call a helper function. In Simply Scheme, I made all the functions tail-recursive. To do this, you usually need a parameter that is the “accumulator” or the output (see this answer on Stack Overflow or my post here).

In The Seasoned Schemer, they use letrec for functions in which one argument does not change and one does, such as checking if an atom is a member of a list, or performing a union of two lists:

(define (union-letrec s1 s2)
  (letrec
      ([U (lambda (set-1)
            (cond [(null? set-1) s2]
                  [(ss-sc:member? (car set-1) s2) (U (cdr set-1))]
                  [else (cons (car set-1) (U (cdr set-1)))]))])
    (U s1)))

I know I think the whole argument about Lisp/Scheme being hard to read because of all the parentheses is usually exaggerated, here I think for these letrec examples there might be something to it. These were hard to type correctly from the book. For example, the internal function has to be after the “(set-1)” which is the argument to the “lambda”, but before the closing parens for “lambda”. And the call to the internal function has to be before the closing call to “letrec”. You can have multiple functions defined in a “letrec”, and your call to the internal functions can be in a cond.

A helper function to do the actual work with tail-recursion might be more lines of code, but I think it is easier to understand.

Chapter 13 is about let/cc, combining let with “call-with-current-continuation”. I think some people consider this Scheme’s defining feature.

They have a function rember-upto-last which takes an atom and a list of atoms and removes everything in the list before the last instance of the atom as well as the atom.

Here it is:

(define (rember-upto-last a lat)
  (let/cc skip
      (letrec
          ([R (lambda (lat)
                (cond [(null? lat) '()]
                      [(ss-sc:equal5? (car lat) a) 
                       (skip (R (cdr lat)))
                       ; (R (cdr lat))
                       ]
                      [else (cons (car lat) (R (cdr lat)))]))])
          (R lat))))

Here is a tail-recursive version:

(define (rember-upto-last-r a lat)
  (let/cc skip
      (letrec
          ([R (lambda (lat outp)
                (ss-sc:display-all "Calling R w/lat: " lat 
                                   " and outp: " outp)
                (cond [(null? lat) (reverse outp)]
                      [(ss-sc:equal5? (car lat) a) 
                         (skip (R (cdr lat) '()))
                         ;(R (cdr lat) '())
                       ]
                      [else (R (cdr lat) (cons (car lat) outp))]))])
        (R lat '()))))

Both of these have a commented out call to “(R (cdr lat)” (with a second arg in the tail-recursive version) below the call to “skip”.[Note 1]. In the tail-recursive version, either  call gives the proper result. In the regular version, we are building our answer through a chain of calls to “cons”. The “skip” eliminates all the pending “cons” calls, and the function is called anew with whatever the then-current values are. In the tail-recursive version, we can get rid of those “pending” values ourselves.

I think Java might get continuations soon.

You’re welcome.

[Note 1]: For some reason, the code formatter I am using does not always color comments correctly. In all variants of Lisp that I have seen, comments start with a semi-colon.

Image from Psalterium Gallicanum with Cantica, a 9th century manuscript from the monastery of St. Gall, housed at Central Library of Zurich. Image from e-Codices. This image is assumed to be allowed under Fair Use.

Chapter 9 of ‘The Little Schemer’

I finally finished chapter 9 of The Little Schemer. This was about partial functions, total functions, and ended with the applicative-order Y combinator.

Frankly, what I understood in this chapter I did not see the point of, and I am not sure there is much point in the parts I do not understand. I think a total function returns a unique value for every input, and partial functions do not. Some of the functions they described as partial sometimes did not return values. Which to me sounds like a badly-designed function.

Maybe Godel’s incompleteness theorem has seeped into our collective consciousness to such a degree that the idea that some functions cannot be computed seems obvious.

Maybe I am not smart enough to be one of those super high-level math/language theory people. I realize I do not have the inclination to do so. I do not have much interest in conjectures about functions that do not return values. I will have to ask a few people I know who have been through SICP if this is the sort of thing in that book. I will finish The Little Schemer and go on to The Seasoned Schemer in a while.

I went through the part about the Y combinator a second time, and I am not too sure I understand it or see the point. Is there a point? According to some guy named Mike, the point of the Y combinator is:  The Y combinator allows us to define recursive functions in computer languages that do not have built-in support for recursive functions, but that do support first-class functions.

Are there languages that fit that description? I did some googling, and I found a Hacker News discussion about “The Why of Y” on Dreamsongs (an interesting website I hope to explore in depth someday). As one commenter points out, the article goes into the How of Y, but never the Why.

The Seasoned Schemer says you only need to understand the first eight chapters of The Little Schemer to go through TSS. So hopefully I should be fine. I was hoping to get through TLS more quickly. I am more busy at work, and chapters 8 and 9 were a lot harder (and had more concepts that were new to me) than the first seven.

I have not gone through these yet, but here are a few more links I found about total and partial functions:

 

You’re welcome.

Image from World Digital Library, assumed allowed under Fair Use. Image from the Ashburnham Pentateuch, or Tours Pentateuch, a Latin manuscript of the first five books of the Old Testament from the 6th century or 7th century. Its place of origin is unknown.

Update on ‘The Little Schemer’

I am almost through with The Little Schemer. I got through the first seven chapters fairly quickly. There are no exercises per se. They will ask questions, invite you to figure out the answer, and show you. I admit, a few times I peeked, but only after trying to get it myself.

There were a few things in chapter 8 that were mind-bending. One was using higher-order functions for code-reuse.

In chapter 3, the authors introduce a few functions. One is “rember”, which removes an element (or member) from a list:

  (runit:check-equal? (lt-sc:rember 'and '(bacon lettuce and tomato))
                      '(bacon lettuce tomato))

Another is “insertR”, which inserts a new element to the right of an old element in a list:

  (runit:check-equal? (lt-sc:insertR 'topping 
                                     'fudge 
                                     '(ice cream with fudge for dessert))
                      '(ice cream with fudge topping for dessert))

The third is “insertL”, which inserts a new element to the left of an old element:

  (runit:check-equal? (lt-sc:insertL 'topping 
                                     'fudge 
                                     '(ice cream with fudge for dessert))
                      '(ice cream with topping fudge for dessert))

The functions are pretty much identical. In chapter 8, they make a base function, and then make three more to cover the three different requirements.

(define insert-g
  (lambda (seq)
    (lambda (new old l)
      (cond [(null? l) (quote ())]
            ; calling passed seq function
            [(eq? (car l) old) (seq new old (cdr l))] 
            [else (cons (car l) ((insert-g seq) new old (cdr l)))]))))

(define insertL2
  (insert-g (lambda (new old l)
              (cons new (cons old l)))))

It works just like the original:

  (runit:check-equal? (lt-sc:insertL2 'topping 
                                      'fudge 
                                      '(ice cream with fudge for dessert))
                      '(ice cream with topping fudge for dessert))

This reminds me of something that Eric Normand showed in Purely Functional, where he puts anonymous functions in the values of a map. I wrote about that in August of 2018.

The truly mind-bending part was the “collectors”. Dark arts, these are.

They define a function that does the usual removing of members. It takes an additional parameter which is a function that does some calculations/manipulations on the resulting list. But in the recursive calls, the function uses inline lambdas to make additional collections.

Here is their explanation from page 140; the function is (multirember&co a lat f), where “a” is an atom, “lat” is a list of atoms, and “f’ is a function: It looks at every atom of the lat to see whether it is eq? to a. Those atoms that are not are collected in one list ls1 ; the others for which the answer is true are collected in a second list ls2 . Finally, it determines the value of (f ls1 ls2 ).

Here is the multirember&co function:

(define (multirember&co a lat col)
    (cond [(null? lat) (col '() '())]
          [(eq? (car lat) a)
           (multirember&co a (cdr lat)
                           (lambda (newlat seen)
                             (col newlat
                                  (cons (car lat) seen))))]
          [else
           (multirember&co a (cdr lat)
                           (lambda (newlat seen)
                             (col (cons (car lat) newlat)
                                  seen)))]))

Here is the function we will use in our test:

(define (last-friend x y)
  (length x))

The second argument is unused in last-friend. So when you use last-friend, it will count how many elements are not equal to the first argument. If it returned the length of y, it would tell us how many times the first argument is in the list.

Here are the tests in Racket:

  (runit:check-equal? (lt-sc:multirember&co 'tuna
                                            '(strawberries tuna and swordfish)
                                            lt-sc:last-friend)
                      3)
  (runit:check-equal? (lt-sc:multirember&co 'tuna
                                            '(strawberries tuna swordfish tuna shark)
                                            lt-sc:last-friend)
                      3)

Later, they use collectors on functions that work on multi-level lists. There is a recursive call within the collector.

I think I understand this, but I am not entirely sure about it. I was able to figure out some of the collector examples as they went along. Truly this is unholy power.

You’re welcome.

Image from Corpus Agrimensorum Romanorum, a 6th century manuscript on land surveying housed at the Herzog August Library in  Wolfenbüttel. According to Wikipedia, “It is one of the few surviving non-literary and non-religious illuminated manuscripts from late antiquity.” This image is assumed to be allowed under Fair Use.

On To The Little Books

I finished the poker program from Chapter 15 of Simply Scheme, and I finished Chapter 24.

I have decided I am willing to let MengSince1996 be the King of Berkeley, and move on to Daniel Friedman’s “Little” books.

The first is “The Little Schemer“. This seems to deal with recursion. The first sequel is “The Seasoned Schemer“. The co-author of these books is Matthias Felleisen, one of the founders of Racket. On his Northeastern University page, he states that “The Seasoned Schemer” deals with higher-order functions, set! and continuations.

Next is “The Reasoned Schemer“. This bridges functional programming and logic programming. I work with a rules engine in my day job. I wonder if that is what this is about.

The next book is “The Little Prover“. According to the book’s page on the MIT Press site, this book “introduces inductive proofs as a way to determine facts about computer programs.” Honestly, I am not too clear what that means at this point.

The most recent book in the series is “The Little Typer“. For this book, Friedman and co-author David Thrane Christiansen made a language for the book using Racket.

I will probably use Racket for all these books instead of straight Scheme because I want to be able to run a tests and not type and re-type function invocations every time I make a change. In order to use tests, I had to require the R6RS packages into a program using “#lang racket/base”. I do not think there is a way to use the Racket unit test libraries in an R6RS program. So there are a lot of prefixes.

I like prefixes before function names. It is a bit more typing, and maybe it is not as clean, but I like to know where everything is coming from. One of the things that I did not like about Rails was there were no import or require statements. Everything was everywhere. That made tutorials look very interesting, but it was frustrating finding documentation for classes if you wanted to see what else the gems could do.

I plan on getting through these faster than I took to get through Simply Scheme.

See also my mentions of these books in a post from a few years ago.

You’re welcome.

Image from the Tabara Beatus, a 10th century manuscript of ‘Commentary on the Apocalypse‘, written in the 8th century by Beatus of Liébana; image from Spanish Ministry of Culture and Sports, assumed allowed under Fair Use.

2019-08-13: Thoughts On Simply Scheme

I may not finish the rest of Simply Scheme.

Chapter 22 deals with files and I/O, and some of the exercises and examples are not working. Simply Scheme came out just after R5RS, but I cannot find anything about a specific version. It might even be running R4RS.

I guess the I/O functions work differently in different implementations. Or perhaps Racket is handling things differently. My goal of completing 100% of Simply Scheme will not happen.

I do not know what I will do next. The options are: The Little Schemer books, How To Design Programs, climb Mount SICP, or get back to Clojure.

You’re welcome.

Image from ‘Beatus of Navarra’, aka ‘Navarra Codex’, a 12th century manuscript of the 8th century work Commentary on the Apocalypse‘, written in the 8th century by Beatus of Liébana, housed at the Bibliothèque nationale de France (more info in French at this page). Source gallica.bnf.fr / BnF; image assumed allowed under Fair Use.

Spaniards look at this and say, “French manuscripts are okay, but if you want something with intense pictures, you can’t beat us.”

Thoughts On Lisp And Racket

I plan on writing about why I am interested in the Lisp family of languages. It will probably come out in stages.

But first, I will write about some recent events. (This is a bit all over the place.)

A few weeks ago there was a lot of traffic on the Racket Users mailing list about a proposal by Racket core developer Matthew Flatt called “Racket2“. They are thinking about changes, with one goal to increase the user base.

One proposal was to change the syntax and move away from s-expressions. The current syntax would be “#lang racket”, and the new syntax would be “#lang racket2” (or whatever it winds up being called). This has caused a lot of debate.

Some people (including myself) came to Racket because it is part of the Lisp family. And s-expressions are part of that. I have met a lot of people who said that they could do things with Lisp 20, 30 years ago that languages either cannot do today, or could only do recently. Many languages are influenced by Lisp, yet Lisp does not feel the need to be influenced by anybody else. (An exception might be OOP, one of the few ideas that did not start in the Lisp family, and is very easy to implement in Lisp.)

I grew up near Chicago, and the population kept expanding westward. People would complain that their suburb was too crowded, so they would pave over more farmland, and expand the next suburb, and ten years later this would repeat. I always thought that maybe we should learn to design cities and towns better so we don’t cut into our food supply and stop making the same mistakes over and over again. Eventually we will run out of land. Or people will be commuting from the Quad Cities.

I remember when the hot thing was to do Java/Spring/Hibernate. Then Rails came along, and a lot of Java people went to Rails because they could build apps faster. And then they got tired of the magic and the monolith and the lack of multi-threading and now a lot are going to Elixir. Granted, not all Rails people came from Java, and not all of them are going to Elixir, but there are a lot of them who took the Java-Rails-Elixir path. In other words, there are a lot of people who dumped unmanageable apps on other people for the new cool, hip language twice in the span of a decade.[Note 1]

And then there is the JavaScript community. Constantly churning out new frameworks and libraries and entire languages that transpile to JavaScript so they do not have to deal with JavaScript directly. And the whole time Lisp people have been in their corner just doing their thing.

There is a lot of churning in IT/CS, but not a lot of learning. It looks to me like the Lisp community knows something the rest of the world does not. They are not searching for the next hot thing. They seem to understand things on a deeper level than other communities. Perhaps “enlightenment” is not an overwrought term to use.

No other language has people claiming what the Lisp people claim. Many langs claim to be influenced by Lisp, or try to do things that Lisp can do, or do things that started in Lisp (which is just about everything but OOP). But the Lisp crowd doesn’t see a need to be like other languages. It’s like fat people want to date fit people, but fit people do not want to date fat people.

Norvig asks if Lisp is still unique. More languages have features that at some point only existed in Lisp. (Paul Graham also lists some Lisp features.) I get the impression that Norvig thinks that the world does not need Lisp anymore. Perhaps a better interpretation is that a lot of time and energy has gone into re-inventing the wheel.

Granted, maybe this was inevitable. C and UNIX were given away for free, and for a time Lisp was only available on specialized and more expensive hardware.

But if languages are becoming more and more like Lisp, maybe we should just cut to the chase and use some variant of Lisp.

I am one of those people who came to Racket because it is a Lisp. I feel that I should be better at creating/using software and general problem solving than I am, and I guess you could say I am looking for the fabled Lisp enlightenment. Maybe saying Lisp is the language of the gods is overwrought, but nobody ever said that JavaScript made them smarter, or that they learned a lot using anything by Microsoft.

It seems like everybody wants the capabilities that s-expressions give them, without actually using s-expressions. It has been tried, and nobody has been able to get it to work. Even if you could, why bother? Why go through the effort to invent a language that can do the things that Lisp can do? I think it would be easier to just learn to program with s-expressions (which frankly are not as hard as some people seem to think). A lot of the suggested alternatives usually end up looking like Python. If you want to use Python, then go use Python.

There was one person on the Racket users mailing list who wrote that parentheses make his head hurt. He also wrote that he found arguments from “parenthistas” to be condescending. And he is a PhD student in CompSci. Frankly, if you are a PhD student in CS and you do not grasp parentheses, then you deserve condescension. I am not claiming to be the foremost Lisp expert, and I am sure you can find Lisp code that makes my head hurt. But you can find impenetrable code in any language. But in all seriousness, s-expressions just do not seem as hard as some people make them out to be.

In “The Evolution of Lisp“, written around 1993, Richard Gabriel and Guy Steele predicted this would happen: People would suggest alternative syntaxes to Lisp, and the suggestions would be rejected. There have been a couple of SFRIs for this in Scheme. They never seem to go anywhere. From Gabriel and Steele:
On the other hand, precisely because Lisp makes it easy to play with program representations, it is always easy for the novice to experiment with alternative notations. Therefore we expect future generations of Lisp programmers to continue to reinvent Algol-style syntax for Lisp, over and over and over again, and we are equally confident that they will continue, after an initial period of infatuation, to reject it. (Perhaps this process should be regarded as a rite of passage for Lisp hackers.)

I think it should be regarded as an IQ test. People have done this, and it has never caught on. Why will it be different this time? Also: What if the people who are in Racket for the Lispiness leave and you do NOT gain new users?

Back to Racket: What do I think Racket should do to increase its user base?

1. Do something about Dr Racket.
I use racket-mode with emacs, which may not be the most beginner-friendly way to use Racket. But DrRacket looks kind of cartoonish in a way. It’s clean, I’ll grant that. Maybe I am the only person who does not like it. Maybe I expect an IDE to look more like IntelliJ, or Eclipse, or Visual Studio.

2. Focus more on libraries, frameworks, and applications. I read the Racket Manifesto, and I know that it is intended to be “a programming language for creating new programming languages”. But it also claims to have “batteries included”. Which is it?

I know some say language oriented programming is Racket’s strong suit. But to some people, it can make Racket look more cumbersome and less powerful. It is a nice thing to have when you need it, but do you always need it? Why can’t Racket solve problems out of the box? If it is powerful enough to create new languages, then you should be able to do something with plain old Racket.

In other languages, when you ask how to do something, many times you are pointed to a library or framework. In Racket, you might get told to “write a language.” People want to make applications, not languages.

I think one reason Rails was so successful was not just that it had a lot of magic, but that it was a nice default answer. Back then, the major languages for web programming were PHP, where you did have to do everything yourself, or Java, which had (and still has) a lot of frameworks. After Rails came along, if you asked how to make a web application in Ruby, the answer was: Try Rails. It wasn’t the only option, but it was a nice default. I think the Racket community should focus on building libraries, frameworks, and applications that people can use in Racket.

3. Related to the above comment: Does Racket want to be a teaching language? Or a language used by professional developers? Are these two goals possible at the same time?

4. I think being immutable by default is a good idea.

5. Can Racket do more with GPUs? I think these will become more important going forward.

[Note 1] Another thing that bugs me is that for a long time, Java developers said that Java was faster than Ruby, and criticized Ruby for not being able to execute multiple threads. Rails developers responded that the speed of the developer was more important than the speed of the runtime, and that WRT threads, they could just send stuff to a message broker. And unlike Java, Ruby had metaprogramming, which some derided as “magic”; Rails devs said they were just envious.

Now, lots of Rails devs are moving to Elixir because it’s fast, it can handle multiple threads, and a lot of the Rails magic was changing core Ruby classes which caused a lot of problems. In other words, Rails developers left Rails due to the criticisms that they all said were invalid a few years ago.

You’re welcome.

Image from the Beatus of Santo Domingo de Silos, an 11th century manuscript of ‘Commentary on the Apocalypse‘, by the Abbey of Santo Domingo de Silos, the same guys who did ‘Chant‘, original manuscript written in the 8th century by Beatus of Liébana; image from British Library, assumed allowed under Fair Use.

2019-03-14 Update: Simply Scheme, Simply Clojure, Simply Racket

I have been taking a break from Simply Scheme. I got stumped on one of the exercises. I started doing the exercises in Clojure for a couple of reasons. One is that is the most commercially viable Lisp out there right now. Another reason is that I want to run automated tests. I would like to be able to quickly run a function multiple times with different inputs. I was typing and re-typing the same calls over and over. Or I could just use tests.

I do not know how to do tests in Scheme. I was using Chicken Scheme for Simply Scheme. There are a few “eggs” for testing, but the instructions were not that great. Also some of them were not working on the version of Chicken that I was using for Simply Scheme. I use Chicken on Ubuntu and Cygwin, and not directly; they are a bit behind the official version. I did find out recently there is an SFRI for testing. It is implemented by Kawa, so perhaps I could have used Kawa. I do not plan on building any apps with Scheme, or using it long-term. It is just a vehicle for enlightenment. I do not know what the most common test libraries are, and I do not want to spend time on something that I might not be able to use later. Clojure has testing out of the box.

I also started looking into using Racket. I have thought about it before, since there are a lot of language modules for Racket. There is one for Simply Scheme. I also found out about an Emacs mode for Racket. I am just running some tests from some .rkt files, but from what I understand, this is intended to be a replacement for Dr Racket. I do not know how to make an app with Racket, but right now I do not need much. I think I might be better off going with Racket, even if I am using a Scheme language module. While Racket is pretty rare, it is used more than Scheme.

So I have started a project using Racket and the Simply Scheme library to do the Simply Scheme exercises. Maybe someday I will do SICP in Racket, and become a Little, Reasoned or Seasoned Racketeer.

You’re welcome.

Image from ImgFlip, assumed allowed under Fair Use.

Yet Another Change In Plans

I am getting a bit frustrated with Realm Of Racket.

I am going through chapter 8. I downloaded their source from github and tried to run it locally. It does not work for some reason. It works if I clone the repo and run it from there. But it should still run somewhere else. I have the same directory structure as they do. I really don’t feel like debugging it.

I couldn’t get their example from chapter 6 to work either.

I will try to run some Scheme in DrRacket. If that does not go well, I will just go back to Clojure.

You’re welcome.

Back To Racket

I am back to going through Realm Of Racket. I am not doing the challenges. I guess I want enlightenment sooner rather than later. Or just cross this off my list.

I am doing it because I get the impression that it can be hard to get through some of the Scheme books using the Scheme implementations available.

There is one Scheme implementation that looks interesting is Kawa, which is written in Java.

You’re welcome.

Image from the Montpellier Psalter, an 8th Century Carolingian manuscript. Image from Wikimedia, assumed allowed under Fair Use.