version-case:   conditionally compile code based on current version number
1 Example
2 Usage
version-case
version<
version<=
version=
version>
version>=
3 Gotchas
4 Thanks
8.12

version-case: conditionally compile code based on current version number🔗ℹ

Danny Yoo <dyoo@hashcollision.org>
and Sam Tobin-Hochstadt <samth@racket-lang.org>

Source code can be found at: https://github.com/samth/version-case.

This library provides support for conditionally compiling code based on the version of Racket. One common application of this module is to write compatibility bindings.

The library is supported for Racket 6.0 and later.

1 Example🔗ℹ

The following example shows how one can use web-server/dispatchers/dispatch-logresp, a web server logging facility that supports both request and response logging, if the current Racket version is at least 8.6, while falling back to web-server/dispatchers/dispatch-log, another web server logging facility that only supports request logging, when the current Racket version is less than 8.6.

(require version-case
         (prefix-in sequencer: web-server/dispatchers/dispatch-log)
         (for-syntax racket/base))
(version-case
  [(version< (version) "8.6")
   (require (prefix-in log: web-server/dispatchers/dispatch-log))
   (define-syntax-rule (with-logging (options ...) dispatcher ...)
     (sequencer:make (log:make options ...) dispatcher ...))]
  [else
   (require (prefix-in log: web-server/dispatchers/dispatch-logresp))
   (define-syntax-rule (with-logging (options ...) dispatcher ...)
     (log:make options ... (sequencer:make dispatcher ...)))])
 
...
(serve #:dispatch
       (with-logging ()
         ...))

Another simple example:
#lang racket/base
(require version-case
         (for-syntax racket/base))
(printf "~a~n" (version-case [(version<= (version) "4")
                              'huh?]
                             [else
                              'ok]))

2 Usage🔗ℹ

 (require version-case) package: version-case

syntax

(version-case clause ...)

 
clause = [test code ...]
  | [else code ...]
version-case is a macro that expands out to one of the code blocks, depending on which test succeeds first. The test expression is evaluated at compile-time. Some version-comparing functions are available for convenience.

procedure

(version< v1 v2)  boolean?

  v1 : string?
  v2 : string?
Returns true if v1 is less than v2.

procedure

(version<= v1 v2)  boolean?

  v1 : string?
  v2 : string?
Returns true if v1 is less than or equal to v2.

procedure

(version= v1 v2)  boolean?

  v1 : string?
  v2 : string?
Returns true if v1 is equal to v2.

procedure

(version> v1 v2)  boolean?

  v1 : string?
  v2 : string?
Returns true if v1 is greater than v2.

procedure

(version>= v1 v2)  boolean?

  v1 : string?
  v2 : string?
Returns true if v1 is greater than or equal to v2.

3 Gotchas🔗ℹ

The tests are done at compile time. If the language of your module doesn’t include compile-time bindings for function application, you may see funny error messages. For example, racket/base doesn’t automatically provide the necessary compile-time bindings, so if you use version-case with it, you also need to do a (require (for-syntax racket/base)).

4 Thanks🔗ℹ

Special thanks to Carl Eastlund providing the implementation that doesn’t use eval, and for feedback. Thanks also to Ambjorn Elder for noticing a bug regarding the use of syntax-case within a version-case’s body.