Gauche enhances Scheme symbols in a couple of ways:
Like Common Lisp, you can create an uninterned symbol, which is
not registered to the internal table, so it is guaranteed not to be eq?
to any other symbols created by string->symbol
or read
.
Since Scheme’s hygienic macro system automatically avoids name collisions, uninterned symbols are less needed than Common Lisp, but it comes handy when you want a unique object with some descriptive name.
A symbol whose name begins with a colon (:
) is automatically
bound to itself in gauche.keyword
module. By importing or inheriting
it, you can use such symbols as if they’re self-evaluating object. They’re
extensively used in Gauche for passing keyword arguments.
• Basic symbols: | ||
• Uninterned symbols: | ||
• Keywords: | ||
• Keyword and symbol integration: |
A class for symbols.
|name|
¶[R7RS] Denotes a symbol that has weird name, including the characters that are not usually allowed in symbols. It can also include hex-escaped characters.
;; A symbol with spaces in its name '|this is a symbol| ⇒ |this is a symbol| ;; Unicode codepoint can be used following backslash-x escape, ;; and terminated by semicolon. '|\x3bb;| ⇒ λ
If the interpreter is running in case-insensitive mode, this syntax can be used to include uppercase characters in a symbol (see Case-sensitivity).
[R7RS base] Returns true if and only if obj is a symbol.
(symbol? 'abc) ⇒ #t (symbol? 0) ⇒ #f (symbol? 'i) ⇒ #t (symbol? '-i) ⇒ #f (symbol? '|-i|) ⇒ #t
[R7RS base]
Every argument must be a symbol. Returns #t
iff
every pair of arguments are eq?
to each other.
[R7RS base] Returns the name of symbol in a string. Returned string is immutable.
(symbol->string 'foo) ⇒ foo
[R7RS base] Returns a symbol whose name is a string string. String may contain weird characters.
(string->symbol "a") ⇒ a (string->symbol "A") ⇒ A (string->symbol "weird symbol name") ⇒ |weird symbol name|
Both symbol and prefix must be symbols.
If the name of prefix matches the beginning part of the
name of symbol, this procedure returns a symbol whose
name is the name of symbol without the matched prefix.
Otherwise, it returns #f
.
(symbol-sans-prefix 'foo:bar 'foo:) ⇒ bar (symbol-sans-prefix 'foo:bar 'baz:) ⇒ #f
Returns a symbol with the name which is a concatenation of string representation of objs.
If the first argument is a boolean, it is recognized as the first form; the first argument specifies whether the resulting symbol is interned or not.
Each other argument is converted to a string as follows:
If it is a keyword, its name (with the preceding :
) is used.
For all other objects, x->string
is used. (The special treatment
of keyword is to keep the consistency before and after
keyword-symbol integration. See Keyword and symbol integration, for
the details.)
This is upper-compatible to Bigloo’s same name procedure, which only allows symbols as the arguments and the result is always interned.
(symbol-append 'ab 'cd) ⇒ abcd (symbol-append 'ab ':c 30) ⇒ ab:c30 (symbol-append #f 'g 100) ⇒ #:g100
#:name
¶Denotes uninterned symbol. Uninterned symbols can be created
by gensym
or string->uninterned-symbol
.
Uninterned symbols are mainly for legacy macros to avoid
variable conflicts. They are not registered in the internal
dictionary, so such symbols with the same name can’t be eq?
.
(eq? '#:foo '#:foo) ⇒ #f (eq? '#:foo 'foo) ⇒ #f
To preserve eq?
-ness of uninterened symbols,
you need to use write-shared
which
shows shared structures.
(write-shared (let1 s '#:foo (list s s))) ⇒ prints (#0=#:foo #0#) (write-shared (let ((s '#:foo) (t '#:foo)) (list s t s t))) ⇒ prints (#0=#:foo #1=#:foo #0# #1#)
[SRFI-258]
Returns #t
if symbol is an interned symbol,
#f
if it is an uninterned symbol. An error is signaled
if symbol is not a symbol.
This is included in SRFI-258 (see srfi.258
- Uninterned symbols (SRFI)).
[SRFI-258]
Like string->symbol
, but the created symbol is uninterned.
(string->uninterned-symbol "a") ⇒ #:a
This is included in SRFI-258 (see srfi.258
- Uninterned symbols (SRFI)).
Returns a fresh, uninterned symbol. The returned symbol can never
be eq?
to other symbol within the process.
If prefix is given, which must be a string, it is used
as a prefix of the name of the generated symbol. It is mainly for
the convenience of debugging.
This is similar to SRFI-258’s generate-uninterned-symbol
(see Uninterned symbols).
Keywords are a subtype of symbols that are automatically bound to itself. It is extensively used in named arguments (keyword arguments), and keyword-value list.
See Making procedures for how Gauche supports keyword
arguments, and let-keywords
macro (Optional argument parsing)
for parsing keyword-value list manually.
NB: Keywords used to be a disjoint type from symbols. We suppored that compatibility mode with a special environment variable up to 0.9.15, but no longer provide that mode. See Keyword and symbol integration, if you need to update your code.
:name
¶Read to a keyword whose name is :name.
Returns #t
if obj is a keyword.
Returns a keyword whose name is name prepended by :
.
The name argument can be a string or a symbol.
(make-keyword "foo") ⇒ :foo (make-keyword 'foo) ⇒ :foo
Returns the name (without the initial :
) of the keyword
keyword, in a string.
(This is mainly to support legacy code written when keywords are disjoint from
symbols.)
(keyword->string :foo) ⇒ "foo"
A useful procedure to extract a value from key-value list. A key-value list kv-list must contains even number of elements; the first, third, fifth … elements are regarded as keys, and the second, fourth, sixth … elements are the values of the preceding keys.
This procedure looks for key from the keys, and if it finds one, it returns the corresponding value. If there are more than one matching keys, the leftmost one is taken. If there is no matching key, it returns fallback if provided, or signals an error otherwise.
It is an error if kv-list is not a proper, even-number element list.
Actually, ‘keywords’ in the keyword-value list and the key argument
need not be a keyword—it can be any Scheme object. Key comparison
is done by eq?
.
This procedure is taken from STk.
(get-keyword :y '(:x 1 :y 2 :z 3)) ⇒ 2 (get-keyword 'z '(x 1 y 2 z 3)) ⇒ 3 (get-keyword :t '(:x 1 :y 2 :z 3)) ⇒ #<error> (get-keyword :t '(:x 1 :y 2 :z 3) #f) ⇒ #f
Like get-keyword
, but fallback is evaluated only
if kv-list does not have key.
Removes all the keys and values from kv-list for
keys that are eq?
to key.
delete-keyword
doesn’t change kv-list, but the returned
list may share the common tail of it.
delete-keyword!
doesn’t allocate, and may destructively
changes kv-list. You still have to use the returned value,
for the original list may not be changed if its first key matches
key.
If there’s no key that matches key, kv-list is returned.
(delete-keyword :y '(:x 1 :y 2 :z 3 :y 4)) ⇒ (:x 1 :z 3)
Similar to delete-keyword
and delete-keyword!
, but
you can specify a list of objects in keys;
when a key in kv-list matches any of keys,
the key and the following value is removed from kv-list.
(delete-keywords '(:x :y) '(:x 1 :y 2 :z 3 :y 4)) ⇒ (:z 3)
• Keyword and symbol integration: |
In older versions of Gauche, keywords are of disjoint type
from symbols, and they are self-evaluating objects.
To maintain the compatibility, the current Gauche makes
symbols that begins with :
automatically bound to itself,
in gauche.keyword
module.
The gauche
module inherits gauche.keyword
, so all the
keyword look like self-evaluating objects.
That allows most legacy Gauche code keep working, but there are some
catches.
(symbol? :key)
used to return #f
, now returns #t
¶keyword?
always returns #t
on keywords, but
if you need to switch behavior depending whether an object is a symbol
or a keyword, you should test keyword-ness first.
;; behaved differently in 0.9.7 and before (cond [(symbol? x) (x-is-symbol)] [(keyword? x) (x-is-keyword)]) ;; works on all versions (cond [(keyword? x) (x-is-keyword)] [(symbol? x) (x-is-symbol)])
In the old versions,
when keywords appear in a pattern of util.match
or syntax-rules
, they only matched to themselves.
In the current version, such keywords in
a pattern are treated as pattern variables, since they are symbols.
;; In the old versions (match '(a b) [(:key z) (list :key z)] [_ "nope"]) ⇒ "nope" ;; In the current version ;; :key is treated just as a pattern variable (match '(a b) [(:key z) (list :key z)] [_ "nope"]) ⇒ (a b)
The same thing happens to the patterns in syntax-rules
.
To make the code work in both versions, explicitly mark the keywords as literals.
match
, quote the keywords you want to be treated as literals.
(match '(a b) [(':key z) (list :key z)] [_ "nope"]) ⇒ "nope"
syntax-rules
, list the keywords as literals.
(syntax-rules (:key) [(_ :key z) (list :key z)]) ;etc.
(display :key)
used to print key
(no colon), while it now
prints :key
.
You can use (display (keyword->string :key))
which prints key
in both versions.
Keywords (symbols beginning with :
) are automatically bound to itself
in the gauche.keyword
module.
Gauche code inherits the gauche
module by default, which inherits
keyword
, so you can see the binding of the keyword by default.
In R7RS code, however, you don’t inherit gauche
,
so symbols beginning with :
are just ordinary symbols by default.
Usually you do (import (gauche base))
to use Gauche built-ins,
and that makes binding of gauche.keyword
available in your
code, too (since gauche.base
inherits gauche.keyword
).
But keep this in mind just in case you want to handle keywords in
your R7RS code separate from Gauche procedures—you have to either say
(import (gauche keyword))
to get just the self-bound keywords,
or quote them.
(import (scheme base))
:foo ⇒ ERROR: unbound variable: :foo
(import (gauche base))
:foo ⇒ :foo
In the following example, the R7RS library foo
imports only
copy-port
from (gauche base)
; in that case,
you have to import (gauche keyword)
separately
in order to use :size
keyword without quoting.
(Or add :size
explicitly in the imported symbol
list of (gauche base)
.)
(define-library (foo) (import (scheme base) (only (gauche base) copy-port) (gauche keyword)) (export cat) (begin (define (cat) (copy-port (current-input-port) (current-output-port) :size 4096))))