1 #+TITLE: PortaCL: Easing the Creation of CL Portability Libraries 2 3 * Rationale 4 5 Sometimes you want to do something based upon *features*. Often, that results 6 in lots of reader conditionals, and a final reader conditional duplicating and 7 negating all previous conditionals. Ew! 8 9 * API 10 11 ** ASDF Components: port-file, port-module 12 13 It's not uncommon for a portability library to include something like: 14 :(:file 15 : #+sbcl "port-sbcl" 16 : #+clisp "port-clisp" 17 : #-(or sbcl clisp) (error "not supported")) 18 port-file and port-modules allow you to specify things more like so: 19 :(:port-file "port-~A") 20 or, less positionally, 21 :(:port-file "port-~/implementation/") 22 23 Whether such magical divinations are a good thing is left to you to decide. 24 25 port-file and port-module both also support specification of an :alternate-file, 26 which if specified will be used in place of throwing a not-implemented error. 27 E.g., for use if only one or two implementations need special behavior. 28 29 You can also specify :not-found-condition, the condition type which will be 30 thrown if no applicable file is found. (e.g., you might prefer 'not-supported 31 instead, or 'not-necessary if a missing component is okay). 32 33 ** Condition: not-implemented 34 35 Useful for indicating a particular thing is not implemented. 36 37 This is the default condition thrown when an implementation-specific ASDF 38 component is not found. 39 40 ** Condition: not-supported 41 42 A particular thing is not implemented and won't be. E.g., because the lisp 43 implementation lacks the necessary features. 44 45 ** Condition: not-necessary 46 47 If this thing is not implemented, it didn't need to be. 48 49 When specified as the :not-found-condition in a defsystem form, will cause 50 operations on the component to be considered successful even if the component 51 could not be found. 52 53 ** Function: featurep feature-expression 54 55 Given a feature expression, returns true if that expression is true. 56 57 see [[http://www.lispworks.com/documentation/HyperSpec/Body/24_aba.htm][CLHS 24.1.2.1]] for details. 58 59 ** Macro: define-feature-test test-name-or-names lambda-list [documentation] &body 60 61 Defines a feature test which shall return true if the given feature expressions apply. 62 63 see [[http://repo.kepibu.org/portaCL/feature-tests.lisp][feature-tests.lisp]] for usage examples. 64 65 ** Macro: feature-cond ([feature-conditional] [clause]+)* 66 67 A macro version of #+foo (thing) #+bar (thing2) #-(or foo bar) (no-thing), with 68 all the caveats and shortcomings that implies. 69 70 ** Macro: feature-ecase ([[feature-conditional] [clause]+]+) 71 72 feature-case, except always includes a final (error 'not-implemented). 73 74 * Future Ideas 75 76 ** ASDF component enhancements 77 *** platform / operating system 78 79 It might be useful to also offer up the operating system for interpolation into 80 port-files. (e.g., via ~/platform/ or ~/operating-system/). 81 82 *** shared-implementation support 83 84 It might also be useful to offer a way to specify that certain implementations 85 should be treated just like another implementation. E.g., 86 :(:port-file "port-~a" :treat-as (:ecl :sbcl)) 87 could be used by usocket, instead of futzing with :alternate-file. 88 89 ** Other porting styles? 90 91 Per-file implementation is not the only possible or used porting approach. 92 Perhaps some others should also be supported? 93 94 * SLIME's defimplementation 95 * Xach's CLOS-based approach 96 * Any others? 97 98 * Bugs 99 100 * ASDF systems sometimes try to recursively load themselves a couple 101 hundred times. (Though I've seen that even without loading portaCL, so 102 may not be entirely my bug...) 103 * Constructs similar to the ones below will result in an incorrect 104 package-error: 105 :(list #+(or) #+package:notexported a b c) 106 :(list #+(or) #+notapackage:foo a b c) 107 NOTE: this bug is shared by the standard readers of at least SBCL, 108 Clisp, and Lispworks; but not by Allegro. 109 110 * see also 111 112 [[http://www.cliki.net/trivial-features][trivial-features]] 113 smooths out the unnecessary differences between implementation *features* 114 [[http://common-lisp.net/project/alexandria/][alexandria]] 115 implements a #'featurep which exactly matches that used by the standard's 116 #+/#- readmacros. 117 [[http://common-lisp.net/project/cl-syntax-sugar/][cl-syntax-sugar]] 118 Offers a feature-case reader which is almost certainly more useful than 119 portaCL's feature-cond macro.