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
7.0

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

Danny Yoo <[email protected]>
and Sam Tobin-Hochstadt <[email protected]>

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.

1 Example

The following example shows how one can write unit code that works with both the old and new unit libraries.

(module some-sample-unit-code mzscheme
  (require (planet "version-case.ss" ("dyoo" "version-case.plt" 1))
           (lib "mred.ss" "mred"))
 
 
 
 
  (version-case
   [(version<= (version) "360")
    (printf "old unit code~n")
    (require (lib "tool.ss" "drscheme")
             (lib "unitsig.ss"))
 
    (define [email protected]
      (unit/sig drscheme:tool-exports^
        (import drscheme:tool^)
        (define (phase1)
          (message-box "phase1"))
        (define (phase2)
          (message-box "phase2"))))]
 
   [else
    (printf "new unit code~n")
    (require (lib "tool.ss" "drscheme")
             (lib "unit.ss"))
    (define-unit [email protected]
      (import drscheme:tool^)
      (export drscheme:tool-exports^)
      (define (phase1)
        (message-box "phase1"))
      (define (phase2)
        (message-box "phase2")))]))

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

syntax

(version-case [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, scheme/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 scheme/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.