1
0
Fork 0
cl-sites/guile.html_node/Slot-Options.html

298 lines
16 KiB
HTML
Raw Normal View History

2024-12-17 12:49:28 +01:00
<!DOCTYPE html>
<html>
<!-- Created by GNU Texinfo 7.1, https://www.gnu.org/software/texinfo/ -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!-- This manual documents Guile version 3.0.10.
Copyright (C) 1996-1997, 2000-2005, 2009-2023 Free Software Foundation,
Inc.
Copyright (C) 2021 Maxime Devos
Copyright (C) 2024 Tomas Volf
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
copy of the license is included in the section entitled "GNU Free
Documentation License." -->
<title>Slot Options (Guile Reference Manual)</title>
<meta name="description" content="Slot Options (Guile Reference Manual)">
<meta name="keywords" content="Slot Options (Guile Reference Manual)">
<meta name="resource-type" content="document">
<meta name="distribution" content="global">
<meta name="Generator" content=".texi2any-real">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link href="index.html" rel="start" title="Top">
<link href="Concept-Index.html" rel="index" title="Concept Index">
<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
<link href="GOOPS.html" rel="up" title="GOOPS">
<link href="Slot-Description-Example.html" rel="next" title="Slot Description Example">
<link href="Instance-Creation.html" rel="prev" title="Instance Creation">
<style type="text/css">
<!--
a.copiable-link {visibility: hidden; text-decoration: none; line-height: 0em}
div.example {margin-left: 3.2em}
span:hover a.copiable-link {visibility: visible}
strong.def-name {font-family: monospace; font-weight: bold; font-size: larger}
ul.mark-bullet {list-style-type: disc}
-->
</style>
<link rel="stylesheet" type="text/css" href="https://www.gnu.org/software/gnulib/manual.css">
</head>
<body lang="en">
<div class="section-level-extent" id="Slot-Options">
<div class="nav-panel">
<p>
Next: <a href="Slot-Description-Example.html" accesskey="n" rel="next">Illustrating Slot Description</a>, Previous: <a href="Instance-Creation.html" accesskey="p" rel="prev">Instance Creation and Slot Access</a>, Up: <a href="GOOPS.html" accesskey="u" rel="up">GOOPS</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html" title="Index" rel="index">Index</a>]</p>
</div>
<hr>
<h3 class="section" id="Slot-Options-1"><span>8.4 Slot Options<a class="copiable-link" href="#Slot-Options-1"> &para;</a></span></h3>
<p>When specifying a slot (in a <code class="code">(define-class &hellip;)</code> form),
various options can be specified in addition to the slot&rsquo;s name. Each
option is specified by a keyword. The list of possible keywords is
as follows.
</p>
<dl class="first-deffn">
<dt class="deffn" id="index-_0023_003ainit_002dvalue"><span class="category-def">slot option: </span><span><strong class="def-name">#:init-value</strong> <var class="def-var-arguments">init-value</var><a class="copiable-link" href="#index-_0023_003ainit_002dvalue"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-_0023_003ainit_002dform"><span class="category-def">slot option: </span><span><strong class="def-name">#:init-form</strong> <var class="def-var-arguments">init-form</var><a class="copiable-link" href="#index-_0023_003ainit_002dform"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-_0023_003ainit_002dthunk"><span class="category-def">slot option: </span><span><strong class="def-name">#:init-thunk</strong> <var class="def-var-arguments">init-thunk</var><a class="copiable-link" href="#index-_0023_003ainit_002dthunk"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-_0023_003ainit_002dkeyword"><span class="category-def">slot option: </span><span><strong class="def-name">#:init-keyword</strong> <var class="def-var-arguments">init-keyword</var><a class="copiable-link" href="#index-_0023_003ainit_002dkeyword"> &para;</a></span></dt>
<dd><p>These options provide various ways to specify how to initialize the
slot&rsquo;s value at instance creation time.
<a class="index-entry-id" id="index-default-slot-value"></a>
</p>
<p><var class="var">init-value</var> specifies a fixed initial slot value (shared across all
new instances of the class).
</p>
<p><var class="var">init-thunk</var> specifies a thunk that will provide a default value for
the slot. The thunk is called when a new instance is created and should
return the desired initial slot value.
</p>
<p><var class="var">init-form</var> specifies a form that, when evaluated, will return
an initial value for the slot. The form is evaluated each time that
an instance of the class is created, in the lexical environment of the
containing <code class="code">define-class</code> expression.
</p>
<p><var class="var">init-keyword</var> specifies a keyword that can be used to pass an
initial slot value to <code class="code">make</code> when creating a new instance.
</p>
<p>Note that, since an <code class="code">init-value</code> value is shared across all
instances of a class, you should only use it when the initial value is
an immutable value, like a constant. If you want to initialize a slot
with a fresh, independently mutable value, you should use
<code class="code">init-thunk</code> or <code class="code">init-form</code> instead. Consider the following
example.
</p>
<div class="example">
<pre class="example-preformatted">(define-class &lt;chbouib&gt; ()
(hashtab #:init-value (make-hash-table)))
</pre></div>
<p>Here only one hash table is created and all instances of
<code class="code">&lt;chbouib&gt;</code> have their <code class="code">hashtab</code> slot refer to it. In order
to have each instance of <code class="code">&lt;chbouib&gt;</code> refer to a new hash table, you
should instead write:
</p>
<div class="example">
<pre class="example-preformatted">(define-class &lt;chbouib&gt; ()
(hashtab #:init-thunk make-hash-table))
</pre></div>
<p>or:
</p>
<div class="example">
<pre class="example-preformatted">(define-class &lt;chbouib&gt; ()
(hashtab #:init-form (make-hash-table)))
</pre></div>
<p>If more than one of these options is specified for the same slot, the
order of precedence, highest first is
</p>
<ul class="itemize mark-bullet">
<li><code class="code">#:init-keyword</code>, if <var class="var">init-keyword</var> is present in the options
passed to <code class="code">make</code>
</li><li><code class="code">#:init-thunk</code>, <code class="code">#:init-form</code> or <code class="code">#:init-value</code>.
</li></ul>
<p>If the slot definition contains more than one initialization option of
the same precedence, the later ones are ignored. If a slot is not
initialized at all, its value is unbound.
</p>
<p>In general, slots that are shared between more than one instance are
only initialized at new instance creation time if the slot value is
unbound at that time. However, if the new instance creation specifies
a valid init keyword and value for a shared slot, the slot is
re-initialized regardless of its previous value.
</p>
<p>Note, however, that the power of GOOPS&rsquo; metaobject protocol means that
everything written here may be customized or overridden for particular
classes! The slot initializations described here are performed by the least
specialized method of the generic function <code class="code">initialize</code>, whose
signature is
</p>
<div class="example">
<pre class="example-preformatted">(define-method (initialize (object &lt;object&gt;) initargs) ...)
</pre></div>
<p>The initialization of instances of any given class can be customized by
defining a <code class="code">initialize</code> method that is specialized for that class,
and the author of the specialized method may decide to call
<code class="code">next-method</code> - which will result in a call to the next less
specialized <code class="code">initialize</code> method - at any point within the
specialized code, or maybe not at all. In general, therefore, the
initialization mechanisms described here may be modified or overridden by
more specialized code, or may not be supported at all for particular
classes.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-_0023_003agetter"><span class="category-def">slot option: </span><span><strong class="def-name">#:getter</strong> <var class="def-var-arguments">getter</var><a class="copiable-link" href="#index-_0023_003agetter"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-_0023_003asetter"><span class="category-def">slot option: </span><span><strong class="def-name">#:setter</strong> <var class="def-var-arguments">setter</var><a class="copiable-link" href="#index-_0023_003asetter"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-_0023_003aaccessor"><span class="category-def">slot option: </span><span><strong class="def-name">#:accessor</strong> <var class="def-var-arguments">accessor</var><a class="copiable-link" href="#index-_0023_003aaccessor"> &para;</a></span></dt>
<dd><p>Given an object <var class="var">obj</var> with slots named <code class="code">foo</code> and <code class="code">bar</code>, it
is always possible to read and write those slots by calling
<code class="code">slot-ref</code> and <code class="code">slot-set!</code> with the relevant slot name; for
example:
</p>
<div class="example">
<pre class="example-preformatted">(slot-ref <var class="var">obj</var> 'foo)
(slot-set! <var class="var">obj</var> 'bar 25)
</pre></div>
<p>The <code class="code">#:getter</code>, <code class="code">#:setter</code> and <code class="code">#:accessor</code> options, if
present, tell GOOPS to create generic function and method definitions
that can be used to get and set the slot value more conveniently.
<var class="var">getter</var> specifies a generic function to which GOOPS will add a
method for getting the slot value. <var class="var">setter</var> specifies a generic
function to which GOOPS will add a method for setting the slot value.
<var class="var">accessor</var> specifies an accessor to which GOOPS will add methods for
both getting and setting the slot value.
</p>
<p>So if a class includes a slot definition like this:
</p>
<div class="example">
<pre class="example-preformatted">(c #:getter get-count #:setter set-count #:accessor count)
</pre></div>
<p>GOOPS defines generic function methods such that the slot value can be
referenced using either the getter or the accessor -
</p>
<div class="example">
<pre class="example-preformatted">(let ((current-count (get-count obj))) ...)
(let ((current-count (count obj))) ...)
</pre></div>
<p>- and set using either the setter or the accessor -
</p>
<div class="example">
<pre class="example-preformatted">(set-count obj (+ 1 current-count))
(set! (count obj) (+ 1 current-count))
</pre></div>
<p>Note that
</p>
<ul class="itemize mark-bullet">
<li>with an accessor, the slot value is set using the generalized
<code class="code">set!</code> syntax
</li><li>in practice, it is unusual for a slot to use all three of these options:
read-only, write-only and read-write slots would typically use only
<code class="code">#:getter</code>, <code class="code">#:setter</code> and <code class="code">#:accessor</code> options
respectively.
</li></ul>
<p>The binding of the specified names is done in the environment of the
<code class="code">define-class</code> expression. If the names are already bound (in that
environment) to values that cannot be upgraded to generic functions,
those values are overwritten when the <code class="code">define-class</code> expression is
evaluated. For more detail, see <a class="ref" href="Generic-Function-Internals.html">ensure-generic</a>.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-_0023_003aallocation"><span class="category-def">slot option: </span><span><strong class="def-name">#:allocation</strong> <var class="def-var-arguments">allocation</var><a class="copiable-link" href="#index-_0023_003aallocation"> &para;</a></span></dt>
<dd><p>The <code class="code">#:allocation</code> option tells GOOPS how to allocate storage for
the slot. Possible values for <var class="var">allocation</var> are
</p>
<ul class="itemize mark-bullet">
<li><code class="code">#:instance</code>
<a class="index-entry-id" id="index-_0023_003ainstance"></a>
<p>Indicates that GOOPS should create separate storage for this slot in
each new instance of the containing class (and its subclasses). This is
the default.
</p>
</li><li><code class="code">#:class</code>
<a class="index-entry-id" id="index-_0023_003aclass"></a>
<p>Indicates that GOOPS should create storage for this slot that is shared
by all instances of the containing class (and its subclasses). In other
words, a slot in class <var class="var">C</var> with allocation <code class="code">#:class</code> is shared
by all <var class="var">instance</var>s for which <code class="code">(is-a? <var class="var">instance</var> <var class="var">c</var>)</code>.
This permits defining a kind of global variable which can be accessed
only by (in)direct instances of the class which defines the slot.
</p>
</li><li><code class="code">#:each-subclass</code>
<a class="index-entry-id" id="index-_0023_003aeach_002dsubclass"></a>
<p>Indicates that GOOPS should create storage for this slot that is shared
by all <em class="emph">direct</em> instances of the containing class, and that
whenever a subclass of the containing class is defined, GOOPS should
create a new storage for the slot that is shared by all <em class="emph">direct</em>
instances of the subclass. In other words, a slot with allocation
<code class="code">#:each-subclass</code> is shared by all instances with the same
<code class="code">class-of</code>.
</p>
</li><li><code class="code">#:virtual</code>
<a class="index-entry-id" id="index-_0023_003aslot_002dset_0021"></a>
<a class="index-entry-id" id="index-_0023_003aslot_002dref"></a>
<a class="index-entry-id" id="index-_0023_003avirtual"></a>
<p>Indicates that GOOPS should not allocate storage for this slot. The
slot definition must also include the <code class="code">#:slot-ref</code> and
<code class="code">#:slot-set!</code> options to specify how to reference and set the value
for this slot. See the example below.
</p></li></ul>
<p>Slot allocation options are processed when defining a new class by the
generic function <code class="code">compute-get-n-set</code>, which is specialized by the
class&rsquo;s metaclass. Hence new types of slot allocation can be
implemented by defining a new metaclass and a method for
<code class="code">compute-get-n-set</code> that is specialized for the new metaclass. For
an example of how to do this, see <a class="ref" href="Customizing-Class-Definition.html">Customizing Class Definition</a>.
</p></dd></dl>
<dl class="first-deffn">
<dt class="deffn" id="index-_0023_003aslot_002dref-1"><span class="category-def">slot option: </span><span><strong class="def-name">#:slot-ref</strong> <var class="def-var-arguments">getter</var><a class="copiable-link" href="#index-_0023_003aslot_002dref-1"> &para;</a></span></dt>
<dt class="deffnx def-cmd-deffn" id="index-_0023_003aslot_002dset_0021-1"><span class="category-def">slot option: </span><span><strong class="def-name">#:slot-set!</strong> <var class="def-var-arguments">setter</var><a class="copiable-link" href="#index-_0023_003aslot_002dset_0021-1"> &para;</a></span></dt>
<dd><p>The <code class="code">#:slot-ref</code> and <code class="code">#:slot-set!</code> options must be specified
if the slot allocation is <code class="code">#:virtual</code>, and are ignored otherwise.
</p>
<p><var class="var">getter</var> should be a closure taking a single <var class="var">instance</var> parameter
that returns the current slot value. <var class="var">setter</var> should be a closure
taking two parameters - <var class="var">instance</var> and <var class="var">new-val</var> - that sets the
slot value to <var class="var">new-val</var>.
</p></dd></dl>
</div>
<hr>
<div class="nav-panel">
<p>
Next: <a href="Slot-Description-Example.html">Illustrating Slot Description</a>, Previous: <a href="Instance-Creation.html">Instance Creation and Slot Access</a>, Up: <a href="GOOPS.html">GOOPS</a> &nbsp; [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html" title="Index" rel="index">Index</a>]</p>
</div>
</body>
</html>