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.
Keywords used to be a disjoint type from symbols.
Since it isn’t conformant to R7RS, in which symbols can begin
with :
, we’ve introduced two modes since 0.9.5; keywords
can be a disjoint type of its own, or it can be a subtype of symbols.
The behavior can be switched by environment variables. If the environment
variable GAUCHE_KEYWORD_DISJOINT
is defined when gosh
starts
up, keywords and symbols are disjoint. Otherwise, if the environment
variable GAUCHE_KEYWORD_IS_SYMBOL
is defined, keywords are
a subtype of symbols.
The default behavior when neither environment variables are defined
has been switched since 0.9.8. GAUCHE_KEYWORD_DISJOINT
was assumed
in 0.9.7 and before, while GAUCHE_KEYWORD_IS_SYMBOL
is assumed
in 0.9.8 and after.
Most typical code run in either mode, but there can be some code that behaves differently. See Keyword and symbol integration, for effect of the change.
In future we’ll stop supporting GAUCHE_KEYWORD_DISJOINT
,
so we recommend you to ensure applications to run on the current
default mode.
: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.
(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.
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 as they used to be.
If you use :key
as variables, however, e.g. (define :key 3)
,
the value of :key
in your module changes
(it won’t affect other modules, which refer to the binding of :key
in gauche.keyword
module).
However, there are several subtle points that do make difference, that breaks compatibility of legacy code. We explain here how to change the code that works in both ways.
If you find a problem in new mode and want to get the old behavior
until you change the code, you can set the environment variable
GAUCHE_KEYWORD_DISJOINT.
(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.
As of Gauche 0.9.5, match
warns if you have unquoted
keywords in match patterns.
(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))))