Loading main function in Racket

Series: racket February 24, 2014

Updated on Sat, 01 Mar 2014 23:37:57 +0700: Thanks to Takikawa-san (asumu on IRC) for pointing out the use of main submodule. Now all you have to do is to declare a main submodule:

#lang racket

(module+ main
  (displayln "¡Hola mundo!"))

And you can run racket command without any argument to achieve the same effect:

racket a-module.rkt

This is the question I’ve encountered several times helping people learning Racket. The default behavior is a little unexpected, so I think I’d note it here as a short entry for whom it may be of help.

If you’re coming from the Python world, you’d probably write a Python code as followed:

#!/usr/bin/env python

# Some code
# ...

if __name__ == "__main__":
    run_this_module_as_script()

Meaning your Python module could be executed as script. run_this_module_as_script() is called only when this module is treated as script.

The same technique could be performed by Rubyists though it’s highly discouraged since the standard Ruby design pattern is to separate modules and scripts:

#!/usr/bin/env ruby

# Some code
# ...

if __FILE__ == $0
    run_this_module_as_script
end

Let’s get back to Racket. Suppose we have this simple Racket module:

#lang racket

(provide main)

(define (main)
  (displayln "¡Hola mundo!"))

To achieve the same effect, reading racket --help, one might be tempted to use:

racket -m a-module.rkt

to run the main function, which (unexpectedly) fails.

Inexperienced Racket programmers might tell you to remove the #lang line and change it to a require. This works but your file is no longer a module, which most of the time is a horrible idea. If you don’t know what it means, go read Racket references. Unless you know exactly what you’re doing, do NOT write non-module Racket.

Reading carefully, you’d see that the Racket guide shows that for Racket to process other flags, you need to explicitly tell Racket to do so with -t:

racket -tm a-module.rkt

And voilà!

Personally, I think it’s a bad design decision as it surprises new users. Still, that’s how it’s supposed to work for a long time. Behaviors from the Racket world don’t follow other popular languages. Sometimes they’re better, and sometimes they’re worse. Watch out for these moments and always read the documentation carefully.