improved indentation and whitespace for markdown code blocks
All code blocks in markdown have been intended by at least 4 spaces. We add `--tab-stop=8` to all `pandoc(1)` executions in order to set a better tab stop indentation, especially for tab intended code blocks. Changed `bin/pandoc-wrapper.sh` VERSION from "1.5.3 2024-03-26" to "1.6 2024-03-31". Fixed `1991/brnstnd/sorta.README.md` so that the sorta code is code blocks. Removed unneeded paragraph group in copyright in `inc/footer.default.html`. Fixed excess whitespace after list Author on entry `index.html` page. Changed `bin/output-index-author.sh` VERSION from "1.5.2 2024-03-26" to "1.6 2024-03-31". Performed `make www` to perform the above and test under macOS. TODO: Fix the problem of the initial line of code being extra intended. TODO: Fix excess whitespace around code that is inline.
This commit is contained in:
1 parent
b84c27ce02
commit
a996f8d2b8
734 files changed
+16723
-16963
No files matched your search
+49
-50
@@ -132,8 +132,7 @@
|
||||
<h2 id="author"><a name="author"></a>Author:</h2>
|
||||
<ul>
|
||||
<li>Name: <a href="../../authors.html#Tony_Finch">Tony Finch</a><br>
|
||||
Location: <a href="../../location.html#GB">GB</a> - <em>United Kingdom of Great Britain and Northern Ireland</em> (<em>United Kingdom</em>)
|
||||
<br><br></li>
|
||||
Location: <a href="../../location.html#GB">GB</a> - <em>United Kingdom of Great Britain and Northern Ireland</em> (<em>United Kingdom</em>)</li>
|
||||
</ul>
|
||||
|
||||
<!-- END: next line ends content generated by: bin/output-index-author.sh -->
|
||||
@@ -142,14 +141,14 @@ Location: <a href="../../location.html#GB">GB</a> - <em>United Kingdom of Great
|
||||
<!-- START: this line starts content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
|
||||
<h2 id="to-build">To build:</h2>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="fu">make</span> all</span></code></pre></div>
|
||||
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a> <span class="fu">make</span> all</span></code></pre></div>
|
||||
<p>NOTE: this may take a while. Some systems may have problems building
|
||||
this entry because of the system resources it requires.</p>
|
||||
<h2 id="to-use">To use:</h2>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./fanf</span></span></code></pre></div>
|
||||
<div class="sourceCode" id="cb2"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a> <span class="ex">./fanf</span></span></code></pre></div>
|
||||
<h2 id="try">Try:</h2>
|
||||
<p>Enter an expression on standard input. To try some we have selected:</p>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ex">./try.sh</span></span></code></pre></div>
|
||||
<div class="sourceCode" id="cb3"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a> <span class="ex">./try.sh</span></span></code></pre></div>
|
||||
<h2 id="judges-remarks">Judges’ remarks:</h2>
|
||||
<h3 id="historical-aside">Historical aside:</h3>
|
||||
<p>At a time the code in <a href="fanf.c">fanf.c</a> was that of <a href="fanf.orig.c">fanf.orig.c</a>
|
||||
@@ -166,7 +165,7 @@ source.</p>
|
||||
<code>fanftmp2.c</code> C program. Take a look at that final C program again,
|
||||
can you begin to understand what it is doing?</p>
|
||||
<p>Look at the first stage of the C pre-processing which was done like:</p>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="fu">cc</span> fanf.c <span class="at">-E</span> <span class="op">></span> fanftmp1.c</span></code></pre></div>
|
||||
<div class="sourceCode" id="cb4"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a> <span class="fu">cc</span> fanf.c <span class="at">-E</span> <span class="op">></span> fanftmp1.c</span></code></pre></div>
|
||||
<p>Skip to the bottom of <code>fanftmp1.c</code> (after all of the C pre-processor header
|
||||
stuff … look for a line of the form: <code># 38 "fanf.c"</code> near the bottom)
|
||||
and look at the resulting code. This code, when C pre-processed
|
||||
@@ -218,44 +217,44 @@ since it is equivalent to <code>S K K</code>:</p>
|
||||
<p>The algorithm for translating lambda expressions into combinator
|
||||
expressions works as follows. There are three forms of lambda expression
|
||||
to consider: variables, applications, and abstractions.</p>
|
||||
<pre><code>trans v -> v (variable)
|
||||
trans a b -> (trans a) (trans b ) (application)
|
||||
trans \ab -> abs a (trans b) (abstraction)</code></pre>
|
||||
<pre><code> trans v -> v (variable)
|
||||
trans a b -> (trans a) (trans b ) (application)
|
||||
trans \ab -> abs a (trans b) (abstraction)</code></pre>
|
||||
<p>There are a further three cases to consider for the body of lambda
|
||||
expressions, where we need to do the magic that transforms away the
|
||||
variables.</p>
|
||||
<pre><code>abs a f x -> S (abs a f) (abs a x)
|
||||
abs a b -> K b (b != a)
|
||||
abs a a -> I</code></pre>
|
||||
<pre><code> abs a f x -> S (abs a f) (abs a x)
|
||||
abs a b -> K b (b != a)
|
||||
abs a a -> I</code></pre>
|
||||
<p>E.g. suppose we had combinator expressions for <code>+</code> and <code>3</code> and we wanted
|
||||
to see what the combinator expression for doubling 3 looked like:</p>
|
||||
<pre><code> trans \x(+ x x) 3
|
||||
-> (trans \x(+ x x)) (trans 3)
|
||||
-> (abs x (trans + x x)) 3
|
||||
-> (abs x + x x) 3
|
||||
-> S (abs x + x) (abs x x) 3
|
||||
-> S (S (abs x +) (abs x x)) I 3
|
||||
-> S (S (K +) I) I 3
|
||||
-> S (S (K +) I) I 3</code></pre>
|
||||
<pre><code> trans \x(+ x x) 3
|
||||
-> (trans \x(+ x x)) (trans 3)
|
||||
-> (abs x (trans + x x)) 3
|
||||
-> (abs x + x x) 3
|
||||
-> S (abs x + x) (abs x x) 3
|
||||
-> S (S (abs x +) (abs x x)) I 3
|
||||
-> S (S (K +) I) I 3
|
||||
-> S (S (K +) I) I 3</code></pre>
|
||||
<p>We can then check that this evaluates to the expected result:</p>
|
||||
<pre><code> S (S (K +) I) I 3
|
||||
-> S (K +) I 3 (I 3)
|
||||
-> K + 3 (I 3) (I 3)
|
||||
-> + (I 3) (I 3)
|
||||
-> + 3 3</code></pre>
|
||||
<pre><code> S (S (K +) I) I 3
|
||||
-> S (K +) I 3 (I 3)
|
||||
-> K + 3 (I 3) (I 3)
|
||||
-> + (I 3) (I 3)
|
||||
-> + 3 3</code></pre>
|
||||
<p>It is possible to perform a slightly more compact translation with a
|
||||
couple of simple optimisations. For example, note that <code>K (a b)</code> is the
|
||||
same as <code>S (K a) (K b)</code>, because</p>
|
||||
<pre><code> K (a b) x
|
||||
-> a b</code></pre>
|
||||
<pre><code> K (a b) x
|
||||
-> a b</code></pre>
|
||||
<p>and</p>
|
||||
<pre><code> S (K a) (K b) x
|
||||
-> K a x (K b x)
|
||||
-> a b</code></pre>
|
||||
<pre><code> S (K a) (K b) x
|
||||
-> K a x (K b x)
|
||||
-> a b</code></pre>
|
||||
<p>Also, <code>S (K a) I</code> is the same as just <code>a</code> because</p>
|
||||
<pre><code> S (K a) I x
|
||||
-> K a x (I x)
|
||||
-> a x</code></pre>
|
||||
<pre><code> S (K a) I x
|
||||
-> K a x (I x)
|
||||
-> a x</code></pre>
|
||||
<p>The program simply reads a lambda expression from the standard input,
|
||||
translates it into a combinator expression using the transformation and
|
||||
optimisations described above, and prints out the result.</p>
|
||||
@@ -305,12 +304,12 @@ obfuscated form <code>E('a') char then else</code>.</p>
|
||||
its first argument and checking that it is some form of <code>E</code>. It then
|
||||
writes that character on <code>stdout</code>, and finally it calls its second
|
||||
argument as a function with the argument <code>I</code>, i.e.</p>
|
||||
<pre><code>P x f -> f I</code></pre>
|
||||
<pre><code> P x f -> f I</code></pre>
|
||||
<p>with a side-effect.</p>
|
||||
<p>The <code>G</code> combinator just reads a character from <code>stdin</code> then calls its
|
||||
argument as a function with the appropriate <code>E</code> combinator as an
|
||||
argument, i.e.</p>
|
||||
<pre><code>G f -> f E(c)</code></pre>
|
||||
<pre><code> G f -> f E(c)</code></pre>
|
||||
<p>with a side-effect.</p>
|
||||
<p>One of the problems with non-strict languages is that it is hard to
|
||||
predict in advance in which order side-effects will occur. In my program
|
||||
@@ -323,11 +322,11 @@ CPS form of the I/O monad from page 6 of “Imperative Functional
|
||||
Programming”.)</p>
|
||||
<p>The <code>Y</code> combinator is used for implementing recursive functions. It has
|
||||
the evaluation rule</p>
|
||||
<pre><code>Y f -> f (Y f)</code></pre>
|
||||
<pre><code> Y f -> f (Y f)</code></pre>
|
||||
<p>so that it can be used to call a function with itself as an argument.
|
||||
For example, if I had the appropriate arithmetic operators defined, I
|
||||
could write a factorial function in the lambda calculus like this:</p>
|
||||
<pre><code>Y \f\n((= n 0) 1 (* n (f (- n 1))))</code></pre>
|
||||
<pre><code> Y \f\n((= n 0) 1 (* n (f (- n 1))))</code></pre>
|
||||
<p><code>OFL</code> provides a facility for naming expressions so that they can be used
|
||||
more than once without writing them in full. A definition must be written
|
||||
on one line in the form <code>l name b expression</code> where <code>l</code> is short for
|
||||
@@ -342,23 +341,23 @@ expression must be surrounded by brackets.</p>
|
||||
basic eight. These combinators provide greater scope for optimisation
|
||||
when translating an expression from the lambda calculus to combinators,
|
||||
and therefore more compact programs. Their evaluation rules are:</p>
|
||||
<pre><code>B f g x -> f (g x)
|
||||
C f g x -> (f x) g
|
||||
BB c f g x -> c (f (g x))
|
||||
CC c f g x -> c (f x) g
|
||||
SS c f g x -> c (f x) (g x)</code></pre>
|
||||
<pre><code> B f g x -> f (g x)
|
||||
C f g x -> (f x) g
|
||||
BB c f g x -> c (f (g x))
|
||||
CC c f g x -> c (f x) g
|
||||
SS c f g x -> c (f x) (g x)</code></pre>
|
||||
<p>I used them to help fit my program into the required space; unfortunately
|
||||
I couldn’t fit the version that fully optimises the lambda expressions
|
||||
it reads into the required space. The complete optimisation rules
|
||||
including the ones it doesn’t use are:</p>
|
||||
<pre><code>S (K p) I -> p
|
||||
S (K p) (K r) -> K ( p r )
|
||||
S (K p) (B r s) -> BB p r s
|
||||
S (K p) r -> B p r
|
||||
S (B p q) (K r) -> CC p q r
|
||||
S p (K r) -> C p r
|
||||
S (B p q) r -> SS p q r
|
||||
S p r -> S p r</code></pre>
|
||||
<pre><code> S (K p) I -> p
|
||||
S (K p) (K r) -> K ( p r )
|
||||
S (K p) (B r s) -> BB p r s
|
||||
S (K p) r -> B p r
|
||||
S (B p q) (K r) -> CC p q r
|
||||
S p (K r) -> C p r
|
||||
S (B p q) r -> SS p q r
|
||||
S p r -> S p r</code></pre>
|
||||
<h3 id="the-implementation-of-ofl">The implementation of <code>OFL</code></h3>
|
||||
<p>Although <code>OFL</code> has completely different syntax and semantics to C, all you
|
||||
need to compile <code>OFL</code> programs is a C compiler and a header file (which in
|
||||
|
||||
Reference in new issue
Block a user