code.html 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  3. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  4. <html xmlns="http://www.w3.org/1999/xhtml" lang="English" xml:lang="English">
  5. <head>
  6. <!-- 2023-02-26 So 16:12 -->
  7. <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  8. <meta name="viewport" content="width=device-width, initial-scale=1" />
  9. <title>The Seasoned Schemer Notes</title>
  10. <meta name="author" content="Zelphir Kaltstahl" />
  11. <meta name="generator" content="Org Mode" />
  12. <style>
  13. #content { max-width: 60em; margin: auto; }
  14. .title { text-align: center;
  15. margin-bottom: .2em; }
  16. .subtitle { text-align: center;
  17. font-size: medium;
  18. font-weight: bold;
  19. margin-top:0; }
  20. .todo { font-family: monospace; color: red; }
  21. .done { font-family: monospace; color: green; }
  22. .priority { font-family: monospace; color: orange; }
  23. .tag { background-color: #eee; font-family: monospace;
  24. padding: 2px; font-size: 80%; font-weight: normal; }
  25. .timestamp { color: #bebebe; }
  26. .timestamp-kwd { color: #5f9ea0; }
  27. .org-right { margin-left: auto; margin-right: 0px; text-align: right; }
  28. .org-left { margin-left: 0px; margin-right: auto; text-align: left; }
  29. .org-center { margin-left: auto; margin-right: auto; text-align: center; }
  30. .underline { text-decoration: underline; }
  31. #postamble p, #preamble p { font-size: 90%; margin: .2em; }
  32. p.verse { margin-left: 3%; }
  33. pre {
  34. border: 1px solid #e6e6e6;
  35. border-radius: 3px;
  36. background-color: #f2f2f2;
  37. padding: 8pt;
  38. font-family: monospace;
  39. overflow: auto;
  40. margin: 1.2em;
  41. }
  42. pre.src {
  43. position: relative;
  44. overflow: auto;
  45. }
  46. pre.src:before {
  47. display: none;
  48. position: absolute;
  49. top: -8px;
  50. right: 12px;
  51. padding: 3px;
  52. color: #555;
  53. background-color: #f2f2f299;
  54. }
  55. pre.src:hover:before { display: inline; margin-top: 14px;}
  56. /* Languages per Org manual */
  57. pre.src-asymptote:before { content: 'Asymptote'; }
  58. pre.src-awk:before { content: 'Awk'; }
  59. pre.src-authinfo::before { content: 'Authinfo'; }
  60. pre.src-C:before { content: 'C'; }
  61. /* pre.src-C++ doesn't work in CSS */
  62. pre.src-clojure:before { content: 'Clojure'; }
  63. pre.src-css:before { content: 'CSS'; }
  64. pre.src-D:before { content: 'D'; }
  65. pre.src-ditaa:before { content: 'ditaa'; }
  66. pre.src-dot:before { content: 'Graphviz'; }
  67. pre.src-calc:before { content: 'Emacs Calc'; }
  68. pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
  69. pre.src-fortran:before { content: 'Fortran'; }
  70. pre.src-gnuplot:before { content: 'gnuplot'; }
  71. pre.src-haskell:before { content: 'Haskell'; }
  72. pre.src-hledger:before { content: 'hledger'; }
  73. pre.src-java:before { content: 'Java'; }
  74. pre.src-js:before { content: 'Javascript'; }
  75. pre.src-latex:before { content: 'LaTeX'; }
  76. pre.src-ledger:before { content: 'Ledger'; }
  77. pre.src-lisp:before { content: 'Lisp'; }
  78. pre.src-lilypond:before { content: 'Lilypond'; }
  79. pre.src-lua:before { content: 'Lua'; }
  80. pre.src-matlab:before { content: 'MATLAB'; }
  81. pre.src-mscgen:before { content: 'Mscgen'; }
  82. pre.src-ocaml:before { content: 'Objective Caml'; }
  83. pre.src-octave:before { content: 'Octave'; }
  84. pre.src-org:before { content: 'Org mode'; }
  85. pre.src-oz:before { content: 'OZ'; }
  86. pre.src-plantuml:before { content: 'Plantuml'; }
  87. pre.src-processing:before { content: 'Processing.js'; }
  88. pre.src-python:before { content: 'Python'; }
  89. pre.src-R:before { content: 'R'; }
  90. pre.src-ruby:before { content: 'Ruby'; }
  91. pre.src-sass:before { content: 'Sass'; }
  92. pre.src-scheme:before { content: 'Scheme'; }
  93. pre.src-screen:before { content: 'Gnu Screen'; }
  94. pre.src-sed:before { content: 'Sed'; }
  95. pre.src-sh:before { content: 'shell'; }
  96. pre.src-sql:before { content: 'SQL'; }
  97. pre.src-sqlite:before { content: 'SQLite'; }
  98. /* additional languages in org.el's org-babel-load-languages alist */
  99. pre.src-forth:before { content: 'Forth'; }
  100. pre.src-io:before { content: 'IO'; }
  101. pre.src-J:before { content: 'J'; }
  102. pre.src-makefile:before { content: 'Makefile'; }
  103. pre.src-maxima:before { content: 'Maxima'; }
  104. pre.src-perl:before { content: 'Perl'; }
  105. pre.src-picolisp:before { content: 'Pico Lisp'; }
  106. pre.src-scala:before { content: 'Scala'; }
  107. pre.src-shell:before { content: 'Shell Script'; }
  108. pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
  109. /* additional language identifiers per "defun org-babel-execute"
  110. in ob-*.el */
  111. pre.src-cpp:before { content: 'C++'; }
  112. pre.src-abc:before { content: 'ABC'; }
  113. pre.src-coq:before { content: 'Coq'; }
  114. pre.src-groovy:before { content: 'Groovy'; }
  115. /* additional language identifiers from org-babel-shell-names in
  116. ob-shell.el: ob-shell is the only babel language using a lambda to put
  117. the execution function name together. */
  118. pre.src-bash:before { content: 'bash'; }
  119. pre.src-csh:before { content: 'csh'; }
  120. pre.src-ash:before { content: 'ash'; }
  121. pre.src-dash:before { content: 'dash'; }
  122. pre.src-ksh:before { content: 'ksh'; }
  123. pre.src-mksh:before { content: 'mksh'; }
  124. pre.src-posh:before { content: 'posh'; }
  125. /* Additional Emacs modes also supported by the LaTeX listings package */
  126. pre.src-ada:before { content: 'Ada'; }
  127. pre.src-asm:before { content: 'Assembler'; }
  128. pre.src-caml:before { content: 'Caml'; }
  129. pre.src-delphi:before { content: 'Delphi'; }
  130. pre.src-html:before { content: 'HTML'; }
  131. pre.src-idl:before { content: 'IDL'; }
  132. pre.src-mercury:before { content: 'Mercury'; }
  133. pre.src-metapost:before { content: 'MetaPost'; }
  134. pre.src-modula-2:before { content: 'Modula-2'; }
  135. pre.src-pascal:before { content: 'Pascal'; }
  136. pre.src-ps:before { content: 'PostScript'; }
  137. pre.src-prolog:before { content: 'Prolog'; }
  138. pre.src-simula:before { content: 'Simula'; }
  139. pre.src-tcl:before { content: 'tcl'; }
  140. pre.src-tex:before { content: 'TeX'; }
  141. pre.src-plain-tex:before { content: 'Plain TeX'; }
  142. pre.src-verilog:before { content: 'Verilog'; }
  143. pre.src-vhdl:before { content: 'VHDL'; }
  144. pre.src-xml:before { content: 'XML'; }
  145. pre.src-nxml:before { content: 'XML'; }
  146. /* add a generic configuration mode; LaTeX export needs an additional
  147. (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
  148. pre.src-conf:before { content: 'Configuration File'; }
  149. table { border-collapse:collapse; }
  150. caption.t-above { caption-side: top; }
  151. caption.t-bottom { caption-side: bottom; }
  152. td, th { vertical-align:top; }
  153. th.org-right { text-align: center; }
  154. th.org-left { text-align: center; }
  155. th.org-center { text-align: center; }
  156. td.org-right { text-align: right; }
  157. td.org-left { text-align: left; }
  158. td.org-center { text-align: center; }
  159. dt { font-weight: bold; }
  160. .footpara { display: inline; }
  161. .footdef { margin-bottom: 1em; }
  162. .figure { padding: 1em; }
  163. .figure p { text-align: center; }
  164. .equation-container {
  165. display: table;
  166. text-align: center;
  167. width: 100%;
  168. }
  169. .equation {
  170. vertical-align: middle;
  171. }
  172. .equation-label {
  173. display: table-cell;
  174. text-align: right;
  175. vertical-align: middle;
  176. }
  177. .inlinetask {
  178. padding: 10px;
  179. border: 2px solid gray;
  180. margin: 10px;
  181. background: #ffffcc;
  182. }
  183. #org-div-home-and-up
  184. { text-align: right; font-size: 70%; white-space: nowrap; }
  185. textarea { overflow-x: auto; }
  186. .linenr { font-size: smaller }
  187. .code-highlighted { background-color: #ffff00; }
  188. .org-info-js_info-navigation { border-style: none; }
  189. #org-info-js_console-label
  190. { font-size: 10px; font-weight: bold; white-space: nowrap; }
  191. .org-info-js_search-highlight
  192. { background-color: #ffff00; color: #000000; font-weight: bold; }
  193. .org-svg { }
  194. </style>
  195. </head>
  196. <body>
  197. <div id="content" class="content">
  198. <h1 class="title">The Seasoned Schemer Notes
  199. <br />
  200. <span class="subtitle">Chapter 13</span>
  201. </h1>
  202. <div id="table-of-contents" role="doc-toc">
  203. <h2>Table of Contents</h2>
  204. <div id="text-table-of-contents" role="doc-toc">
  205. <ul>
  206. <li><a href="#prerequisites">1. Prerequisites</a>
  207. <ul>
  208. <li><a href="#prerequisites-y-combinator">1.1. Y-combinator</a></li>
  209. </ul>
  210. </li>
  211. <li><a href="#chapter-13">2. Chapter 13</a>
  212. <ul>
  213. <li><a href="#chapter-13-example">2.1. Example :: Computing the intersection of multiple sets</a>
  214. <ul>
  215. <li><a href="#chapter-13-example-usage">2.1.1. Usage</a></li>
  216. <li><a href="#chapter-13-example-conclusion">2.1.2. Conclusion</a></li>
  217. <li><a href="#chapter-13-example-attempt-fix">2.1.3. Attempt of fixing the issue</a></li>
  218. <li><a href="#chapter-13-example-continuations">2.1.4. Continuations to the rescue</a></li>
  219. <li><a href="#chapter-13-example-optimizations">2.1.5. Further optimization of <code class="src src-scheme">intersect</code> and <code class="src src-scheme">intersectall</code></a></li>
  220. </ul>
  221. </li>
  222. <li><a href="#chapter-13-example-skipping">2.2. Example :: Skipping computation</a></li>
  223. <li><a href="#chapter-13-example-continuations-notes">2.3. Notes about continuations</a>
  224. <ul>
  225. <li><a href="#chapter-13-example-continuations-notes-languages-specifics">2.3.1. Specific language implementations</a></li>
  226. <li><a href="#chapter-13-example-continuations-notes-other-languages">2.3.2. Other languages</a></li>
  227. <li><a href="#chapter-13-example-continuations-notes-other-concepts">2.3.3. Other concepts</a></li>
  228. </ul>
  229. </li>
  230. </ul>
  231. </li>
  232. </ul>
  233. </div>
  234. </div>
  235. <div id="outline-container-prerequisites" class="outline-2">
  236. <h2 id="prerequisites"><span class="section-number-2">1.</span> Prerequisites</h2>
  237. <div class="outline-text-2" id="text-prerequisites">
  238. <div class="org-src-container">
  239. <pre class="src src-scheme" id="orgb8927a7">(define atom?
  240. (λ (x)
  241. (and (not (pair? x))
  242. (not (null? x)))))
  243. </pre>
  244. </div>
  245. <p>
  246. In theory we could define other things as numbers, for example church numerals.
  247. </p>
  248. <div class="org-src-container">
  249. <pre class="src src-scheme" id="orga569744">(define one?
  250. (λ (x)
  251. (= x 1)))
  252. </pre>
  253. </div>
  254. <div class="org-src-container">
  255. <pre class="src src-scheme" id="org6b7d346">(define pick
  256. (λ (n lat)
  257. (cond
  258. [(one? n) (car lat)]
  259. [else
  260. (pick (- n 1) (cdr lat))])))
  261. </pre>
  262. </div>
  263. </div>
  264. <div id="outline-container-prerequisites-y-combinator" class="outline-3">
  265. <h3 id="prerequisites-y-combinator"><span class="section-number-3">1.1.</span> Y-combinator</h3>
  266. <div class="outline-text-3" id="text-prerequisites-y-combinator">
  267. <p>
  268. In the first book the Y-combinator was derived. It is again:
  269. </p>
  270. <div class="org-src-container">
  271. <pre class="src src-scheme" id="orgb70ef1b">(define Y
  272. (λ (proc)
  273. ((λ (f) (f f))
  274. (λ (f)
  275. (proc
  276. (λ (x) ((f f) x)))))))
  277. </pre>
  278. </div>
  279. </div>
  280. </div>
  281. </div>
  282. <div id="outline-container-chapter-13" class="outline-2">
  283. <h2 id="chapter-13"><span class="section-number-2">2.</span> Chapter 13</h2>
  284. <div class="outline-text-2" id="text-chapter-13">
  285. <p>
  286. Chapter 13 deals with continuations. It shows situations, in which they can be useful. Situations, which before were not encountered. A typical situation is a recursive function, that builds up a result in recursive calls, but only after having potentially built up part of the result, notices that previously built up parts are not needed. This makes sense, when the check for some condition, that tells, that the parts are not needed is too expensive to be done in the average case.
  287. </p>
  288. </div>
  289. <div id="outline-container-chapter-13-example" class="outline-3">
  290. <h3 id="chapter-13-example"><span class="section-number-3">2.1.</span> Example :: Computing the intersection of multiple sets</h3>
  291. <div class="outline-text-3" id="text-chapter-13-example">
  292. <p>
  293. One example the book uses is a function which computes the set intersection between multiple sets, represented by lists, given as a list of lists.
  294. </p>
  295. <div class="org-src-container">
  296. <pre class="src src-scheme" id="orgca3199e">(define intersect
  297. (λ (set1 set2)
  298. (letrec ([member?
  299. (λ (elem lst)
  300. (member elem lst))]
  301. [intersect-inner
  302. (λ (set1°)
  303. (cond
  304. [(null? set1°) '()]
  305. [(member? (car set1°) set2)
  306. (cons (car set1°)
  307. (intersect-inner (cdr set1°)))]
  308. [else
  309. (intersect-inner (cdr set1°))]))])
  310. (intersect-inner set1))))
  311. </pre>
  312. </div>
  313. <div class="org-src-container">
  314. <pre class="src src-scheme" id="orgc64d883">
  315. (define intersectall
  316. (λ (lsts)
  317. (letrec ([intersectall-inner
  318. (λ (lsts°)
  319. (cond
  320. [(null? (cdr lsts°)) (car lsts°)]
  321. [else
  322. (intersect (car lsts°)
  323. (intersectall-inner (cdr lsts°)))]))])
  324. (cond
  325. [(null? lsts) '()]
  326. [else
  327. (intersectall-inner lsts)]))))
  328. </pre>
  329. </div>
  330. </div>
  331. <div id="outline-container-chapter-13-example-usage" class="outline-4">
  332. <h4 id="chapter-13-example-usage"><span class="section-number-4">2.1.1.</span> Usage</h4>
  333. <div class="outline-text-4" id="text-chapter-13-example-usage">
  334. <div class="org-src-container">
  335. <pre class="src src-scheme" id="orgd9b039e">
  336. (simple-format
  337. #t "~a\n"
  338. (intersect '(a b c) '(c d e)))
  339. (simple-format
  340. #t "~a\n"
  341. (intersectall '((a b c)
  342. (c d e)
  343. (f c))))
  344. (simple-format
  345. #t "~a\n"
  346. (intersectall '((a b c)
  347. (c d e)
  348. ()
  349. (f g c))))
  350. </pre>
  351. </div>
  352. <pre class="example" id="org2f8dd34">
  353. (c)
  354. (c)
  355. ()
  356. </pre>
  357. </div>
  358. </div>
  359. <div id="outline-container-chapter-13-example-conclusion" class="outline-4">
  360. <h4 id="chapter-13-example-conclusion"><span class="section-number-4">2.1.2.</span> Conclusion</h4>
  361. <div class="outline-text-4" id="text-chapter-13-example-conclusion">
  362. <p>
  363. The problem with this definition of <code>intersectall</code> is, that even if a list in the call:
  364. </p>
  365. <div class="org-src-container">
  366. <pre class="src src-scheme" id="org7bffcc3">...
  367. (intersect (car lsts°)
  368. (intersectall-inner (cdr lsts°)))
  369. ...
  370. </pre>
  371. </div>
  372. <p>
  373. in <code>intersectall-inner</code> is empty, <code>intersectall-inner</code> in its iterations continues to call <code>intersect</code> with that empty list as a first argument. Continuing to call <code>intersect</code> is unnecessary work. Any intersection with an empty set will result in an empty set, in this case represented by an empty list. Any in previous iterations already computed partial intersection is useless as well. In fact the longer the already computed intersection is, the more work <code>intersect</code> will perform, because it iterates over the set members, checking, whether they are <code>member?</code> of the other set.
  374. </p>
  375. <p>
  376. Ideally, even though the result computed by <code>intersectall</code> is correct, one would want to avoid this extra work being performed.
  377. </p>
  378. <p>
  379. However, since the unnecessary expense of the computation is not noticed by any conditional in the code, it is not avoided.
  380. </p>
  381. </div>
  382. </div>
  383. <div id="outline-container-chapter-13-example-attempt-fix" class="outline-4">
  384. <h4 id="chapter-13-example-attempt-fix"><span class="section-number-4">2.1.3.</span> Attempt of fixing the issue</h4>
  385. <div class="outline-text-4" id="text-chapter-13-example-attempt-fix">
  386. <p>
  387. It is also not simple to rewrite <code>intersectall-inner</code> to perform such a check. For example the following does not eliminate all redundant work:
  388. </p>
  389. <div class="org-src-container">
  390. <pre class="src src-scheme" id="orgd8a6cd1">
  391. (define intersectall
  392. (λ (lsts)
  393. (letrec ([intersectall-inner
  394. (λ (lsts°)
  395. (cond
  396. [(null? (car lsts°)) '()] ; added check
  397. [(null? (cdr lsts°)) (car lsts°)]
  398. [else
  399. (intersect (car lsts°)
  400. (intersectall-inner (cdr lsts°)))]))])
  401. (cond
  402. [(null? lsts) '()]
  403. [else
  404. (intersectall-inner lsts)]))))
  405. </pre>
  406. </div>
  407. <p>
  408. Why does this not eliminate all redundant work? Because the return value of the check <code class="src src-scheme">[(null? (car lsts°)) '()]</code>, the empty list, will still be used as an argument in calls of <code>intersect</code> in the <code>else</code> branch of the <code>cond</code> in earlier iterations of <code>intersectall-inner</code>. Ideally one would avoid even calling <code>intersect</code> with any empty lists resulting from calls to <code>intersectall-inner</code>.
  409. </p>
  410. </div>
  411. </div>
  412. <div id="outline-container-chapter-13-example-continuations" class="outline-4">
  413. <h4 id="chapter-13-example-continuations"><span class="section-number-4">2.1.4.</span> Continuations to the rescue</h4>
  414. <div class="outline-text-4" id="text-chapter-13-example-continuations">
  415. <p>
  416. Fortunately, there is a good way to do so! Enter continuations.
  417. </p>
  418. <p>
  419. We can store a continuation of the program before <code>intersectall-inner</code> is ever called. That continuation takes an argument, which is the result of <code>intersectall-inner</code>. This way the continuation acts as means to do an early exit, no matter where the execution of <code>intersectall-inner</code> is, when it notices, that there is an empty list as return value of an <code>intersectall-inner</code> call. This is called an exit<sup><a id="fnr.1" class="footref" href="#fn.1" role="doc-backlink">1</a></sup> continuation.
  420. </p>
  421. <div class="org-src-container">
  422. <pre class="src src-scheme" id="org062f828">
  423. (define intersectall
  424. (λ (lsts)
  425. (call-with-current-continuation
  426. (λ (exit)
  427. (letrec ([intersectall-inner
  428. (λ (lsts°)
  429. (cond
  430. [(null? (car lsts°)) (exit '())] ; exit continuation call
  431. [(null? (cdr lsts°)) (car lsts°)]
  432. [else
  433. (intersect (car lsts°)
  434. (intersectall-inner (cdr lsts°)))]))])
  435. (cond
  436. [(null? lsts) '()]
  437. [else
  438. (intersectall-inner lsts)]))))))
  439. </pre>
  440. </div>
  441. <p>
  442. <code>intersectall-inner</code> can be used just like before.
  443. </p>
  444. <div class="org-src-container">
  445. <pre class="src src-scheme" id="org7a04a78">
  446. (simple-format
  447. #t "~a\n"
  448. (intersect '(a b c) '(c d e)))
  449. (simple-format
  450. #t "~a\n"
  451. (intersectall '((a b c)
  452. (c d e)
  453. (f c))))
  454. (simple-format
  455. #t "~a\n"
  456. (intersectall '((a b c)
  457. (c d e)
  458. ()
  459. (f g c))))
  460. </pre>
  461. </div>
  462. <pre class="example" id="orgdd28c15">
  463. (c)
  464. (c)
  465. ()
  466. </pre>
  467. </div>
  468. </div>
  469. <div id="outline-container-chapter-13-example-optimizations" class="outline-4">
  470. <h4 id="chapter-13-example-optimizations"><span class="section-number-4">2.1.5.</span> Further optimization of <code class="src src-scheme">intersect</code> and <code class="src src-scheme">intersectall</code></h4>
  471. <div class="outline-text-4" id="text-chapter-13-example-optimizations">
  472. <p>
  473. However, there is still an issue with the definition of <code class="src src-scheme">intersect</code> as defined above:
  474. </p>
  475. <div class="org-src-container">
  476. <pre class="src src-scheme">(define intersect
  477. (λ (set1 set2)
  478. (letrec ([member?
  479. (λ (elem lst)
  480. (member elem lst))]
  481. [intersect-inner
  482. (λ (set1°)
  483. (cond
  484. [(null? set1°) '()]
  485. [(member? (car set1°) set2)
  486. (cons (car set1°)
  487. (intersect-inner (cdr set1°)))]
  488. [else
  489. (intersect-inner (cdr set1°))]))])
  490. (intersect-inner set1))))
  491. </pre>
  492. </div>
  493. <p>
  494. When <code class="src src-scheme">intersect</code> receives an empty list as a second argument. <code class="src src-scheme">intersect-inner</code> will still go through all of the elements of the first argument and check, whether they are <code class="src src-scheme">member?</code> of the second argument. Inside <code class="src src-scheme">intersect-inner</code> the conditional never asks any questions about the second argument. It only ever asks things about the first argument. So the implementation cannot detect, that it is doing unnecessary work. Ideally we would not do any unnecessary work, of course.
  495. </p>
  496. <p>
  497. We can easily add a check for an empty list as second argument:
  498. </p>
  499. <div class="org-src-container">
  500. <pre class="src src-scheme" id="org1c47de9">(define intersect
  501. (λ (set1 set2)
  502. (letrec ([member?
  503. (λ (elem lst)
  504. (member elem lst))]
  505. [intersect-inner
  506. (λ (set1°)
  507. (cond
  508. [(null? set1°) '()]
  509. [(member? (car set1°) set2)
  510. (cons (car set1°)
  511. (intersect-inner (cdr set1°)))]
  512. [else
  513. (intersect-inner (cdr set1°))]))])
  514. ;; added conditional
  515. (cond
  516. [(null? set2) '()]
  517. [else
  518. ;; still same call to intersect-inner
  519. (intersect-inner set1)]))))
  520. </pre>
  521. </div>
  522. <p>
  523. Lets try it. Define <code class="src src-scheme">intersectall</code> in terms of the new <code class="src src-scheme">intersect</code>:
  524. </p>
  525. <div class="org-src-container">
  526. <pre class="src src-scheme" id="orgda6dbc4">(define intersect
  527. (λ (set1 set2)
  528. (letrec ([member?
  529. (λ (elem lst)
  530. (member elem lst))]
  531. [intersect-inner
  532. (λ (set1°)
  533. (cond
  534. [(null? set1°) '()]
  535. [(member? (car set1°) set2)
  536. (cons (car set1°)
  537. (intersect-inner (cdr set1°)))]
  538. [else
  539. (intersect-inner (cdr set1°))]))])
  540. ;; added conditional
  541. (cond
  542. [(null? set2) '()]
  543. [else
  544. ;; still same call to intersect-inner
  545. (intersect-inner set1)]))))
  546. (define intersectall
  547. (λ (lsts)
  548. (call-with-current-continuation
  549. (λ (exit)
  550. (letrec ([intersectall-inner
  551. (λ (lsts°)
  552. (cond
  553. [(null? (car lsts°)) (exit '())] ; exit continuation call
  554. [(null? (cdr lsts°)) (car lsts°)]
  555. [else
  556. (intersect (car lsts°)
  557. (intersectall-inner (cdr lsts°)))]))])
  558. (cond
  559. [(null? lsts) '()]
  560. [else
  561. (intersectall-inner lsts)]))))))
  562. </pre>
  563. </div>
  564. <p>
  565. <code>intersectall-inner</code> can be used just like before.
  566. </p>
  567. <div class="org-src-container">
  568. <pre class="src src-scheme" id="org1b9ce6b">
  569. (simple-format
  570. #t "~a\n"
  571. (intersect '(a b c) '(c d e)))
  572. (simple-format
  573. #t "~a\n"
  574. (intersectall '((a b c)
  575. (c d e)
  576. (f c))))
  577. (simple-format
  578. #t "~a\n"
  579. (intersectall '((a b c)
  580. (c d e)
  581. ()
  582. (f g c))))
  583. </pre>
  584. </div>
  585. <pre class="example" id="orgfdf2113">
  586. (c)
  587. (c)
  588. ()
  589. </pre>
  590. <p>
  591. That is nice. However we are not checking in <code class="src src-scheme">intersectall</code>, whether <code class="src src-scheme">intersect</code> gives an empty list as a return value, which will be the return value of <code class="src src-scheme">intersectall</code> and so we might call <code class="src src-scheme">intersect</code> unnecessarily with an empty list as second argument in iterations further up the stack. Instead, we could check for the result being the empty list. However, then we would check the same fact twice: Once inside <code class="src src-scheme">intersect</code> and then again when <code class="src src-scheme">intersect</code> returns in <code class="src src-scheme">intersectall</code>. Again unnecessary work.
  592. </p>
  593. <p>
  594. What we could do instead, is to let <code class="src src-scheme">intersect</code> use the continuation created in <code class="src src-scheme">intersectall</code>, once <code class="src src-scheme">intersect</code> finds, that one of its arguments is an empty list.
  595. </p>
  596. <p>
  597. There are at least 2 ways we can do this:
  598. </p>
  599. <ol class="org-ol">
  600. <li>passing the continuation<sup><a id="fnr.2" class="footref" href="#fn.2" role="doc-backlink">2</a></sup> to <code class="src src-scheme">intersect</code></li>
  601. <li>moving <code class="src src-scheme">intersect</code> into <code class="src src-scheme">intersectall</code>, so that the continuation is accessible for <code class="src src-scheme">intersect</code></li>
  602. </ol>
  603. <p>
  604. Option 1 is maybe not so great, since it requires <code class="src src-scheme">intersect</code> to have an additional argument, which the caller might need to be aware of, or use optional arguments.
  605. </p>
  606. <p>
  607. Option 2 is used in the book, but it also comes with a problem: <code class="src src-scheme">intersect</code> is a useful function in itself. Moving it into <code class="src src-scheme">intersectall</code> will make it impossible to use merely <code class="src src-scheme">intersect</code>, instead of <code class="src src-scheme">intersectall</code>. It will also make it impossible to write a unit test for <code class="src src-scheme">intersect</code>. Perhaps the idea of the book is to simply always use <code class="src src-scheme">intersectall</code> and wrap 2 arguments in a list, if one only needs the intersection of 2 sets. Or the idea is merely to have a case to show what continuations are and how they can be used to great effect.
  608. </p>
  609. <p>
  610. So lets roll with option 2:
  611. </p>
  612. <div class="org-src-container">
  613. <pre class="src src-scheme" id="org30ee72f">(define intersectall
  614. (λ (lsts)
  615. (call-with-current-continuation
  616. (λ (exit)
  617. (letrec ([intersect
  618. ;; added internal definition of intersect
  619. (λ (set1 set2)
  620. (letrec ([member?
  621. (λ (elem lst)
  622. (member elem lst))]
  623. [intersect-inner
  624. (λ (set1°)
  625. (cond
  626. [(null? set1°) '()]
  627. [(member? (car set1°) set2)
  628. (cons (car set1°)
  629. (intersect-inner (cdr set1°)))]
  630. [else
  631. (intersect-inner (cdr set1°))]))])
  632. (cond
  633. ;; now calling the exit continuation
  634. [(null? set2) (exit '())]
  635. [else
  636. (intersect-inner set1)])))]
  637. [intersectall-inner
  638. (λ (lsts°)
  639. (cond
  640. [(null? (car lsts°)) (exit '())]
  641. [(null? (cdr lsts°)) (car lsts°)]
  642. [else
  643. (intersect (car lsts°)
  644. (intersectall-inner (cdr lsts°)))]))])
  645. (cond
  646. [(null? lsts) '()]
  647. [else
  648. (intersectall-inner lsts)]))))))
  649. </pre>
  650. </div>
  651. <p>
  652. Lets try it:
  653. </p>
  654. <div class="org-src-container">
  655. <pre class="src src-scheme" id="org14c816e">
  656. (simple-format
  657. #t "~a\n"
  658. (intersectall '((a b c)
  659. (c d e)
  660. (f c))))
  661. (simple-format
  662. #t "~a\n"
  663. (intersectall '((a b c)
  664. (c d e)
  665. ()
  666. (f g c))))
  667. </pre>
  668. </div>
  669. <pre class="example" id="org003a3d8">
  670. (c)
  671. ()
  672. </pre>
  673. <p>
  674. Still works!
  675. </p>
  676. </div>
  677. </div>
  678. </div>
  679. <div id="outline-container-chapter-13-example-skipping" class="outline-3">
  680. <h3 id="chapter-13-example-skipping"><span class="section-number-3">2.2.</span> Example :: Skipping computation</h3>
  681. <div class="outline-text-3" id="text-chapter-13-example-skipping">
  682. <p>
  683. Another example for how continuations can be useful is skipping of computation or restarting computation with different state and thereby intentionally forgetting computation, that happened after the continuation was created. The example used in the book is the removal of all elements of a list up to and including the last occurrence of an element, that satisfies some predicate. The problem is, that in only 1 linear pass through the list, one does not know, whether one is removing too much of the list, because no later occurrence of such an element exists.
  684. </p>
  685. <p>
  686. Here is a more flexible version of the code in the book, which also makes the predicate specifiable:
  687. </p>
  688. <div class="org-src-container">
  689. <pre class="src src-scheme" id="org46b4711">(define rember-up-to-last
  690. (λ (lst pred)
  691. (call-with-current-continuation
  692. (λ (restart)
  693. (letrec ([rember-inner
  694. (λ (lst°)
  695. (cond
  696. [(null? lst°) '()]
  697. [(pred (car lst°))
  698. (restart (rember-inner (cdr lst°)))]
  699. [else
  700. (cons (car lst°)
  701. (rember-inner (cdr lst°)))]))])
  702. (rember-inner lst))))))
  703. </pre>
  704. </div>
  705. <p>
  706. We want to forget, what we accumulated in the <code class="src src-scheme">else</code> branch, if we find another predicate satisfying list element. For that we use the continuation named <code class="src src-scheme">restart</code>. We restart the accumulation of the result by using <code class="src src-scheme">(rember-inner (cdr lst°))</code> in place of previous stack frames, that memorized accumulating other elements into a result.
  707. </p>
  708. <p>
  709. Lets use it:
  710. </p>
  711. <div class="org-src-container">
  712. <pre class="src src-scheme" id="orgb165748">
  713. (simple-format
  714. #t "~a\n"
  715. (rember-up-to-last '(8 5 6 0 3 4 9 3 1)
  716. (λ (num) (even? num))))
  717. </pre>
  718. </div>
  719. <pre class="example" id="org1c918c8">
  720. (9 3 1)
  721. </pre>
  722. </div>
  723. </div>
  724. <div id="outline-container-chapter-13-example-continuations-notes" class="outline-3">
  725. <h3 id="chapter-13-example-continuations-notes"><span class="section-number-3">2.3.</span> Notes about continuations</h3>
  726. <div class="outline-text-3" id="text-chapter-13-example-continuations-notes">
  727. </div>
  728. <div id="outline-container-chapter-13-example-continuations-notes-languages-specifics" class="outline-4">
  729. <h4 id="chapter-13-example-continuations-notes-languages-specifics"><span class="section-number-4">2.3.1.</span> Specific language implementations</h4>
  730. <div class="outline-text-4" id="text-chapter-13-example-continuations-notes-languages-specifics">
  731. <p>
  732. The implementation using continuations is conceptually neat. However, in practice one needs to look out for language implementation specifics. For example GNU Guile's documentation mentions:
  733. </p>
  734. <blockquote>
  735. <p>
  736. Continuations are a powerful mechanism, and can be used to implement almost any sort of control structure, such as loops, coroutines, or exception handlers.
  737. </p>
  738. <p>
  739. However the implementation of continuations in Guile is not as efficient as one might hope, because Guile is designed to cooperate with programs written in other languages, such as C, which do not know about continuations. Basically continuations are captured by a block copy of the stack, and resumed by copying back.
  740. </p>
  741. <p>
  742. For this reason, continuations captured by call/cc should be used only when there is no other simple way to achieve the desired result, or when the elegance of the continuation mechanism outweighs the need for performance.
  743. </p>
  744. <p>
  745. Escapes upwards from loops or nested functions are generally best handled with prompts (see Prompts). Coroutines can be efficiently implemented with cooperating threads (a thread holds a full program stack but doesn’t copy it around the way continuations do).
  746. </p>
  747. <p>
  748. &#x2013; <a href="https://www.gnu.org/software/guile/manual/html_node/Continuations.html">https://www.gnu.org/software/guile/manual/html_node/Continuations.html</a> (2023-02-22)
  749. </p>
  750. </blockquote>
  751. <p>
  752. So in a specific Scheme dialect like GNU Guile, one should weigh the costs of the elegance of an implementation using continuations against desired performance and consider other concepts like exceptions and prompts.
  753. </p>
  754. </div>
  755. </div>
  756. <div id="outline-container-chapter-13-example-continuations-notes-other-languages" class="outline-4">
  757. <h4 id="chapter-13-example-continuations-notes-other-languages"><span class="section-number-4">2.3.2.</span> Other languages</h4>
  758. <div class="outline-text-4" id="text-chapter-13-example-continuations-notes-other-languages">
  759. <p>
  760. Another language, that is so nice to offer continuations, is Standard ML. See <a href="https://www.smlnj.org/doc/SMLofNJ/pages/cont.html">https://www.smlnj.org/doc/SMLofNJ/pages/cont.html</a>.
  761. </p>
  762. </div>
  763. </div>
  764. <div id="outline-container-chapter-13-example-continuations-notes-other-concepts" class="outline-4">
  765. <h4 id="chapter-13-example-continuations-notes-other-concepts"><span class="section-number-4">2.3.3.</span> Other concepts</h4>
  766. <div class="outline-text-4" id="text-chapter-13-example-continuations-notes-other-concepts">
  767. <p>
  768. This section discusses other language concepts, that one could employ to get the same result.
  769. </p>
  770. </div>
  771. <div id="outline-container-chapter-13-example-continuations-notes-other-concepts-return-statement" class="outline-5">
  772. <h5 id="chapter-13-example-continuations-notes-other-concepts-return-statement"><span class="section-number-5">2.3.3.1.</span> Return statement</h5>
  773. <div class="outline-text-5" id="text-chapter-13-example-continuations-notes-other-concepts-return-statement">
  774. <p>
  775. In many languages a <code>return</code> statement might be used to return early. However, this requires there to be a <code>return</code> <i>statement</i> in the language. For functional languages having statements like <code>return</code> does not make much sense, because everything or almost everything is an expression. Furthermore a <code>return</code> keyword is unnecessary to have in the language, as we have shown by effectively creating our own exit function using a continuation. A <code>return</code> statement can be seen as clutter in a language's syntax definition. Even some languages which do not prioritize functional programming have opted to not have a <code>return</code> statement. See Rust for example.
  776. </p>
  777. <p>
  778. Having all things be expressions has loads of advantages. Everything can be expected to return some value. Everything can be moved around in the code and placed in other places, without for example worrying about things like it being correct or incorrect syntax to use a conditional inside another expression. Expressions make code more flexible. When languages mix expressions and statements, it can mean a much more complicated language and grammar of the language's syntax in the end. Look for example at Python and its <code>if</code> constructs. It has many special cases and inline syntax, that needs to be explicitly added to the language's syntax. For languages which handle these things as expressions there is no surprise, that one can use conditionals wherever one wants to. There is simply nothing special about conditionals.
  779. </p>
  780. </div>
  781. </div>
  782. <div id="outline-container-chapter-13-example-continuations-notes-other-concepts-exceptions" class="outline-5">
  783. <h5 id="chapter-13-example-continuations-notes-other-concepts-exceptions"><span class="section-number-5">2.3.3.2.</span> Exceptions</h5>
  784. <div class="outline-text-5" id="text-chapter-13-example-continuations-notes-other-concepts-exceptions">
  785. <p>
  786. If not a <code>return</code> statement, then maybe an exception could be used to the same result? It could, but exceptions are actually meant to be used for exceptional circumstances and not for regular control flow. Using them for regular control flow is usually making it harder to read the code. If an exception is raised, it should be caught somewhere else in the code. That is more code. Also an exception type needs to be defined or an appropriate one already needs to exist. Also note, that using continuations one can implement exceptions in ones language. Using a continuation is using a more fundamental building block, a more basic concept.
  787. </p>
  788. </div>
  789. </div>
  790. <div id="outline-container-chapter-13-example-continuations-notes-other-concepts-prompts" class="outline-5">
  791. <h5 id="chapter-13-example-continuations-notes-other-concepts-prompts"><span class="section-number-5">2.3.3.3.</span> Prompts</h5>
  792. <div class="outline-text-5" id="text-chapter-13-example-continuations-notes-other-concepts-prompts">
  793. <p>
  794. I do not yet know enough about prompts and their semantics to judge, whether they are conceptually fitting for being used instead of continuations. Them being mentioned in the GNU Guile manual makes me hopeful though, that they are indeed an appropriate concept to use in place of continuations.
  795. </p>
  796. </div>
  797. </div>
  798. </div>
  799. </div>
  800. </div>
  801. <div id="footnotes">
  802. <h2 class="footnotes">Footnotes: </h2>
  803. <div id="text-footnotes">
  804. <div class="footdef"><sup><a id="fn.1" class="footnum" href="#fnr.1" role="doc-backlink">1</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">or "escape"?</p></div></div>
  805. <div class="footdef"><sup><a id="fn.2" class="footnum" href="#fnr.2" role="doc-backlink">2</a></sup> <div class="footpara" role="doc-footnote"><p class="footpara">Uh oh! Continuation Passing Style lurking!</p></div></div>
  806. </div>
  807. </div></div>
  808. <div id="postamble" class="status">
  809. <p class="date">Date: 2023-02-26 So 00:00</p>
  810. <p class="author">Author: Zelphir Kaltstahl</p>
  811. <p class="date">Created: 2023-02-26 So 16:12</p>
  812. <p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
  813. </div>
  814. </body>
  815. </html>