You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
typesetting/quad/qtest/mds/running.md

10 KiB

Running and Creating Executables

While developing programs, many Racket programmers use the DrRacket programming environment. To run a program without the development environment, use racket for console-based programs or gracket for GUI programs. This chapter mainly explains how to run racket and gracket.

1 Running `racket` and `gracket`  
  1.1 Interactive Mode            
  1.2 Module Mode                 
  1.3 Load Mode                   
                                  
2 Scripts                         
  2.1 Unix Scripts                
  2.2 Windows Batch Files         
                                  
3 Creating Stand-Alone Executables

1. Running racket and gracket

The gracket executable is the same as racket, but with small adjustments to behave as a GUI application rather than a console application. For example, gracket by default runs in interactive mode with a GUI window instead of a console prompt. GUI applications can be run with plain racket, however.

Depending on command-line arguments, racket or gracket runs in interactive mode, module mode, or load mode.

1.1. Interactive Mode

When racket is run with no command-line arguments (other than confguration options, like -j), then it starts a REPL with a prompt:

Welcome to Racket v7.1.0.6. >

For enhancing your REPL experience, see xrepl; for information on GNU Readline support, see readline.

To initialize the REPLs environment, racket first requires the racket/init module, which provides all of racket, and also installs pretty-print for display results. Finally, racket loads the file reported by (find-system-path 'init-file), if it exists, before starting the REPL.

If any command-line arguments are provided (other than configuration options), add -i or --repl to re-enable the REPL. For example,

  racket -e '(display "hi\n")' -i

displays “hi” on start-up, but still presents a REPL.

If module-requiring flags appear before -i/--repl, they cancel the automatic requiring of racket/init. This behavior can be used to initialize the REPLs environment with a different language. For example,

  racket -l racket/base -i

starts a REPL using a much smaller initial language (that loads much faster). Beware that most modules do not provide the basic syntax of Racket, including function-call syntax and require. For example,

  racket -l racket/date -i

produces a REPL that fails for every expression, because racket/date provides only a few functions, and not the #%top-interaction and #%app bindings that are needed to evaluate top-level function calls in the REPL.

If a module-requiring flag appears after -i/--repl instead of before it, then the module is required after racket/init to augment the initial environment. For example,

  racket -i -l racket/date

starts a useful REPL with racket/date available in addition to the exports of racket.

1.2. Module Mode

If a file argument is supplied to racket before any command-line switch other than configuration options, then the file is required as a module, and unless `-i`/`--repl` is specified, no REPL is started. For example,

  racket hello.rkt

requires the "hello.rkt" module and then exits. Any argument after the file name, flag or otherwise, is preserved as a command-line argument for use by the required module via current-command-line-arguments.

If command-line flags are used, then the -u or --require-script flag can be used to explicitly require a file as a module. The -t or --require flag is similar, except that additional command-line flags are processed by racket, instead of preserved for the required module. For example,

  racket -t hello.rkt -t goodbye.rkt

requires the "hello.rkt" module, then requires the "goodbye.rkt" module, and then exits.

The -l or --lib flag is similar to -t/--require, but it requires a module using a lib module path instead of a file path. For example,

  racket -l raco

is the same as running the raco executable with no arguments, since the raco module is the executables main module.

Note that if you wanted to pass command-line flags to raco above, you would need to protect the flags with a --, so that racket doesnt try to parse them itself:

  racket -l raco -- --help

1.3. Load Mode

The -f or --load flag supports loading top-level expressions in a file directly, as opposed to expressions within a module file. This evaluation is like starting a REPL and typing the expressions directly, except that the results are not printed. For example,

  racket -f hi.rkts

loads "hi.rkts" and exits. Note that load mode is generally a bad idea, for the reasons explained in [missing]; using module mode is typically better.

The -e or --eval flag accepts an expression to evaluate directly. Unlike file loading, the result of the expression is printed, as in a REPL. For example,

  racket -e '(current-seconds)'

prints the number of seconds since January 1, 1970.

For file loading and expression evaluation, the top-level environment is created in the same way for interactive mode: racket/init is required unless another module is specified first. For example,

  racket -l racket/base -e '(current-seconds)'

likely runs faster, because it initializes the environment for evaluation using the smaller racket/base language, instead of racket/init.

2. Scripts

Racket files can be turned into executable scripts on Unix and Mac OS. On Windows, a compatibility layer like Cygwin support the same kind of scripts, or scripts can be implemented as batch files.

2.1. Unix Scripts

In a Unix environment including Linux and Mac OS, a Racket file can be turned into an executable script using the shells #! convention. The first two characters of the file must be #!; the next character must be either a space or /, and the remainder of the first line must be a command to execute the script. For some platforms, the total length of the first line is restricted to 32 characters, and sometimes the space is required.

Use #lang racket/base instead of #lang racket to produce scripts with a faster startup time.

The simplest script format uses an absolute path to a racket executable followed by a module declaration. For example, if racket is installed in "/usr/local/bin", then a file containing the following text acts as a “hello world” script:

#! /usr/local/bin/racket #lang racket/base
"Hello, world!"

In particular, if the above is put into a file "hello" and the file is made executable e.g., with `chmod a+x hello`, then typing ./hello at the shell prompt produces the output "Hello, world!".

The above script works because the operating system automatically puts the path to the script as the argument to the program started by the #! line, and because racket treats a single non-flag argument as a file containing a module to run.

Instead of specifying a complete path to the racket executable, a popular alternative is to require that racket is in the users command path, and then “trampoline” using /usr/bin/env:

#! /usr/bin/env racket #lang racket/base
"Hello, world!"

In either case, command-line arguments to a script are available via current-command-line-arguments:

#! /usr/bin/env racket
#lang racket/base
(printf "Given arguments: ~s\n"
(current-command-line-arguments))

If the name of the script is needed, it is available via (find-system-path 'run-file), instead of via (current-command-line-arguments).

Usually, the best way to handle command-line arguments is to parse them using the command-line form provided by racket. The command-line form extracts command-line arguments from (current-command-line-arguments) by default:

#! /usr/bin/env racket
#lang racket

(define verbose? (make-parameter #f))

(define greeting
(command-line
#:once-each
[("-v") "Verbose mode" (verbose? #t)]
#:args
(str) str))

(printf "~a~a\n"
greeting
(if (verbose?) " to you, too!" ""))

Try running the above script with the --help flag to see what command-line arguments are allowed by the script.

An even more general trampoline uses /bin/sh plus some lines that are comments in one language and expressions in the other. This trampoline is more complicated, but it provides more control over command-line arguments to racket:

#! /bin/sh
#|
exec racket -e '(printf "Running...\n")' -u "$0" ${1+"$@"} |#
#lang racket/base
(printf "The above line of output had been produced via\n") (printf "a use of the -e' flag.\n") (printf "Given arguments: ~s\n" (current-command-line-arguments))`

Note that #! starts a line comment in Racket, and #|...|# forms a block comment. Meanwhile, # also starts a shell-script comment, while exec racket aborts the shell script to start racket. That way, the script file turns out to be valid input to both /bin/sh and racket.

2.2. Windows Batch Files

A similar trick can be used to write Racket code in Windows .bat batch files:

; @echo off
; Racket.exe "%~f0" %* ; exit /b
#lang racket/base
"Hello, world!"

3. Creating Stand-Alone Executables

For information on creating and distributing executables, see

missing