169 lines
6.1 KiB
HTML
169 lines
6.1 KiB
HTML
<!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> [<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"> ¶</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 <class>
|
|
(make-vtable
|
|
(string-append standard-vtable-fields "pwpwpw")
|
|
(lambda (x port)
|
|
(format port "<<class> ~a>" (class-name x)))))
|
|
|
|
(define (class? x)
|
|
(and (struct? x)
|
|
(eq? (struct-vtable x) <class>)))
|
|
</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 <class>
|
|
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) "pw"))))
|
|
|
|
(define (field-index class field)
|
|
(list-index (class-fields class) field))
|
|
|
|
(define (print-instance x port)
|
|
(format port "<~a" (class-name (struct-vtable x)))
|
|
(for-each (lambda (field idx)
|
|
(format port " ~a: ~a" field (struct-ref x idx)))
|
|
(class-fields (struct-vtable x))
|
|
(iota (length (class-fields (struct-vtable x)))))
|
|
(format port ">"))
|
|
</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 <surface> #f
|
|
width height)
|
|
|
|
(define-class <window> <surface>
|
|
x y)
|
|
</pre></div>
|
|
|
|
<p>And finally, make an instance:
|
|
</p>
|
|
<div class="example">
|
|
<pre class="example-preformatted">(make-struct/no-tail <window> 400 300 10 20)
|
|
⇒ <<window> width: 400 height: 300 x: 10 y: 20>
|
|
</pre></div>
|
|
|
|
<p>And that’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> [<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>
|