emacs.d/clones/lispcookbook.github.io/cl-cookbook/misc.html
2022-08-04 11:37:48 +02:00

212 lines
8.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta name="generator" content=
"HTML Tidy for HTML5 for Linux version 5.2.0">
<title>Miscellaneous</title>
<meta charset="utf-8">
<meta name="description" content="A collection of examples of using Common Lisp">
<meta name="viewport" content=
"width=device-width, initial-scale=1">
<link rel="icon" href=
"assets/cl-logo-blue.png"/>
<link rel="stylesheet" href=
"assets/style.css">
<script type="text/javascript" src=
"assets/highlight-lisp.js">
</script>
<script type="text/javascript" src=
"assets/jquery-3.2.1.min.js">
</script>
<script type="text/javascript" src=
"assets/jquery.toc/jquery.toc.min.js">
</script>
<script type="text/javascript" src=
"assets/toggle-toc.js">
</script>
<link rel="stylesheet" href=
"assets/github.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<h1 id="title-xs"><a href="index.html">The Common Lisp Cookbook</a> &ndash; Miscellaneous</h1>
<div id="logo-container">
<a href="index.html">
<img id="logo" src="assets/cl-logo-blue.png"/>
</a>
<div id="searchform-container">
<form onsubmit="duckSearch()" action="javascript:void(0)">
<input id="searchField" type="text" value="" placeholder="Search...">
</form>
</div>
<div id="toc-container" class="toc-close">
<div id="toc-title">Table of Contents</div>
<ul id="toc" class="list-unstyled"></ul>
</div>
</div>
<div id="content-container">
<h1 id="title-non-xs"><a href="index.html">The Common Lisp Cookbook</a> &ndash; Miscellaneous</h1>
<!-- Announcement we can keep for 1 month or more. I remove it and re-add it from time to time. -->
<p class="announce">
📹 <a href="https://www.udemy.com/course/common-lisp-programming/?couponCode=6926D599AA-LISP4ALL">NEW! Learn Lisp in videos and support our contributors with this 40% discount.</a>
</p>
<p class="announce-neutral">
📕 <a href="index.html#download-in-epub">Get the EPUB and PDF</a>
</p>
<div id="content"
<p><a name="opt"></a></p>
<h2 id="re-using-complex-data-structures">Re-using complex data structures</h2>
<p>Sometimes you want your functions to behave in a functional way, i.e. return <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_f.htm#fresh">fresh</a> results without side effects, sometimes you want them to re-use and modify existing data in a destructive way - consider the difference between <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_append.htm"><code>append</code></a> and <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_nconc.htm"><code>nconc</code></a> for an example.</p>
<p>Well, you can have your cake and eat it too, by using optional (or keyword) parameters. Heres an example: Lets assume youre writing a function <code>complex-matrix-stuff</code> which takes two matrices <code>m1</code> and <code>m2</code> as its arguments and computes and returns a resulting matrix the size of which depends on <code>m1</code> and <code>m2</code>, i.e. for a fresh result youll need an empty matrix whichll be created by, say, <code>(make-appropriate-result-matrix-for m1 m2)</code>.</p>
<p>The classical textbook way to implement this function will more or less look like this:</p>
<pre><code class="language-lisp">(defun complex-matrix-stuff (m1 m2)
(let ((result (make-appropriate-result-matrix-for m1 m2)))
;; ... compute storing the results in RESULT
result))
</code></pre>
<p>And youll use it like this:</p>
<pre><code class="language-lisp">(setq some-matrix (complex-matrix-stuff A B))
</code></pre>
<p>But why not write it like so:</p>
<pre><code class="language-lisp">(defun complex-matrix-stuff (m1 m2
&amp;optional
(result
(make-appropriate-result-matrix-for m1 m2)))
;; ... compute storing the results in RESULT
result)
</code></pre>
<p>Now you have it both ways. You can still “make up results” on the fly as in:</p>
<pre><code class="language-lisp">(setq some-matrix (complex-matrix-stuff A B))
</code></pre>
<p>But you can also (destructively) re-use previously allocated matrices:</p>
<pre><code class="language-lisp">(complex-matrix-stuff A B some-appropriate-matrix-I-built-before)
</code></pre>
<p>Or use your function like this:</p>
<pre><code class="language-lisp">(setq some-other-matrix
(complex-matrix-stuff A B some-appropriate-matrix-I-built-before))
</code></pre>
<p>in which case youll end up with:</p>
<pre><code class="language-lisp">* (eq some-other-matrix some-appropriate-matrix-I-built-before)
T
</code></pre>
<p><a name="adjust"></a></p>
<h2 id="using-adjust-array-instead-of-consing-up-new-sequences-with-subseq">Using <code>ADJUST-ARRAY</code> instead of consing up new sequences with <code>SUBSEQ</code></h2>
<p>Most CL functions operating on sequences will accept <code>start</code> and <code>end</code> keywords so you can make them operate on a sub-sequence without actually creating it, i.e. instead of</p>
<pre><code class="language-lisp">(count #\a (subseq long-string from to))
</code></pre>
<p>you should of course use</p>
<pre><code class="language-lisp">(count #\a long-string :start from :end to)
</code></pre>
<p>whichll yield the same result but not create an unnecessary intermediate sub-sequence.</p>
<p>However, sometimes it looks like you cant avoid creating new data. Consider a hash table the keys of which are strings. If the key youre looking for is a sub-string of another string youll most likely end up with</p>
<pre><code class="language-lisp">(gethash (subseq original-string from to)
hash-table)
</code></pre>
<p>But you dont have to. You can create <em>one</em> <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_d.htm#displaced_array">displaced</a> string and reuse it multiple times with <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_adjust.htm"><code>adjust-array</code></a>:</p>
<pre><code class="language-lisp">(let ((substring (make-array 0
:element-type 'character
:displaced-to ""
:displaced-index-offset 0)))
;; more code
(gethash
(adjust-array substring (- to from)
:displaced-to original-string
:displaced-index-offset from)
hash-table)
;; even more code
)
</code></pre>
<p class="page-source">
Page source: <a href="https://github.com/LispCookbook/cl-cookbook/blob/master/misc.md">misc.md</a>
</p>
</div>
<script type="text/javascript">
// Don't write the TOC on the index.
if (window.location.pathname != "/cl-cookbook/") {
$("#toc").toc({
content: "#content", // will ignore the first h1 with the site+page title.
headings: "h1,h2,h3,h4"});
}
$("#two-cols + ul").css({
"column-count": "2",
});
$("#contributors + ul").css({
"column-count": "4",
});
</script>
<div>
<footer class="footer">
<hr/>
&copy; 2002&ndash;2021 the Common Lisp Cookbook Project
</footer>
</div>
<div id="toc-btn">T<br>O<br>C</div>
</div>
<script text="javascript">
HighlightLisp.highlight_auto({className: null});
</script>
<script type="text/javascript">
function duckSearch() {
var searchField = document.getElementById("searchField");
if (searchField && searchField.value) {
var query = escape("site:lispcookbook.github.io/cl-cookbook/ " + searchField.value);
window.location.href = "https://duckduckgo.com/?kj=b2&kf=-1&ko=1&q=" + query;
// https://duckduckgo.com/params
// kj=b2: blue header in results page
// kf=-1: no favicons
}
}
</script>
<script async defer data-domain="lispcookbook.github.io/cl-cookbook" src="https://plausible.io/js/plausible.js"></script>
</body>
</html>