Permalink
Browse files

Initial commit.

  • Loading branch information...
0 parents commit 646a1afacb21a566d15e53fe93c212da926f7336 @Hexstream committed Oct 29, 2012
Showing with 222 additions and 0 deletions.
  1. +3 −0 .gitignore
  2. +129 −0 README
  3. +22 −0 UNLICENSE
  4. +15 −0 incognito-keywords.asd
  5. +44 −0 main.lisp
  6. +9 −0 package.lisp
@@ -0,0 +1,3 @@
+*.fasl
+*.*~
+#*
129 README
@@ -0,0 +1,129 @@
+Project's home: http://www.hexstreamsoft.com/projects/incognito-keywords/
+
+
+incognito-keywords introduces a new kind of keyword that looks just
+like any non-keyword symbol and allows safe usage of convenient but
+clashy symbol names by multiple libraries without conflicts through
+sharing. Some names that might benefit are (alist blist plist macro
+operator index &doc &decl &rest+ &destructure &ignored &ignorable).
+
+
+Some hypothetical examples
+--------------------------
+
+incognito keywords, or "ikeywords" for short, are useful targets for
+various kinds of dispatching.
+
+(define (macro my-macro) ...) ; MACRO being an ikeyword
+
+;; blends much better with:
+(define (variable my-variable) ...) ; VARIABLE is exported from CL.
+
+;; than would:
+(define (:macro my-macro))
+
+;; And the following:
+(define (macro my-macro) ...) ; MACRO a normal symbol
+;; would very likely result in symbol conflicts.
+
+(map 'alist ...) ; ALIST being an ikeyword
+
+;; INDEX, &IGNORED and PLIST being ikeywords
+(do-for ((i (index :from 1))
+ (((&ignored key) value) (plist my-plist)))
+ ...)
+
+(ikeywords:defpackage #:do-for.ikeywords
+ (:export #:index
+ #:&ignored
+ #:plist
+ ...))
+
+(defpackage #:do-for-user-package
+ (:use #:cl #:do-for-ikeywords)
+ (:import-from #:do-for #:do-for))
+
+(locate 'macro "my-macro")
+
+In the examples above, DEFINE, MAP, DO-FOR and LOCATE could come from
+different libraries by different authors. If they all use ikeywords as
+appropriate, then their users can use all these libraries from one
+package without symbol conflicts!
+
+
+API
+---
+
+Usage of incognito-keywords is very easy!
+
+First of all, in the way of packages there's the INCOGNITO-KEYWORDS
+package, which is also nicknamed IKEYWORDS. It exports the functions
+PACKAGE and ENSURE and the macro DEFPACKAGE. These symbols should be
+explicitly qualified. For example, ikeywords:defpackage instead of
+(:use #:ikeywords) or (:import-from #:ikeywords #:defpackage).
+
+ikeywords live in the IKEYWORD package and are typically created
+implicitly with ikeywords:defpackage, but it's also possible to create
+some dynamically with ikeywords:ensure.
+
+
+macro DEFPACKAGE name &rest options => new-or-redefined-package
+
+ A very simplified version of cl:defpackage dedicated to creation of
+ "ikeyword packages". The syntax is just like cl:defpackage, except
+ that only the :export and :documentation options are supported. The
+ package will implicitly use the IKEYWORD package. All the symbol
+ names in :export clauses will be passed to ENSURE.
+
+ It's possible to obtain a list of all ikeyword packages with:
+ (package-used-by-list (ikeywords:package))
+
+
+function ENSURE name => new-or-existing-ikeyword
+
+ If NAME already names an ikeyword (a symbol in the IKEYWORD
+ package), then return that ikeyword.
+
+ Else, create the ikeyword (interning a symbol with that name in the
+ IKEYWORD package), immediately export it (from the IKEYWORD
+ package), then return the new ikeyword.
+
+ Attempting to create an ikeyword with the name of one of the 978
+ symbols in the COMMON-LISP package is an error, as this would almost
+ inevitably result in symbol conflicts, which would defeat the whole
+ point of ikeywords!
+
+
+function PACKAGE => ikeyword-package
+ This convenience function simply returns the IKEYWORD package.
+ Basically equivalent to (find-package '#:ikeyword).
+
+
+
+Restrictions to avoid definition conflicts
+------------------------------------------
+
+incognito-keywords' reason to exist is to allow libraries to make use
+of some very desirable symbol names, while avoiding the excessive
+symbol conflicts this would normally incur. HOWEVER, INCORRECT USAGE
+OF THIS LIBRARY COULD ACTUALLY INCREASE (DEFINITION) CONFLICTS. So
+please carefully read and understand the following:
+
+Libraries should not create global definitions for Common Lisp
+functions, macros, SETF expanders, etc. on ikeywords, as any two
+libraries that do this can't be safely loaded in the same image.
+
+However, if a library creates a new kind of definition in another
+"namespace", then this library can safely create such definitions on
+these symbols. However, if that library exports a way to create such
+definitions, then users of that library can't safely create such
+definitions on ikeywords.
+
+For this reason, libraries in this situation should provide any
+appropriate definitions on ikeywords using their new exported
+definition mechanisms, and prohibit their users, through mechanism
+and/or policy, from providing any new definitions on those ikeywords.
+
+
+This library is in the Public Domain.
+See the UNLICENSE file for details.
@@ -0,0 +1,22 @@
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,15 @@
+(asdf:defsystem #:incognito-keywords
+
+ :author "Jean-Philippe Paradis <hexstream@gmail.com>"
+
+ ;; See the UNLICENSE file for details.
+ :license "Public Domain"
+
+ :description "incognito-keywords introduces a new kind of keyword that looks just like any non-keyword symbol and allows safe usage of convenient but clashy symbol names by multiple libraries without conflicts through sharing. Some names that might benefit are (alist blist plist macro operator index &doc &decl &rest+ &destructure &ignored &ignorable)."
+
+ :depends-on (#:map-bind)
+
+ :version "1.0"
+ :serial cl:t
+ :components ((:file "package")
+ (:file "main")))
@@ -0,0 +1,44 @@
+(in-package #:incognito-keywords)
+
+(defvar *%package*
+ (or (find-package '#:ikeyword)
+ (make-package '#:ikeyword :use nil)))
+
+(defvar *%cl-package* (find-package '#:cl))
+
+(declaim (inline package))
+(defun package ()
+ *%package*)
+
+(defun ensure (name)
+ (setf name (string name))
+ (when (find-symbol name *%cl-package*)
+ (error "Can't create an ikeyword named ~S ~
+ since a symbol with that name already exists ~
+ in the ~A package."
+ name (package-name *%cl-package*)))
+ (let* ((ikeyword-package (package))
+ (symbol (intern name ikeyword-package)))
+ (export symbol ikeyword-package)
+ symbol))
+
+(defmacro defpackage (name &rest options)
+ (let* ((docstring nil)
+ (exported
+ (map-bind (mapcan) ((option options))
+ (destructuring-bind (operator &rest arguments) option
+ (ecase operator
+ (:export (copy-seq arguments))
+ (:documentation
+ (prog1 nil
+ (destructuring-bind (docstring-option) arguments
+ (check-type docstring-option string)
+ (if docstring
+ (error "Multiple :documentation options in ~S."
+ options)
+ (setf docstring docstring-option))))))))))
+ `(progn
+ (mapcar #'ensure ',exported)
+ (cl:defpackage ,name
+ (:use #:ikeyword)
+ (:export ,@exported)))))
@@ -0,0 +1,9 @@
+(cl:defpackage #:incognito-keywords
+ (:nicknames #:ikeywords)
+ (:use #:cl)
+ (:import-from #:map-bind #:map-bind)
+ (:shadow #:package
+ #:defpackage)
+ (:export #:package
+ #:ensure
+ #:defpackage))

0 comments on commit 646a1af

Please sign in to comment.