1
0
Fork 0
cl-sites/guile.html_node/Vtable-Example.html

170 lines
6.1 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>Vtable Example (Guile Reference Manual)</title>
<meta name="description" content="Vtable Example (Guile Reference Manual)">
<meta name="keywords" content="Vtable Example (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="Structures.html" rel="up" title="Structures">
<link href="Meta_002dVtables.html" rel="prev" title="Meta-Vtables">
<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}
-->
</style>
<link rel="stylesheet" type="text/css" href="https://www.gnu.org/software/gnulib/manual.css">
</head>
<body lang="en">
<div class="subsubsection-level-extent" id="Vtable-Example">
<div class="nav-panel">
<p>
Previous: <a href="Meta_002dVtables.html" accesskey="p" rel="prev">Meta-Vtables</a>, Up: <a href="Structures.html" accesskey="u" rel="up">Structures</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>
<h4 class="subsubsection" id="Vtable-Example-1"><span>6.6.18.5 Vtable Example<a class="copiable-link" href="#Vtable-Example-1"> &para;</a></span></h4>
<p>Let us bring these points together with an example. Consider a simple
object system with single inheritance. Objects will be normal
structures, and classes will be vtables with three extra class fields:
the name of the class, the parent class, and the list of fields.
</p>
<p>So, first we need a meta-vtable that allocates instances with these
extra class fields.
</p>
<div class="example">
<pre class="example-preformatted">(define &lt;class&gt;
(make-vtable
(string-append standard-vtable-fields &quot;pwpwpw&quot;)
(lambda (x port)
(format port &quot;&lt;&lt;class&gt; ~a&gt;&quot; (class-name x)))))
(define (class? x)
(and (struct? x)
(eq? (struct-vtable x) &lt;class&gt;)))
</pre></div>
<p>To make a structure with a specific meta-vtable, we will use
<code class="code">make-struct/no-tail</code>, passing it the computed instance layout and
printer, as with <code class="code">make-vtable</code>, and additionally the extra three
class fields.
</p>
<div class="example">
<pre class="example-preformatted">(define (make-class name parent fields)
(let* ((fields (compute-fields parent fields))
(layout (compute-layout fields)))
(make-struct/no-tail &lt;class&gt;
layout
(lambda (x port)
(print-instance x port))
name
parent
fields)))
</pre></div>
<p>Instances will store their associated data in slots in the structure: as
many slots as there are fields. The <code class="code">compute-layout</code> procedure
below can compute a layout, and <code class="code">field-index</code> returns the slot
corresponding to a field.
</p>
<div class="example">
<pre class="example-preformatted">(define-syntax-rule (define-accessor name n)
(define (name obj)
(struct-ref obj n)))
;; Accessors for classes
(define-accessor class-name (+ vtable-offset-user 0))
(define-accessor class-parent (+ vtable-offset-user 1))
(define-accessor class-fields (+ vtable-offset-user 2))
(define (compute-fields parent fields)
(if parent
(append (class-fields parent) fields)
fields))
(define (compute-layout fields)
(make-struct-layout
(string-concatenate (make-list (length fields) &quot;pw&quot;))))
(define (field-index class field)
(list-index (class-fields class) field))
(define (print-instance x port)
(format port &quot;&lt;~a&quot; (class-name (struct-vtable x)))
(for-each (lambda (field idx)
(format port &quot; ~a: ~a&quot; field (struct-ref x idx)))
(class-fields (struct-vtable x))
(iota (length (class-fields (struct-vtable x)))))
(format port &quot;&gt;&quot;))
</pre></div>
<p>So, at this point we can actually make a few classes:
</p>
<div class="example">
<pre class="example-preformatted">(define-syntax-rule (define-class name parent field ...)
(define name (make-class 'name parent '(field ...))))
(define-class &lt;surface&gt; #f
width height)
(define-class &lt;window&gt; &lt;surface&gt;
x y)
</pre></div>
<p>And finally, make an instance:
</p>
<div class="example">
<pre class="example-preformatted">(make-struct/no-tail &lt;window&gt; 400 300 10 20)
&rArr; &lt;&lt;window&gt; width: 400 height: 300 x: 10 y: 20&gt;
</pre></div>
<p>And that&rsquo;s that. Note that there are many possible optimizations and
feature enhancements that can be made to this object system, and the
included GOOPS system does make most of them. For more simple use
cases, the records facility is usually sufficient. But sometimes you
need to make new kinds of data abstractions, and for that purpose,
structs are here.
</p>
</div>
<hr>
<div class="nav-panel">
<p>
Previous: <a href="Meta_002dVtables.html">Meta-Vtables</a>, Up: <a href="Structures.html">Structures</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>