A keyword is a sort of a special symbol that is automatically quoted. It is extensively used in pass-by-name arguments (keyword arguments), and keyword-value list.
See Making Procedures for how Gauche supports keyword
let-keywords macro (Optional argument parsing)
for parsing keyword-value list manually.
Unlike Common Lisp, keywords and symbols have been distinct types in
Gauche. Since it isn’t conformant to R7RS, in which symbols can begin
:, we’re moving on to integrate keywords and symbols—
that is, a keyword will be evaluated as an identifier, just like symbols,
but just happens to have itself as a value.
The integration may break the backward compatibility, we haven’t
turned it on by default.
When you set the environment variable
keywords become a subtype of symbols;
Our plan is to make keywords as a subtype of symbols by default
in near future. So we urge developers to test their libraries and
GAUCHE_KEYWORD_IS_SYMBOL to make sure the change won’t
break them. See Keyword and symbol integration,
for the hints to keep the compatibility.
Read to a keyword whose name is name. (Note that the preceding ’:’ is not a part of the keyword’s name.)
#t if obj is a keyword.
Returns a keyword whose name is name, which can be can be a string or a symbol.
(make-keyword "foo") ⇒ :foo (make-keyword 'foo) ⇒ :foo
Returns the name of the keyword keyword, in a string.
(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
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
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
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)
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 future versions of Gauche, keywords will become symbols,
automatically bound to itself by default.
On the surface it won’t make much difference;
you can write a keyword
:key, which evaluates to itself; so you
can pass and receive keyword arguments just like as they are now. You will
be able to use
:key as variables, e.g.
(define :key 3),
which changes the value of
:key in your module,
but that isn’t allowed in the current version of Gauche and it will be
upper-compatible change. (We assume you know what you’re doing
if you redefine keywords; still the effect stays local in your module
and other module that import yours.)
However, there are several subtle points that do make difference, that would break backward compatibility unless you code carefully. We explain here how to write code that works in the current Gauche and will keep working after we make the change.
You can test if your library/application works after the change,
by setting the environment variable
(symbol? :key)that returns
#fnow, will return
You will still be able to distinguish keywords by
if you need to switch behavior depending whether an object is a symbol
or a keyword, you have to test keyword-ness first.
;; will break (cond [(symbol? x) (x-is-symbol)] [(keyword? x) (x-is-keyword)]) ;; will work on both versions (cond [(keyword? x) (x-is-keyword)] [(symbol? x) (x-is-symbol)])
In the current version,
when keywords appear in a pattern of
syntax-rules, they only match to themselves.
After we make keywords as a subtype of symbols, such keywords in
a pattern are treated as pattern variables, just like symbols.
;; In the current version (match '(a b) [(:key z) (list :key z)] [_ "nope"]) ⇒ "nope" ;; After keyword symbol integration; ;; :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
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.
As of Gauche 0.9.5,
match warns if you have unquoted
keywords in match patterns.
(display :key) prints
key (no colon), while it will
:key in future.
You can use
(display (keyword->string :key)) which prints
in both versions.
After integration, keywords (i.e. symbols that begins with
:) are automatically bound to itself,
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
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
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
(gauche base); in that case,
you have to import
(gacueh keyword) separately
in order to use
:size keyword without quoting.
:size explicitly in the imported symbol
(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))))