Racket is an excellent programming language. It’s actually “a programming language programming language” or, in other words, a programming language to create programming languages.

However, to anyone used to Ruby or Python, it seems rather “raw”. At first glance, you have a collections API that’s not really ergonomic, no good date/time API, no multimethods, no static typing (no, wait, that’s actually not a problem)…

At first glance, I said! ;)

When you learn to use the right things™ instead of the first thing you learn™, Racket is a language as pragmatic as any of those cited above.

Few external libraries

As any other language, a few external libraries become “de facto” standard libraries, think OTP for Erlang or ActiveSupport for Ruby.

To install an external library (package) type in the command line:

> raco pkg install the-package-name

Here the list of essential packages for Racket:

  • Threading Macros (package name: threading), by Alexis King. It provides threading operators from Clojure, just easier and more flexible.
  • Gregor (package-name: gregor), by Jon Zeppieri. Excellent date/time library with everything you need. The “period” functions and structs worth it.

If you are feeling fancy, you can use Generic Collections (package-name: collections), by Alexis King. It’s really nice and works like a charm. Also, if you miss ordered hashes, the package Simple, Deterministic Dictionaries (package name: ddict), by Andrew Kent, is an excellent alternative.

Using the right functions

Most of the time, lists and hashmaps will do what you need. However, sooner or later you will need vectors or more sofisticated data structures. Then, things become ugly.

Just avoid to use specific list and hashmap functions. Abuse comprehensions, prefer dictionary interface and, above all, use sequence interface.

Also, if you are not fond of “string=?” try “equal?”. It works for strings, numbers, lists, hashes and a lot of other things.

Finally, get a good grasp of Generic Interfaces and Pattern Matching. They are very powerful and you are not going to miss multimethods if you understand them.

A helper function or two

Often you have a function that’s pretty much what you need, but you don’t like its name or arguments.

For example: sequence-ref and sequence-tail are useful, but I’d rather have “sequence-first” and “sequence-rest”, so I can skip the extra “position” argument.

No problem, just define them:

(define (sequence-first seq) (sequence-ref seq 0))
(define (sequence-rest seq) (sequence-tail seq 0))

Or, if you are using threading macros:

(define sequence-first (λ~> (sequence-ref 0)))

Actually, I redefine “first” and “rest” in terms of sequence. It’s far more ergonomic than the original “first” and “rest” (which work only for lists).

(define first (λ~> (sequence-ref 0)))
(define rest (λ~> (sequence-tail 0)))

Also, it’s possible to rename functions as you require them. That means it’s possible to forget the standard “map” function (that also works only for lists), and replace it by “sequence-map”.

(require (rename-in racket/sequence [sequence-map map]))

Yes, I rename a lot of functions in favor of the ones that use generic interfaces. Just be aware it can be a little confusing to anyone not used to your code.

Final notes

Racket is awesome in day-by-day programming and it’s getting better as time passes. Plus, it has A LOT of really useful things you can’t easily find in other languages, start with macros and plots (far better than “matplotlib”, IMHO), if you want a glimpse of them.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store