chickadee » feature-test » #?

#?read
#?(FEATURE CONSEQUENT ALTERNATE)

Perform an if-then test at read-time on FEATURE, expanding to CONSEQUENT if FEATURE is present or ALTERNATE if absent. FEATURE may be any feature expression permitted in a cond-expand, such as windows or (and windows macosx).

#? can be used inside macros because it is expanded when the macro form is read, prior to macroexpansion. It expands correctly irrespective of Chicken version.

#? is similar to the Common Lisp idiom

#+FEATURE CONSEQUENT
#-FEATURE ALTERNATE

and, in Chicken versions >= 4.6.7 it is exactly equivalent, even inside macro bodies. However, in previous versions #+ and #- will not work properly inside macros; see #+ for further explanation.

An example of #? which is essentially equivalent to cond-expand:

(define af/unix #?(AF_UNIX _af_unix #f))
;; is basically the same as
(define af/unix (cond-expand (AF_UNIX _af_unix) (else #f)))

A more powerful example of #?:

(cond ((eq? x _af_inet) "internet address family")
      #?(AF_UNIX
         ((eq? x _af_unix) "unix address family")
         (#f))
      (else "unknown address family")

which, if AF_UNIX is a registered feature, expands into

(cond ((eq? x _af_inet) "internet address family")
      ((eq? x _af_unix) "unix address family")
      (else "unknown address family")

and if not, expands into

(cond ((eq? x _af_inet) "internet address family")
      (#f)
      (else "unknown address family")

In the latter case, the false clause cannot succeed and is hopefully optimized out by the compiler. #+ would be more appropriate, but requires Chicken >= 4.6.7. This technique doesn't work with every macro, but you do what you can.