Different applications may want to use the same symbol to mean different things. To avoid such name clashes we can use compound symbols, which have two string parts: a local name and a namespace URI. The namespace-uri can be any string, but it is recommended that it have the form of an absolute URI. It would be too verbose to write the full URI all the time, so one usually uses a namespace prefix (namespace alias) as a short local alias to refer to a namespace URI.
Compound symbols are usually written using the infix colon operator:
prefix
:
local-name
where prefix
is a namespace alias bound
to some (lexically-known) namespace URI.
Compound symbols are used for namespace-aware XML processing.
A namespace is a mapping from strings to symbols. The string is the local-name of the resulting symbol. A namespace is similar to a Common Lisp package.
A namespace has a namespace-uri, which a string; it is recommended that it have the form of an absolute URI. A namespace may optionally have a prefix, which is a string used when printing out symbols belonging to the namespace. (If you want “equivalent symbols” (i.e. those that have the same local-name and same uri) to be the identical symbol object, then you should use namespaces whose prefix is the empty string.)
Constructor: namespace
name
[prefix
]
Return a namespace with the given
name
andprefix
. If no such namespace exists, create it. Thenamespace-name
is commonly a URI, especially when working with XML, in which case it is called anamespace-uri
. However, any non-empty string is allowed. The prefix can be a string or a simple symbol. (If a symbol is used, then the symbol’s local-name is used.) The default forprefix
is the empty string. Multiple calls with the same arguments will yield the same namespace object.
The reader macro #,namespace
is equivalent to the
namespace
function, but it is invoked at read-time:
#,(namespace "http://www.w3.org/1999/XSL/Transform" xsl) (eq? #,(namespace "foo") (namespace "foo")) ⇒ #t
The form (,#namespace "" "")
returns the default empty namespace,
which is used for simple symbols.
Procedure: namespace-uri
namespace
Return the namespace-uri of the argument
namespace
, as a string.
Procedure: namespace-prefix
namespace
Return the namespace prefix of the argument
namespace
, as a string.
A compound symbol is one that belongs to a namespace other than the default empty namespace, and (normally) has a non-empty namespace uri. (It is possible for a symbol to belong to a non-default namespace and have an empty namespace uri, but that is not recommended.)
Constructor: symbol
local-name
namespace-spec
Constructor: symbol
local-name
[uri
[prefix
]]
Construct a symbol with the given
local-name
and namespace. Ifnamespace-spec
is a namespace object, then find (or, if needed, construct) a symbol with the givenlocal-name
belonging to the namespace. Multiple calls tosymbol
with the same namespace andlocal-name
will yield the same symbol object.If uri is a string (optionally followed by a prefix), then:
(symbol lname uri [prefix])is equivalent to:
(symbol lname (namespace uri [prefix]))Using
#t
for thenamespace-spec
is equivalent to using the empty namespace#,(namespace "")
.Using
#!null
or#f
for thenamespace-spec
creates anuninterned
symbol, which does not belong to any namespace.
Procedure: symbol-local-name
symbol
Return the local name of the argument symbol, as an immutable string. (The string is interned, except in the case of an uninterned symbol.)
Procedure: symbol-prefix
symbol
Return the prefix of the argument symbol, as an immutable (and interned) string.
Procedure: symbol-namespace-uri
symbol
Return the namespace uri of the argument symbol, as an immutable (and interned) string.
Procedure: symbol-namespace
symbol
Return the namespace object (if any) of the argument symbol. Returns
#!null
if the symbol is uninterned.
Procedure: symbol=?
symbol
1
symbol
2
symbol
3
…
Return
#t
if the symbols are equivalent as symbols, i.e., if their local-names and namespace-uris are the same. They may have different values ofsymbol-prefix
andsymbol-namespace
. If a symbol is uninterned (or is#!null
) thensymbol=?
returns the same result aseq?
.
Two symbols are equal?
or eqv?
if they’re symbol=?
.
A namespace is usually referenced using a shorter namespace alias, which is is a lexical definition that binds a namespace prefix to a namespace object (and thus a namespace uri). This allows using compound symbols as identifiers in Scheme programs.
Syntax: define-namespace
name
namespace-name
Defines
name
as a namespace prefix - a lexically scoped "nickname" for the namespace whose full name isnamespace-name
, which should be a non-empty string literal. It is customary for the string have syntactic form of an absolute URI, but any non-empty string is acceptable and is used without further interpretation.Any symbols in the scope of this definitions that contain a colon, and where the part before the colon matches the
name
will be treated as being in the package/namespace whose global unique name is thenamespace-name
.Has mostly the same effect as:
(define-constantname
#,(namespacenamespace-name
)However, using
define-namespace
(rather thandefine-constant
) is recommended if you want to use compound symbols as names of variables, especially local variables, or if you want to quote compound symbols.Note that the prefix is only visible lexically: it is not part of the namespace, or thus indirectly the symbols, and so is not available when printing the symbol. You might consider using
define-xml-namespace
as an alternative.A namespace is similar to a Common Lisp package, and the
namespace-name
is like the name of the package. However, a namespace alias belongs to the lexical scope, while a Common Lisp package nickname is global and belongs to the package itself.If the namespace-name starts with the string
"class:"
, then thename
can be used for invoking Java methods (see Method operations) and accessing fields (see Field operations).You can use a namespace as an abbreviation or renaming of a class name, but as a matter of style
define-alias
is preferred.
Syntax: define-private-namespace
name
namespace-name
Same as
define-namespace
, but the prefixname
is local to the current module.
For example, you might have a set of a geometry definitions
defined under the namespace-uri "http://foo.org/lib/geometry"
:
(define-namespace geom "http://foo.org/lib/geometry") (define (geom:translate x y) (java.awt.geom.AffineTransform:getTranslateInstance x y)) (define geom:zero (geom:translate 0 0)) geom:zero ⇒ AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
You could have some other definitions for complex math:
(define-namespace complex "http://foo.org/lib/math/complex") (define complex:zero +0+0i)
You can use a namespace-value directly in a compound name:
(namespace "http://foo.org/lib/geometry"):zero ⇒ AffineTransform[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]
The variation define-xml-namespace
is used for Creating XML nodes.
Syntax: define-xml-namespace
prefix
"namespace-uri"
Defines a namespace with prefix
prefix
and URInamespace-uri
. This is similar todefine-namespace
but with two important differences:
Every symbol in the namespace automatically maps to an element-constructor-type, as with the
html
namespace.The
prefix
is a component of the namespace object, and hence indirectly of any symbols belongining to the namespace.Thus the definition is roughly equivalent to:
(define-constantname
#,(namespacenamespace-name name
)along with an infinite set of definitions, for every possible
tag
:(define (name:tag
. rest) (apply make-element 'name:tag
rest))
$ kawa --output-format xml #|kawa:1|#(define-xml-namespace na "Namespace1")
#|kawa:2|#(define-xml-namespace nb "Namespace1")
#|kawa:3|#(define xa (na:em "Info"))
#|kawa:4|#xa
<na:em xmlns:na="Namespace1">Info</na:em> #|kawa:5|#(define xb (nb:em "Info"))
#|kawa:6|#xa
<nb:em xmlns:nb="Namespace1">Info</nb:em>
Note that the prefix is part of the qualified name (it is actually part of the namespace object), and it is used when printing the tag. Two qualified names (symbols) that have the same local-name and the same namespace-name are considered equal, even if they have different prefix. You can think of the prefix as annotation used when printing, but not otherwise part of the “meaning” of a compound symbol. They are the same object if they also have the same prefix. This is an important difference from traditional Lisp/Scheme symbols, but it is how XML QNames work.
#|kawa:7|# (instance? xb na:em) true #|kawa:8|# (eq? 'na:em 'nb:em) false #|kawa:9|# (equal? 'na:em 'nb:em) true #|kawa:10|# (eqv? 'na:em 'nb:em) true
(Note that #t
is printed as true
when using XML formatting.)
The predefined html
prefix could be defined thus:
(define-xml-namespace html "http://www.w3.org/1999/xhtml")