{"componentChunkName":"component---src-templates-blog-post-js","path":"/the-little-schemer-summary-8/","result":{"data":{"site":{"siteMetadata":{"title":"星雨之夜"}},"markdownRemark":{"id":"fc4759bc-567d-538b-9d1e-d0fcbd36ff49","excerpt":"准备知识 函数可以返回原子和列表；它也能返回一个函数。 你可能听说过函数“柯里化”。 col 是 collector 的缩写，有时又叫 continuation。 Scheme 十诫之第九诫 用函数来抽象通用模式。 Scheme 十诫之第十诫 构建函数，一次收集多个值。 自定义函数 (rember-f test? a…","html":"<h2>准备知识</h2>\n<ol>\n<li>函数可以返回原子和列表；它也能返回一个函数。</li>\n<li>你可能听说过函数“柯里化”。</li>\n<li>col 是 collector 的缩写，有时又叫 continuation。</li>\n</ol>\n<h2>Scheme 十诫之第九诫</h2>\n<p>用函数来抽象通用模式。</p>\n<h2>Scheme 十诫之第十诫</h2>\n<p>构建函数，一次收集多个值。</p>\n<h2>自定义函数</h2>\n<h3>(rember-f test? a l)</h3>\n<p>定义：函数版本的 <code class=\"language-text\">rember</code>。<code class=\"language-text\">test?</code> 至少有以下几种情况：</p>\n<ul>\n<li><code class=\"language-text\">test?</code> 是 <code class=\"language-text\">=</code></li>\n<li><code class=\"language-text\">test?</code> 是 <code class=\"language-text\">eq?</code></li>\n<li><code class=\"language-text\">test?</code> 是 <code class=\"language-text\">equal?</code></li>\n</ul>\n<p>实现：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> rember-f\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">test?</span> a l<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">null?</span> l<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">test?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span> a<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span>\n                  <span class=\"token punctuation\">(</span><span class=\"token function\">rember-f</span> test? a <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>如果返回一个函数：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> rember-f\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">test?</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">a</span> l<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">null?</span> l<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">test?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span> a<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span>\n                    <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">rember-f</span> test?<span class=\"token punctuation\">)</span> a <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>用法就变成 <code class=\"language-text\">((rember-f test?) a l)</code>。</p>\n<h3>(eq?-c a)</h3>\n<p>定义：其返回一个函数，这个函数用于比较原子 x 与 a 是否相同。</p>\n<p>实现：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> eq?-c\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">a</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">x</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token function\">eq?</span> x a<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>((insertL-f test?) new old l)</h3>\n<p>定义：按照 <code class=\"language-text\">rember</code> 转换 <code class=\"language-text\">rember-f</code> 的思路转换 <code class=\"language-text\">insertL</code>。</p>\n<p>实现：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> insertL-f\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">test?</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">new</span> old l<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">null?</span> l<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">test?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span> old<span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> new <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> old <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span>\n                    <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">insertL-f</span> test?<span class=\"token punctuation\">)</span> new old <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>((insertR-f test?) new old l)</h3>\n<p>定义：按照 <code class=\"language-text\">rember</code> 转换 <code class=\"language-text\">rember-f</code> 的思路转换 <code class=\"language-text\">insertR</code>。</p>\n<p>实现：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> insertR-f\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">test?</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">new</span> old l<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">null?</span> l<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">test?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span> old<span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> old <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> new <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span>\n                    <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">insertR-f</span> test?<span class=\"token punctuation\">)</span> new old <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>比较上述两个函数的差异，发现在于中间的某一行。于是我们引入以下两个函数。</p>\n<h3>(seqL new old l)</h3>\n<p>定义：cons 第二个参数到第三个参数上，得到一个结果，然后再 cons 第一个参数到这个结果上。</p>\n<p>实现：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> seqL\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">new</span> old l<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> new <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> old l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>(seqR new old l)</h3>\n<p>定义：cons 第一个参数到第三个参数上，得到一个结果，然后再 cons 第二个参数到这个结果上。</p>\n<p>实现：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> seqR\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">new</span> old l<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> old <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> new l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>((insert-g seq) new old l)</h3>\n<p>定义：引入 <code class=\"language-text\">insert-g</code>，可以表示 <code class=\"language-text\">insertL</code> 或者 <code class=\"language-text\">insertR</code>。这里 <code class=\"language-text\">seq</code> 是 <code class=\"language-text\">seqL</code> 或者 <code class=\"language-text\">seqR</code>。</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> insert-g\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">seq</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">new</span> old l<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">null?</span> l<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">eq?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span> old<span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token function\">seq</span> new old <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span>\n                    <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">insert-g</span> seq<span class=\"token punctuation\">)</span> new old <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>那么我们定义 <code class=\"language-text\">insertL</code> 可以这样做：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> insertL <span class=\"token punctuation\">(</span><span class=\"token function\">insert-g</span> seqL<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>同样的，<code class=\"language-text\">insertR</code>：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> insertR <span class=\"token punctuation\">(</span><span class=\"token function\">insert-g</span> seqR<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>但是其实不需要单独定义函数，我们可以直接传递整个定义：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> insertL\n  <span class=\"token punctuation\">(</span><span class=\"token function\">insert-g</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">new</span> old l<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> new <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> old l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>考虑以前定义过的 <code class=\"language-text\">subst</code>，也可以这么写：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> subst\n  <span class=\"token punctuation\">(</span><span class=\"token function\">insert-g</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">new</span> old l<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> new l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>(atom-to-function x)</h3>\n<p>定义：我们提取 <code class=\"language-text\">value</code> （第六章）的公共部分，这个函数相当于数学符号的 parser，根据读取到的不同原子（+×↑）来定义运算方法。</p>\n<p>实现：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> atom-to-function\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">x</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">eq?</span> x <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> +<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> plus<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">eq?</span> x <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> ×<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> ×<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> ↑<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>那么我们的 <code class=\"language-text\">value</code> 函数可以写成：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> value\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">nexp</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">atom?</span> nexp<span class=\"token punctuation\">)</span> nexp<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span>\n        <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">atom-to-function</span> <span class=\"token punctuation\">(</span><span class=\"token function\">operator</span> nexp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token function\">value</span> <span class=\"token punctuation\">(</span><span class=\"token function\">1st-sub-exp</span> nexp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token function\">value</span> <span class=\"token punctuation\">(</span><span class=\"token function\">2nd-sub-exp</span> nexp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>以下函数在实现功能的同时，又用 col 收集了其他我们想要的值。</p>\n<h3>(multirember&#x26;co a lat col)</h3>\n<p>定义：查找 lat 的每个原子，判断该原子是否等于 a，否的话那些原子被收集进 ls1 中，是的话被收集进 ls2 中。最后计算 <code class=\"language-text\">(col ls1 ls2)</code> 的值。</p>\n<p>实现：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> multirember&amp;co\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">a</span> lat col<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">null?</span> lat<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">eq?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> lat<span class=\"token punctuation\">)</span> a<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token function\">multirember&amp;co</span> a <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> lat<span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">newlat</span> seen<span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> newlat <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> lat<span class=\"token punctuation\">)</span> seen<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span>\n        <span class=\"token punctuation\">(</span><span class=\"token function\">multirember&amp;co</span> a <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> lat<span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">newlat</span> seen<span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> lat<span class=\"token punctuation\">)</span> newlat<span class=\"token punctuation\">)</span> seen<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>(multiinsertLR&#x26;co new oldL oldR lat col)</h3>\n<p>定义：将 new 插入到 lat 的 oldL 的左边和 oldR 的右边，同时记录左右分别插入了多少次。</p>\n<p>实现：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> multiinsertLR&amp;co\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">new</span> oldL oldR lat col<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">null?</span> lat<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token number\">0</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">eq?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> lat<span class=\"token punctuation\">)</span> oldL<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token function\">multiinsertLR&amp;co</span> new oldL oldR <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> lat<span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">newlat</span> L R<span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> new <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> oldL newlat<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token function\">add1</span> L<span class=\"token punctuation\">)</span> R<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">eq?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> lat<span class=\"token punctuation\">)</span> oldR<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token function\">multiinsertLR&amp;co</span> new oldL oldR <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> lat<span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">newlat</span> L R<span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> oldR <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> new newlat<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> L <span class=\"token punctuation\">(</span><span class=\"token function\">add1</span> R<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token function\">multiinsertLR&amp;co</span> new oldL oldR <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> lat<span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">newlat</span> L R<span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> lat<span class=\"token punctuation\">)</span> newlat<span class=\"token punctuation\">)</span> L R<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<h3>(evens-only* l)</h3>\n<p>定义：去除 l 中所有的奇数。</p>\n<p>我们先定义判断偶数的函数 <code class=\"language-text\">even?</code>：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> even?\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">n</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token function\">×</span> <span class=\"token punctuation\">(</span><span class=\"token function\">÷</span> n <span class=\"token number\">2</span><span class=\"token punctuation\">)</span> <span class=\"token number\">2</span><span class=\"token punctuation\">)</span> n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> evens-only*\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">l</span><span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">null?</span> l<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">atom?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n          <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">even?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span>\n                  <span class=\"token punctuation\">(</span><span class=\"token function\">evens-only*</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token function\">evens-only*</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token function\">evens-only*</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n                  <span class=\"token punctuation\">(</span><span class=\"token function\">evens-only*</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>接下来试着写一个 <code class=\"language-text\">evens-only*&amp;co</code> 函数，其从一个列表中移除所有奇数项，以构建一个偶数项的嵌套列表，同时求出该列表所有偶数项的乘积和奇数项的和。</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">define</span> evens-only*&amp;co\n  <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">l</span> col<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token builtin\">null?</span> l<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">quote</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token number\">1</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">atom?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n        <span class=\"token punctuation\">(</span><span class=\"token keyword\">cond</span>\n          <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token function\">even?</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">(</span><span class=\"token function\">evens-only*&amp;co</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span>\n              <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">newl</span> p s<span class=\"token punctuation\">)</span>\n                <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span> newl<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">(</span><span class=\"token function\">×</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span> p<span class=\"token punctuation\">)</span> s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n          <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token function\">evens-only*&amp;co</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span>\n            <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">newl</span> p s<span class=\"token punctuation\">)</span>\n              <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> newl p <span class=\"token punctuation\">(</span><span class=\"token function\">plus</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span> s<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token keyword\">else</span> <span class=\"token punctuation\">(</span><span class=\"token function\">evens-only*&amp;co</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">car</span> l<span class=\"token punctuation\">)</span> ...<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>可以发现 <code class=\"language-text\">(evens-only*&amp;co (cdr l) ...)</code> 的 collector 很好写，但是 <code class=\"language-text\">(evens-only*&amp;co (car l) ...)</code> 的 collector 应该怎么写呢？</p>\n<p>首先这个 collector 要通过 <code class=\"language-text\">evens-only*&amp;co</code> 访问 l 的 cdr，并收集偶数项，偶数项乘积和奇数项之和，可以这么定义：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">al</span> ap as<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">(</span><span class=\"token function\">evens-only*&amp;co</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span>\n    ...<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>然后接下来的一个 collector 要做的是，把 <code class=\"language-text\">(cdr l)</code> 和 <code class=\"language-text\">(car l)</code> 所收集的值——偶数项、偶数项乘积、奇数项之和——cons、累乘、累加：</p>\n<div class=\"gatsby-highlight\" data-language=\"scheme\"><pre class=\"language-scheme\"><code class=\"language-scheme\"><span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">al</span> ap as<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">(</span><span class=\"token function\">evens-only*&amp;co</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cdr</span> l<span class=\"token punctuation\">)</span>\n    <span class=\"token punctuation\">(</span><span class=\"token keyword\">lambda</span> <span class=\"token punctuation\">(</span><span class=\"token function\">dl</span> dp ds<span class=\"token punctuation\">)</span>\n      <span class=\"token punctuation\">(</span><span class=\"token function\">col</span> <span class=\"token punctuation\">(</span><span class=\"token builtin\">cons</span> al dl<span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">(</span><span class=\"token function\">×</span> ap dp<span class=\"token punctuation\">)</span>\n           <span class=\"token punctuation\">(</span><span class=\"token function\">plus</span> as ds<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span></code></pre></div>\n<p>这就是上面 <code class=\"language-text\">evens-only*&amp;co</code> 所缺失的定义了。</p>","frontmatter":{"title":"The Little Schemer 知识点整理（八）：Lambda 终结者","date":"2019 年 01 月 09 日","description":"这一章讲述了 Scheme 的柯里化，函数能够返回函数；以及在函数递归的过程中，构建 collector 来收集多个值。"}}},"pageContext":{"slug":"/the-little-schemer-summary-8/","previous":{"fields":{"slug":"/the-little-schemer-summary-7/"},"frontmatter":{"title":"The Little Schemer 知识点整理（七）：朋友及关系"}},"next":{"fields":{"slug":"/the-little-schemer-summary-9/"},"frontmatter":{"title":"The Little Schemer 知识点整理（九）：……周而复始……"}}}}}