Remove old docs.
This commit is contained in:
parent
466bf3d79b
commit
3d1dc6232e
|
|
@ -1,20 +0,0 @@
|
|||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
SPHINXPROJ = Thun
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = _build
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,4 +0,0 @@
|
|||
# Sphinx build info version 1
|
||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
||||
config: d581c6009ec2b560e43b1edcc2912d38
|
||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
||||
|
|
@ -1,185 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
|
||||
-->
|
||||
<!-- Title: finite_state_machine Pages: 1 -->
|
||||
<svg width="534pt" height="270pt"
|
||||
viewBox="0.00 0.00 534.00 270.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 266)">
|
||||
<title>finite_state_machine</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-266 530,-266 530,4 -4,4"/>
|
||||
<!-- i -->
|
||||
<g id="node1" class="node"><title>i</title>
|
||||
<ellipse fill="none" stroke="black" cx="338" cy="-146" rx="18" ry="18"/>
|
||||
<ellipse fill="none" stroke="black" cx="338" cy="-146" rx="22" ry="22"/>
|
||||
<text text-anchor="middle" x="338" y="-142.3" font-family="Times,serif" font-size="14.00">i</text>
|
||||
</g>
|
||||
<!-- i->i -->
|
||||
<g id="edge17" class="edge"><title>i->i</title>
|
||||
<path fill="none" stroke="black" d="M330.317,-166.991C329.369,-177.087 331.93,-186 338,-186 341.889,-186 344.337,-182.342 345.346,-177.059"/>
|
||||
<polygon fill="black" stroke="black" points="348.846,-177.102 345.683,-166.991 341.85,-176.868 348.846,-177.102"/>
|
||||
<text text-anchor="middle" x="338" y="-189.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- j -->
|
||||
<g id="node10" class="node"><title>j</title>
|
||||
<ellipse fill="none" stroke="black" cx="421" cy="-136" rx="18" ry="18"/>
|
||||
<text text-anchor="middle" x="421" y="-132.3" font-family="Times,serif" font-size="14.00">j</text>
|
||||
</g>
|
||||
<!-- i->j -->
|
||||
<g id="edge18" class="edge"><title>i->j</title>
|
||||
<path fill="none" stroke="black" d="M357.466,-135.495C363.775,-132.451 371.008,-129.536 378,-128 383.213,-126.855 388.811,-126.984 394.167,-127.763"/>
|
||||
<polygon fill="black" stroke="black" points="393.487,-131.197 404.002,-129.894 394.97,-124.355 393.487,-131.197"/>
|
||||
<text text-anchor="middle" x="381.5" y="-131.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
<!-- h -->
|
||||
<g id="node2" class="node"><title>h</title>
|
||||
<ellipse fill="none" stroke="black" cx="504" cy="-85" rx="18" ry="18"/>
|
||||
<ellipse fill="none" stroke="black" cx="504" cy="-85" rx="22" ry="22"/>
|
||||
<text text-anchor="middle" x="504" y="-81.3" font-family="Times,serif" font-size="14.00">h</text>
|
||||
</g>
|
||||
<!-- h->i -->
|
||||
<g id="edge15" class="edge"><title>h->i</title>
|
||||
<path fill="none" stroke="black" d="M481.868,-83.4025C461.033,-82.62 428.676,-83.5645 403,-94 387.267,-100.394 372.373,-112.028 360.918,-122.673"/>
|
||||
<polygon fill="black" stroke="black" points="358.306,-120.33 353.569,-129.807 363.182,-125.353 358.306,-120.33"/>
|
||||
<text text-anchor="middle" x="421" y="-97.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- h->h -->
|
||||
<g id="edge16" class="edge"><title>h->h</title>
|
||||
<path fill="none" stroke="black" d="M496.317,-105.991C495.369,-116.087 497.93,-125 504,-125 507.889,-125 510.337,-121.342 511.346,-116.059"/>
|
||||
<polygon fill="black" stroke="black" points="514.846,-116.102 511.683,-105.991 507.85,-115.868 514.846,-116.102"/>
|
||||
<text text-anchor="middle" x="504" y="-128.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
<!-- a -->
|
||||
<g id="node3" class="node"><title>a</title>
|
||||
<ellipse fill="none" stroke="black" cx="18" cy="-128" rx="18" ry="18"/>
|
||||
<text text-anchor="middle" x="18" y="-124.3" font-family="Times,serif" font-size="14.00">a</text>
|
||||
</g>
|
||||
<!-- b -->
|
||||
<g id="node4" class="node"><title>b</title>
|
||||
<ellipse fill="none" stroke="black" cx="255" cy="-113" rx="18" ry="18"/>
|
||||
<text text-anchor="middle" x="255" y="-109.3" font-family="Times,serif" font-size="14.00">b</text>
|
||||
</g>
|
||||
<!-- a->b -->
|
||||
<g id="edge1" class="edge"><title>a->b</title>
|
||||
<path fill="none" stroke="black" d="M36.2801,-126.897C76.7816,-124.312 178.091,-117.845 226.89,-114.73"/>
|
||||
<polygon fill="black" stroke="black" points="227.255,-118.214 237.011,-114.084 226.809,-111.229 227.255,-118.214"/>
|
||||
<text text-anchor="middle" x="136.5" y="-123.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- c -->
|
||||
<g id="node5" class="node"><title>c</title>
|
||||
<ellipse fill="none" stroke="black" cx="97" cy="-155" rx="18" ry="18"/>
|
||||
<text text-anchor="middle" x="97" y="-151.3" font-family="Times,serif" font-size="14.00">c</text>
|
||||
</g>
|
||||
<!-- a->c -->
|
||||
<g id="edge2" class="edge"><title>a->c</title>
|
||||
<path fill="none" stroke="black" d="M35.3297,-133.726C45.4364,-137.27 58.635,-141.898 70.1398,-145.932"/>
|
||||
<polygon fill="black" stroke="black" points="69.099,-149.276 79.6938,-149.282 71.4153,-142.67 69.099,-149.276"/>
|
||||
<text text-anchor="middle" x="57.5" y="-145.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
<!-- b->b -->
|
||||
<g id="edge3" class="edge"><title>b->b</title>
|
||||
<path fill="none" stroke="black" d="M248.266,-130.037C246.892,-139.858 249.137,-149 255,-149 258.665,-149 260.916,-145.429 261.753,-140.353"/>
|
||||
<polygon fill="black" stroke="black" points="265.252,-140.031 261.734,-130.037 258.252,-140.044 265.252,-140.031"/>
|
||||
<text text-anchor="middle" x="255" y="-152.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- d -->
|
||||
<g id="node6" class="node"><title>d</title>
|
||||
<ellipse fill="none" stroke="black" cx="338" cy="-79" rx="18" ry="18"/>
|
||||
<text text-anchor="middle" x="338" y="-75.3" font-family="Times,serif" font-size="14.00">d</text>
|
||||
</g>
|
||||
<!-- b->d -->
|
||||
<g id="edge4" class="edge"><title>b->d</title>
|
||||
<path fill="none" stroke="black" d="M272.003,-106.283C283.319,-101.533 298.722,-95.0674 311.693,-89.6227"/>
|
||||
<polygon fill="black" stroke="black" points="313.164,-92.801 321.03,-85.7034 310.455,-86.3466 313.164,-92.801"/>
|
||||
<text text-anchor="middle" x="294.5" y="-101.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
<!-- c->b -->
|
||||
<g id="edge5" class="edge"><title>c->b</title>
|
||||
<path fill="none" stroke="black" d="M114.862,-150.653C138.269,-144.593 181.917,-133.2 219,-123 221.799,-122.23 224.721,-121.414 227.631,-120.594"/>
|
||||
<polygon fill="black" stroke="black" points="228.623,-123.951 237.284,-117.849 226.708,-117.218 228.623,-123.951"/>
|
||||
<text text-anchor="middle" x="176" y="-142.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- e -->
|
||||
<g id="node7" class="node"><title>e</title>
|
||||
<ellipse fill="none" stroke="black" cx="176" cy="-206" rx="18" ry="18"/>
|
||||
<text text-anchor="middle" x="176" y="-202.3" font-family="Times,serif" font-size="14.00">e</text>
|
||||
</g>
|
||||
<!-- c->e -->
|
||||
<g id="edge6" class="edge"><title>c->e</title>
|
||||
<path fill="none" stroke="black" d="M112.483,-164.593C123.668,-172.001 139.356,-182.392 152.219,-190.911"/>
|
||||
<polygon fill="black" stroke="black" points="150.312,-193.846 160.582,-196.45 154.177,-188.01 150.312,-193.846"/>
|
||||
<text text-anchor="middle" x="136.5" y="-185.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
<!-- d->b -->
|
||||
<g id="edge7" class="edge"><title>d->b</title>
|
||||
<path fill="none" stroke="black" d="M320.205,-74.8763C311.208,-73.4911 300.131,-73.1424 291,-77 284.094,-79.9175 277.879,-84.9376 272.669,-90.3183"/>
|
||||
<polygon fill="black" stroke="black" points="269.694,-88.4067 265.791,-98.2568 274.985,-92.9902 269.694,-88.4067"/>
|
||||
<text text-anchor="middle" x="294.5" y="-80.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- f -->
|
||||
<g id="node8" class="node"><title>f</title>
|
||||
<ellipse fill="none" stroke="black" cx="176" cy="-46" rx="18" ry="18"/>
|
||||
<text text-anchor="middle" x="176" y="-42.3" font-family="Times,serif" font-size="14.00">f</text>
|
||||
</g>
|
||||
<!-- d->f -->
|
||||
<g id="edge8" class="edge"><title>d->f</title>
|
||||
<path fill="none" stroke="black" d="M319.923,-75.478C292.098,-69.7389 236.768,-58.3271 203.708,-51.5086"/>
|
||||
<polygon fill="black" stroke="black" points="204.321,-48.0614 193.82,-49.4692 202.907,-54.9171 204.321,-48.0614"/>
|
||||
<text text-anchor="middle" x="255" y="-69.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
<!-- e->b -->
|
||||
<g id="edge9" class="edge"><title>e->b</title>
|
||||
<path fill="none" stroke="black" d="M190.241,-194.796C198.908,-187.136 210.212,-176.503 219,-166 226.507,-157.028 233.803,-146.389 239.774,-137.007"/>
|
||||
<polygon fill="black" stroke="black" points="242.759,-138.834 245.056,-128.491 236.81,-135.144 242.759,-138.834"/>
|
||||
<text text-anchor="middle" x="215.5" y="-176.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- g -->
|
||||
<g id="node9" class="node"><title>g</title>
|
||||
<ellipse fill="none" stroke="black" cx="255" cy="-211" rx="18" ry="18"/>
|
||||
<text text-anchor="middle" x="255" y="-207.3" font-family="Times,serif" font-size="14.00">g</text>
|
||||
</g>
|
||||
<!-- e->g -->
|
||||
<g id="edge10" class="edge"><title>e->g</title>
|
||||
<path fill="none" stroke="black" d="M194.089,-207.11C203.659,-207.731 215.817,-208.521 226.677,-209.226"/>
|
||||
<polygon fill="black" stroke="black" points="226.753,-212.738 236.959,-209.893 227.207,-205.753 226.753,-212.738"/>
|
||||
<text text-anchor="middle" x="215.5" y="-211.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
<!-- f->h -->
|
||||
<g id="edge12" class="edge"><title>f->h</title>
|
||||
<path fill="none" stroke="black" d="M189.02,-33.1864C203.151,-19.5754 227.995,-0 254,-0 254,-0 254,-0 422,-0 453.632,-0 476.677,-31.2311 489.924,-55.8314"/>
|
||||
<polygon fill="black" stroke="black" points="486.862,-57.5325 494.518,-64.8562 493.1,-54.3566 486.862,-57.5325"/>
|
||||
<text text-anchor="middle" x="338" y="-3.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
<!-- f->b -->
|
||||
<g id="edge11" class="edge"><title>f->b</title>
|
||||
<path fill="none" stroke="black" d="M190.834,-56.7689C199.13,-63.3319 209.817,-71.9742 219,-80 224.034,-84.4001 229.343,-89.2757 234.262,-93.899"/>
|
||||
<polygon fill="black" stroke="black" points="231.917,-96.4985 241.576,-100.852 236.74,-91.4252 231.917,-96.4985"/>
|
||||
<text text-anchor="middle" x="215.5" y="-83.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- g->i -->
|
||||
<g id="edge13" class="edge"><title>g->i</title>
|
||||
<path fill="none" stroke="black" d="M269.741,-199.974C281.437,-190.587 298.524,-176.876 312.548,-165.622"/>
|
||||
<polygon fill="black" stroke="black" points="314.778,-168.32 320.387,-159.331 310.397,-162.86 314.778,-168.32"/>
|
||||
<text text-anchor="middle" x="294.5" y="-185.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- g->g -->
|
||||
<g id="edge14" class="edge"><title>g->g</title>
|
||||
<path fill="none" stroke="black" d="M248.266,-228.037C246.892,-237.858 249.137,-247 255,-247 258.665,-247 260.916,-243.429 261.753,-238.353"/>
|
||||
<polygon fill="black" stroke="black" points="265.252,-238.031 261.734,-228.037 258.252,-238.044 265.252,-238.031"/>
|
||||
<text text-anchor="middle" x="255" y="-250.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
<!-- j->i -->
|
||||
<g id="edge19" class="edge"><title>j->i</title>
|
||||
<path fill="none" stroke="black" d="M403.34,-139.8C397.561,-140.993 391.021,-142.205 385,-143 380.321,-143.618 375.357,-144.11 370.488,-144.502"/>
|
||||
<polygon fill="black" stroke="black" points="369.864,-141.036 360.126,-145.209 370.341,-148.02 369.864,-141.036"/>
|
||||
<text text-anchor="middle" x="381.5" y="-146.8" font-family="Times,serif" font-size="14.00">0</text>
|
||||
</g>
|
||||
<!-- j->h -->
|
||||
<g id="edge20" class="edge"><title>j->h</title>
|
||||
<path fill="none" stroke="black" d="M436.857,-126.646C447.841,-119.73 463.1,-110.122 476.194,-101.878"/>
|
||||
<polygon fill="black" stroke="black" points="478.237,-104.727 484.835,-96.4375 474.507,-98.8038 478.237,-104.727"/>
|
||||
<text text-anchor="middle" x="460.5" y="-116.8" font-family="Times,serif" font-size="14.00">1</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 11 KiB |
|
|
@ -1,109 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Overview: module code — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1>All modules for which code is available</h1>
|
||||
<ul><li><a href="joy/joy.html">joy.joy</a></li>
|
||||
<li><a href="joy/library.html">joy.library</a></li>
|
||||
<li><a href="joy/parser.html">joy.parser</a></li>
|
||||
<li><a href="joy/utils/generated_library.html">joy.utils.generated_library</a></li>
|
||||
<li><a href="joy/utils/pretty_print.html">joy.utils.pretty_print</a></li>
|
||||
<li><a href="joy/utils/stack.html">joy.utils.stack</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../notebooks/Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../notebooks/index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,255 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>joy.joy — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css" />
|
||||
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../../genindex.html" />
|
||||
<link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1>Source code for joy.joy</h1><div class="highlight"><pre>
|
||||
<span></span><span class="c1"># -*- coding: utf-8 -*-</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Copyright © 2014, 2015, 2017, 2018 Simon Forman</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># This file is part of Thun</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Thun is free software: you can redistribute it and/or modify</span>
|
||||
<span class="c1"># it under the terms of the GNU General Public License as published by</span>
|
||||
<span class="c1"># the Free Software Foundation, either version 3 of the License, or</span>
|
||||
<span class="c1"># (at your option) any later version.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Thun is distributed in the hope that it will be useful,</span>
|
||||
<span class="c1"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
|
||||
<span class="c1"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
|
||||
<span class="c1"># GNU General Public License for more details.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># You should have received a copy of the GNU General Public License</span>
|
||||
<span class="c1"># along with Thun. If not see <http://www.gnu.org/licenses/>.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd">This module implements an interpreter for a dialect of Joy that</span>
|
||||
<span class="sd">attempts to stay very close to the spirit of Joy but does not precisely</span>
|
||||
<span class="sd">match the behaviour of the original version(s) written in C.</span>
|
||||
|
||||
<span class="sd">'''</span>
|
||||
<span class="kn">from</span> <span class="nn">builtins</span> <span class="kn">import</span> <span class="nb">input</span>
|
||||
<span class="kn">from</span> <span class="nn">traceback</span> <span class="kn">import</span> <span class="n">print_exc</span>
|
||||
<span class="kn">from</span> <span class="nn">joy.parser</span> <span class="kn">import</span> <span class="n">text_to_expression</span><span class="p">,</span> <span class="n">ParseError</span><span class="p">,</span> <span class="n">Symbol</span>
|
||||
<span class="kn">from</span> <span class="nn">joy.utils.stack</span> <span class="kn">import</span> <span class="n">stack_to_string</span>
|
||||
<span class="kn">from</span> <span class="nn">joy.utils.errors</span> <span class="kn">import</span> <span class="p">(</span>
|
||||
<span class="n">NotAListError</span><span class="p">,</span>
|
||||
<span class="n">NotAnIntError</span><span class="p">,</span>
|
||||
<span class="n">StackUnderflowError</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="UnknownSymbolError"><a class="viewcode-back" href="../../joy.html#joy.joy.UnknownSymbolError">[docs]</a><span class="k">class</span> <span class="nc">UnknownSymbolError</span><span class="p">(</span><span class="ne">KeyError</span><span class="p">):</span> <span class="k">pass</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="joy"><a class="viewcode-back" href="../../joy.html#joy.joy.joy">[docs]</a><span class="k">def</span> <span class="nf">joy</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">,</span> <span class="n">viewer</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Evaluate a Joy expression on a stack.</span>
|
||||
|
||||
<span class="sd"> This function iterates through a sequence of terms which are either</span>
|
||||
<span class="sd"> literals (strings, numbers, sequences of terms) or function symbols.</span>
|
||||
<span class="sd"> Literals are put onto the stack and functions are looked up in the</span>
|
||||
<span class="sd"> dictionary and executed.</span>
|
||||
|
||||
<span class="sd"> The viewer is a function that is called with the stack and expression</span>
|
||||
<span class="sd"> on every iteration, its return value is ignored.</span>
|
||||
|
||||
<span class="sd"> :param stack stack: The stack.</span>
|
||||
<span class="sd"> :param stack expression: The expression to evaluate.</span>
|
||||
<span class="sd"> :param dict dictionary: A ``dict`` mapping names to Joy functions.</span>
|
||||
<span class="sd"> :param function viewer: Optional viewer function.</span>
|
||||
<span class="sd"> :rtype: (stack, (), dictionary)</span>
|
||||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="k">while</span> <span class="n">expression</span><span class="p">:</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">viewer</span><span class="p">:</span> <span class="n">viewer</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span>
|
||||
|
||||
<span class="n">term</span><span class="p">,</span> <span class="n">expression</span> <span class="o">=</span> <span class="n">expression</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">term</span><span class="p">,</span> <span class="n">Symbol</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="n">term</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">dictionary</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">UnknownSymbolError</span><span class="p">(</span><span class="n">term</span><span class="p">)</span>
|
||||
<span class="n">func</span> <span class="o">=</span> <span class="n">dictionary</span><span class="p">[</span><span class="n">term</span><span class="p">]</span>
|
||||
<span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">stack</span> <span class="o">=</span> <span class="n">term</span><span class="p">,</span> <span class="n">stack</span>
|
||||
|
||||
<span class="k">if</span> <span class="n">viewer</span><span class="p">:</span> <span class="n">viewer</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="run"><a class="viewcode-back" href="../../joy.html#joy.joy.run">[docs]</a><span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">,</span> <span class="n">viewer</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Return the stack resulting from running the Joy code text on the stack.</span>
|
||||
|
||||
<span class="sd"> :param str text: Joy code.</span>
|
||||
<span class="sd"> :param stack stack: The stack.</span>
|
||||
<span class="sd"> :param dict dictionary: A ``dict`` mapping names to Joy functions.</span>
|
||||
<span class="sd"> :param function viewer: Optional viewer function.</span>
|
||||
<span class="sd"> :rtype: (stack, (), dictionary)</span>
|
||||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">text_to_expression</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">joy</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">,</span> <span class="n">viewer</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="repl"><a class="viewcode-back" href="../../joy.html#joy.joy.repl">[docs]</a><span class="k">def</span> <span class="nf">repl</span><span class="p">(</span><span class="n">stack</span><span class="o">=</span><span class="p">(),</span> <span class="n">dictionary</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Read-Evaluate-Print Loop</span>
|
||||
|
||||
<span class="sd"> Accept input and run it on the stack, loop.</span>
|
||||
|
||||
<span class="sd"> :param stack stack: The stack.</span>
|
||||
<span class="sd"> :param dict dictionary: A ``dict`` mapping names to Joy functions.</span>
|
||||
<span class="sd"> :rtype: stack</span>
|
||||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="k">if</span> <span class="n">dictionary</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">dictionary</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||||
<span class="nb">print</span><span class="p">()</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="n">stack_to_string</span><span class="p">(</span><span class="n">stack</span><span class="p">),</span> <span class="s1">'<-top'</span><span class="p">)</span>
|
||||
<span class="nb">print</span><span class="p">()</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">text</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s1">'joy? '</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="p">(</span><span class="ne">EOFError</span><span class="p">,</span> <span class="ne">KeyboardInterrupt</span><span class="p">):</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">stack</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">dictionary</span> <span class="o">=</span> <span class="n">run</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">)</span>
|
||||
<span class="k">except</span><span class="p">:</span>
|
||||
<span class="n">print_exc</span><span class="p">()</span>
|
||||
<span class="k">except</span><span class="p">:</span>
|
||||
<span class="n">print_exc</span><span class="p">()</span>
|
||||
<span class="nb">print</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="n">stack</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="interp"><a class="viewcode-back" href="../../joy.html#joy.joy.interp">[docs]</a><span class="k">def</span> <span class="nf">interp</span><span class="p">(</span><span class="n">stack</span><span class="o">=</span><span class="p">(),</span> <span class="n">dictionary</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Simple REPL with no extra output, suitable for use in scripts.</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="k">if</span> <span class="n">dictionary</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
||||
<span class="n">dictionary</span> <span class="o">=</span> <span class="p">{}</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">text</span> <span class="o">=</span> <span class="nb">input</span><span class="p">()</span>
|
||||
<span class="k">except</span> <span class="p">(</span><span class="ne">EOFError</span><span class="p">,</span> <span class="ne">KeyboardInterrupt</span><span class="p">):</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">stack</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">dictionary</span> <span class="o">=</span> <span class="n">run</span><span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="n">UnknownSymbolError</span> <span class="k">as</span> <span class="n">sym</span><span class="p">:</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Unknown:'</span><span class="p">,</span> <span class="n">sym</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="n">StackUnderflowError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="p">)</span> <span class="c1"># 'Not enough values on stack.'</span>
|
||||
<span class="k">except</span> <span class="n">NotAnIntError</span><span class="p">:</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Not an integer.'</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="n">NotAListError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
|
||||
<span class="k">except</span><span class="p">:</span>
|
||||
<span class="n">print_exc</span><span class="p">()</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="n">stack_to_string</span><span class="p">(</span><span class="n">stack</span><span class="p">))</span>
|
||||
<span class="k">except</span><span class="p">:</span>
|
||||
<span class="n">print_exc</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="n">stack</span></div>
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../notebooks/Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../notebooks/index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../../index.html">Documentation overview</a><ul>
|
||||
<li><a href="../index.html">Module code</a><ul>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,229 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>joy.parser — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../_static/alabaster.css" />
|
||||
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
|
||||
<script src="../../_static/jquery.js"></script>
|
||||
<script src="../../_static/underscore.js"></script>
|
||||
<script src="../../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../../genindex.html" />
|
||||
<link rel="search" title="Search" href="../../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1>Source code for joy.parser</h1><div class="highlight"><pre>
|
||||
<span></span><span class="c1"># -*- coding: utf-8 -*-</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Copyright © 2014, 2015, 2016, 2017 Simon Forman</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># This file is part of Thun.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Thun is free software: you can redistribute it and/or modify</span>
|
||||
<span class="c1"># it under the terms of the GNU General Public License as published by</span>
|
||||
<span class="c1"># the Free Software Foundation, either version 3 of the License, or</span>
|
||||
<span class="c1"># (at your option) any later version.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Thun is distributed in the hope that it will be useful,</span>
|
||||
<span class="c1"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
|
||||
<span class="c1"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
|
||||
<span class="c1"># GNU General Public License for more details.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># You should have received a copy of the GNU General Public License</span>
|
||||
<span class="c1"># along with Thun. If not see <http://www.gnu.org/licenses/>.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd">This module exports a single function for converting text to a joy</span>
|
||||
<span class="sd">expression as well as a single Symbol class and a single Exception type.</span>
|
||||
|
||||
<span class="sd">The Symbol string class is used by the interpreter to recognize literals</span>
|
||||
<span class="sd">by the fact that they are not Symbol objects.</span>
|
||||
|
||||
<span class="sd">A crude grammar::</span>
|
||||
|
||||
<span class="sd"> joy = term*</span>
|
||||
<span class="sd"> term = integer | '[' joy ']' | symbol</span>
|
||||
|
||||
<span class="sd">A Joy expression is a sequence of zero or more terms. A term is a</span>
|
||||
<span class="sd">literal value (integer or Joy expression) or a function symbol.</span>
|
||||
<span class="sd">Function symbols are sequences of non-blanks and cannot contain square</span>
|
||||
<span class="sd">brackets. Terms must be separated by blanks, which can be omitted</span>
|
||||
<span class="sd">around square brackets.</span>
|
||||
|
||||
<span class="sd">'''</span>
|
||||
<span class="kn">from</span> <span class="nn">re</span> <span class="kn">import</span> <span class="n">Scanner</span>
|
||||
<span class="kn">from</span> <span class="nn">joy.utils.stack</span> <span class="kn">import</span> <span class="n">list_to_stack</span>
|
||||
<span class="kn">from</span> <span class="nn">joy.utils.snippets</span> <span class="kn">import</span> <span class="p">(</span>
|
||||
<span class="n">pat</span> <span class="k">as</span> <span class="n">SNIPPETS</span><span class="p">,</span>
|
||||
<span class="n">from_string</span><span class="p">,</span>
|
||||
<span class="n">Snippet</span><span class="p">,</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
|
||||
<span class="n">BRACKETS</span> <span class="o">=</span> <span class="sa">r</span><span class="s1">'\[|\]'</span>
|
||||
<span class="n">BLANKS</span> <span class="o">=</span> <span class="sa">r</span><span class="s1">'\s+'</span>
|
||||
<span class="n">WORDS</span> <span class="o">=</span> <span class="sa">r</span><span class="s1">'[^[\]\s]+'</span>
|
||||
|
||||
|
||||
<span class="n">token_scanner</span> <span class="o">=</span> <span class="n">Scanner</span><span class="p">([</span>
|
||||
<span class="p">(</span><span class="n">SNIPPETS</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">_</span><span class="p">,</span> <span class="n">token</span><span class="p">:</span> <span class="n">from_string</span><span class="p">(</span><span class="n">token</span><span class="p">)),</span>
|
||||
<span class="p">(</span><span class="n">BRACKETS</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">_</span><span class="p">,</span> <span class="n">token</span><span class="p">:</span> <span class="n">token</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="n">BLANKS</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span>
|
||||
<span class="p">(</span><span class="n">WORDS</span><span class="p">,</span> <span class="k">lambda</span> <span class="n">_</span><span class="p">,</span> <span class="n">token</span><span class="p">:</span> <span class="n">token</span><span class="p">),</span>
|
||||
<span class="p">])</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="Symbol"><a class="viewcode-back" href="../../parser.html#joy.parser.Symbol">[docs]</a><span class="k">class</span> <span class="nc">Symbol</span><span class="p">(</span><span class="nb">str</span><span class="p">):</span>
|
||||
<span class="sd">'''A string class that represents Joy function names.'''</span>
|
||||
<span class="fm">__repr__</span> <span class="o">=</span> <span class="nb">str</span><span class="o">.</span><span class="fm">__str__</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="text_to_expression"><a class="viewcode-back" href="../../parser.html#joy.parser.text_to_expression">[docs]</a><span class="k">def</span> <span class="nf">text_to_expression</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
|
||||
<span class="sd">'''Convert a string to a Joy expression.</span>
|
||||
|
||||
<span class="sd"> When supplied with a string this function returns a Python datastructure</span>
|
||||
<span class="sd"> that represents the Joy datastructure described by the text expression.</span>
|
||||
<span class="sd"> Any unbalanced square brackets will raise a ParseError.</span>
|
||||
|
||||
<span class="sd"> :param str text: Text to convert.</span>
|
||||
<span class="sd"> :rtype: stack</span>
|
||||
<span class="sd"> :raises ParseError: if the parse fails.</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="k">return</span> <span class="n">_parse</span><span class="p">(</span><span class="n">_tokenize</span><span class="p">(</span><span class="n">text</span><span class="p">))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="ParseError"><a class="viewcode-back" href="../../parser.html#joy.parser.ParseError">[docs]</a><span class="k">class</span> <span class="nc">ParseError</span><span class="p">(</span><span class="ne">ValueError</span><span class="p">):</span>
|
||||
<span class="sd">'''Raised when there is a error while parsing text.'''</span></div>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_tokenize</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
|
||||
<span class="sd">'''Convert a text into a stream of tokens.</span>
|
||||
|
||||
<span class="sd"> Converts function names to Symbols.</span>
|
||||
|
||||
<span class="sd"> Raise ParseError (with some of the failing text) if the scan fails.</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="n">tokens</span><span class="p">,</span> <span class="n">rest</span> <span class="o">=</span> <span class="n">token_scanner</span><span class="o">.</span><span class="n">scan</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">rest</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span>
|
||||
<span class="s1">'Scan failed at position </span><span class="si">%i</span><span class="s1">, </span><span class="si">%r</span><span class="s1">'</span>
|
||||
<span class="o">%</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">text</span><span class="p">)</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">rest</span><span class="p">),</span> <span class="n">rest</span><span class="p">[:</span><span class="mi">10</span><span class="p">])</span>
|
||||
<span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">tokens</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_parse</span><span class="p">(</span><span class="n">tokens</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Return a stack/list expression of the tokens.</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="n">frame</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="n">stack</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="n">tok</span> <span class="ow">in</span> <span class="n">tokens</span><span class="p">:</span>
|
||||
<span class="k">if</span> <span class="n">tok</span> <span class="o">==</span> <span class="s1">'['</span><span class="p">:</span>
|
||||
<span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">frame</span><span class="p">)</span>
|
||||
<span class="n">frame</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">elif</span> <span class="n">tok</span> <span class="o">==</span> <span class="s1">']'</span><span class="p">:</span>
|
||||
<span class="n">v</span> <span class="o">=</span> <span class="n">frame</span>
|
||||
<span class="k">try</span><span class="p">:</span> <span class="n">frame</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
|
||||
<span class="k">except</span> <span class="ne">IndexError</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="s1">'Extra closing bracket.'</span><span class="p">)</span> <span class="kn">from</span> <span class="bp">None</span>
|
||||
<span class="n">frame</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">list_to_stack</span><span class="p">(</span><span class="n">v</span><span class="p">))</span>
|
||||
<span class="k">elif</span> <span class="n">tok</span> <span class="o">==</span> <span class="s1">'true'</span><span class="p">:</span> <span class="n">frame</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="kc">True</span><span class="p">)</span>
|
||||
<span class="k">elif</span> <span class="n">tok</span> <span class="o">==</span> <span class="s1">'false'</span><span class="p">:</span> <span class="n">frame</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="kc">False</span><span class="p">)</span>
|
||||
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">tok</span><span class="p">,</span> <span class="n">Snippet</span><span class="p">):</span> <span class="n">frame</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">tok</span><span class="p">)</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="k">try</span><span class="p">:</span> <span class="n">thing</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">tok</span><span class="p">)</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="n">thing</span> <span class="o">=</span> <span class="n">Symbol</span><span class="p">(</span><span class="n">tok</span><span class="p">)</span>
|
||||
<span class="n">frame</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">stack</span><span class="p">:</span> <span class="k">raise</span> <span class="n">ParseError</span><span class="p">(</span><span class="s1">'Unclosed bracket.'</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">list_to_stack</span><span class="p">(</span><span class="n">frame</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../notebooks/Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../notebooks/index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../../index.html">Documentation overview</a><ul>
|
||||
<li><a href="../index.html">Module code</a><ul>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,519 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>joy.utils.generated_library — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" />
|
||||
<script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
|
||||
<script src="../../../_static/jquery.js"></script>
|
||||
<script src="../../../_static/underscore.js"></script>
|
||||
<script src="../../../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../../../genindex.html" />
|
||||
<link rel="search" title="Search" href="../../../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../../../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1>Source code for joy.utils.generated_library</h1><div class="highlight"><pre>
|
||||
<span></span><span class="c1"># GENERATED FILE. DO NOT EDIT.</span>
|
||||
<span class="c1"># The code that generated these functions is in the repo history</span>
|
||||
<span class="c1"># at the v0.4.0 tag.</span>
|
||||
<span class="kn">from</span> <span class="nn">.errors</span> <span class="kn">import</span> <span class="n">NotAListError</span><span class="p">,</span> <span class="n">StackUnderflowError</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_Tree_add_Ee</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="p">((</span><span class="n">a4</span><span class="p">,</span> <span class="p">(</span><span class="n">a5</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="n">s2</span><span class="p">))))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">((</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="n">s2</span><span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_Tree_delete_R0</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a2 ...1] a1 -- [a2 ...1] a2 a1 a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">((</span><span class="n">a2</span><span class="p">,</span> <span class="n">s1</span><span class="p">),</span> <span class="n">s2</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">((</span><span class="n">a2</span><span class="p">,</span> <span class="n">s1</span><span class="p">),</span> <span class="n">s2</span><span class="p">))))</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_Tree_delete_clear_stuff</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a3 a2 [a1 ...1] -- [...1])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="n">s1</span><span class="p">),</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s2</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_Tree_get_E</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a3 a4 ...1] a2 a1 -- a4)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">((</span><span class="n">a3</span><span class="p">,</span> <span class="p">(</span><span class="n">a4</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="n">s2</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a4</span><span class="p">,</span> <span class="n">s2</span><span class="p">)</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="ccons"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.ccons">[docs]</a><span class="k">def</span> <span class="nf">ccons</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a2 a1 [...1] -- [a2 a1 ...1])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s2</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">((</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="n">s2</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="cons"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.cons">[docs]</a><span class="k">def</span> <span class="nf">cons</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a1 [...0] -- [a1 ...0])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">try</span><span class="p">:</span> <span class="n">s0</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">raise</span> <span class="n">StackUnderflowError</span><span class="p">(</span><span class="s1">'Not enough values on stack.'</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span> <span class="k">raise</span> <span class="n">NotAListError</span><span class="p">(</span><span class="s1">'Not a list.'</span><span class="p">)</span>
|
||||
<span class="k">try</span><span class="p">:</span> <span class="n">a1</span><span class="p">,</span> <span class="n">s23</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="k">raise</span> <span class="n">StackUnderflowError</span><span class="p">(</span><span class="s1">'Not enough values on stack.'</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="n">s0</span><span class="p">),</span> <span class="n">s23</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="dup"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.dup">[docs]</a><span class="k">def</span> <span class="nf">dup</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a1 -- a1 a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="dupd"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.dupd">[docs]</a><span class="k">def</span> <span class="nf">dupd</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a2 a1 -- a2 a2 a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="dupdd"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.dupdd">[docs]</a><span class="k">def</span> <span class="nf">dupdd</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a3 a2 a1 -- a3 a3 a2 a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s23</span><span class="p">))))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="first"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.first">[docs]</a><span class="k">def</span> <span class="nf">first</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a1 ...1] -- a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="n">s1</span><span class="p">),</span> <span class="n">s23</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="first_two"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.first_two">[docs]</a><span class="k">def</span> <span class="nf">first_two</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a1 a2 ...1] -- a1 a2)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="n">s2</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s2</span><span class="p">))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="fourth"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.fourth">[docs]</a><span class="k">def</span> <span class="nf">fourth</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a1 a2 a3 a4 ...1] -- a4)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="p">(</span><span class="n">a4</span><span class="p">,</span> <span class="n">s1</span><span class="p">)))),</span> <span class="n">s2</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a4</span><span class="p">,</span> <span class="n">s2</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="over"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.over">[docs]</a><span class="k">def</span> <span class="nf">over</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a2 a1 -- a2 a1 a2)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="pop"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.pop">[docs]</a><span class="k">def</span> <span class="nf">pop</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a1 --)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">StackUnderflowError</span><span class="p">(</span><span class="s1">'Cannot pop empty stack.'</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">s23</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="popd"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.popd">[docs]</a><span class="k">def</span> <span class="nf">popd</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a2 a1 -- a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="popdd"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.popdd">[docs]</a><span class="k">def</span> <span class="nf">popdd</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a3 a2 a1 -- a2 a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="popop"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.popop">[docs]</a><span class="k">def</span> <span class="nf">popop</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a2 a1 --)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="n">s23</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="popopd"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.popopd">[docs]</a><span class="k">def</span> <span class="nf">popopd</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a3 a2 a1 -- a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="popopdd"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.popopdd">[docs]</a><span class="k">def</span> <span class="nf">popopdd</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a4 a3 a2 a1 -- a2 a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="p">(</span><span class="n">a4</span><span class="p">,</span> <span class="n">s23</span><span class="p">))))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="rest"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.rest">[docs]</a><span class="k">def</span> <span class="nf">rest</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a1 ...0] -- [...0])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">s0</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">StackUnderflowError</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="n">NotAListError</span><span class="p">(</span><span class="s1">'Not a list.'</span><span class="p">)</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">_</span><span class="p">,</span> <span class="n">s1</span> <span class="o">=</span> <span class="n">s0</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">StackUnderflowError</span><span class="p">(</span><span class="s1">'Cannot take rest of empty list.'</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">stack</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="rolldown"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.rolldown">[docs]</a><span class="k">def</span> <span class="nf">rolldown</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a1 a2 a3 -- a2 a3 a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="rollup"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.rollup">[docs]</a><span class="k">def</span> <span class="nf">rollup</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a1 a2 a3 -- a3 a1 a2)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="rrest"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.rrest">[docs]</a><span class="k">def</span> <span class="nf">rrest</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a1 a2 ...1] -- [...1])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="n">s2</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="second"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.second">[docs]</a><span class="k">def</span> <span class="nf">second</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a1 a2 ...1] -- a2)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s1</span><span class="p">)),</span> <span class="n">s2</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s2</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="stack"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.stack">[docs]</a><span class="k">def</span> <span class="nf">stack</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (... -- ... [...])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="n">s0</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">s0</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="stuncons"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.stuncons">[docs]</a><span class="k">def</span> <span class="nf">stuncons</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (... a1 -- ... a1 a1 [...])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s1</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s1</span><span class="p">)))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="stununcons"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.stununcons">[docs]</a><span class="k">def</span> <span class="nf">stununcons</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (... a2 a1 -- ... a2 a1 a1 a2 [...])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s1</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s1</span><span class="p">)))))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="swaack"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.swaack">[docs]</a><span class="k">def</span> <span class="nf">swaack</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([...1] -- [...0])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s0</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">StackUnderflowError</span><span class="p">(</span><span class="s1">'Not enough values on stack.'</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="n">NotAListError</span><span class="p">(</span><span class="s1">'Not a list.'</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="n">s1</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="swap"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.swap">[docs]</a><span class="k">def</span> <span class="nf">swap</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a1 a2 -- a2 a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="n">StackUnderflowError</span><span class="p">(</span><span class="s1">'Not enough values on stack.'</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="swons"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.swons">[docs]</a><span class="k">def</span> <span class="nf">swons</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([...1] a1 -- [a1 ...1])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="n">s1</span><span class="p">),</span> <span class="n">s2</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="third"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.third">[docs]</a><span class="k">def</span> <span class="nf">third</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a1 a2 a3 ...1] -- a3)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s1</span><span class="p">))),</span> <span class="n">s2</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a3</span><span class="p">,</span> <span class="n">s2</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="tuck"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.tuck">[docs]</a><span class="k">def</span> <span class="nf">tuck</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a2 a1 -- a1 a2 a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">a2</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">)))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="uncons"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.uncons">[docs]</a><span class="k">def</span> <span class="nf">uncons</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a1 ...0] -- a1 [...0])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="n">s0</span><span class="p">),</span> <span class="n">s23</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">s0</span><span class="p">,</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">))</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="unit"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.unit">[docs]</a><span class="k">def</span> <span class="nf">unit</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> (a1 -- [a1 ])</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="n">s23</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="p">()),</span> <span class="n">s23</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="unswons"><a class="viewcode-back" href="../../../library.html#joy.utils.generated_library.unswons">[docs]</a><span class="k">def</span> <span class="nf">unswons</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">"""</span>
|
||||
<span class="sd"> ::</span>
|
||||
|
||||
<span class="sd"> ([a1 ...1] -- [...1] a1)</span>
|
||||
|
||||
<span class="sd"> """</span>
|
||||
<span class="p">((</span><span class="n">a1</span><span class="p">,</span> <span class="n">s1</span><span class="p">),</span> <span class="n">s2</span><span class="p">)</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="p">(</span><span class="n">a1</span><span class="p">,</span> <span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">))</span></div>
|
||||
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../../../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../notebooks/Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../notebooks/index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../../../index.html">Documentation overview</a><ul>
|
||||
<li><a href="../../index.html">Module code</a><ul>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../../../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.3.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>joy.utils.pretty_print — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" />
|
||||
<script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
|
||||
<script src="../../../_static/jquery.js"></script>
|
||||
<script src="../../../_static/underscore.js"></script>
|
||||
<script src="../../../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../../../genindex.html" />
|
||||
<link rel="search" title="Search" href="../../../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../../../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1>Source code for joy.utils.pretty_print</h1><div class="highlight"><pre>
|
||||
<span></span><span class="c1"># -*- coding: utf-8 -*-</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Copyright © 2016 Simon Forman</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># This file is part of Thun.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Thun is free software: you can redistribute it and/or modify</span>
|
||||
<span class="c1"># it under the terms of the GNU General Public License as published by</span>
|
||||
<span class="c1"># the Free Software Foundation, either version 3 of the License, or</span>
|
||||
<span class="c1"># (at your option) any later version.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Thun is distributed in the hope that it will be useful,</span>
|
||||
<span class="c1"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
|
||||
<span class="c1"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
|
||||
<span class="c1"># GNU General Public License for more details.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># You should have received a copy of the GNU General Public License</span>
|
||||
<span class="c1"># along with Thun. If not see <http://www.gnu.org/licenses/>.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd">Pretty printing support, e.g.::</span>
|
||||
|
||||
<span class="sd"> Joy? [23 18 * 99 +] trace</span>
|
||||
<span class="sd"> • 23 18 mul 99 add</span>
|
||||
<span class="sd"> 23 • 18 mul 99 add</span>
|
||||
<span class="sd"> 23 18 • mul 99 add</span>
|
||||
<span class="sd"> 414 • 99 add</span>
|
||||
<span class="sd"> 414 99 • add</span>
|
||||
<span class="sd"> 513 • </span>
|
||||
|
||||
<span class="sd"> 513 <-top</span>
|
||||
|
||||
<span class="sd"> joy? </span>
|
||||
|
||||
<span class="sd">On each line the stack is printed with the top to the left, then a</span>
|
||||
<span class="sd">bullet symbol, •, to represent the current locus of processing, then</span>
|
||||
<span class="sd">the pending expression to the right.</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="c1"># (Kinda clunky and hacky. This should be swapped out in favor of much</span>
|
||||
<span class="c1"># smarter stuff.)</span>
|
||||
<span class="kn">from</span> <span class="nn">traceback</span> <span class="kn">import</span> <span class="n">print_exc</span>
|
||||
<span class="kn">from</span> <span class="nn">.stack</span> <span class="kn">import</span> <span class="n">expression_to_string</span><span class="p">,</span> <span class="n">stack_to_string</span>
|
||||
<span class="kn">from</span> <span class="nn">..joy</span> <span class="kn">import</span> <span class="n">joy</span>
|
||||
<span class="kn">from</span> <span class="nn">..library</span> <span class="kn">import</span> <span class="n">FunctionWrapper</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="trace"><a class="viewcode-back" href="../../../pretty.html#joy.utils.pretty_print.trace">[docs]</a><span class="nd">@FunctionWrapper</span>
|
||||
<span class="k">def</span> <span class="nf">trace</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
|
||||
<span class="sd">'''Evaluate a Joy expression on a stack and print a trace.</span>
|
||||
|
||||
<span class="sd"> This function is just like the `i` combinator but it also prints a</span>
|
||||
<span class="sd"> trace of the evaluation</span>
|
||||
|
||||
<span class="sd"> :param stack stack: The stack.</span>
|
||||
<span class="sd"> :param stack expression: The expression to evaluate.</span>
|
||||
<span class="sd"> :param dict dictionary: A ``dict`` mapping names to Joy functions.</span>
|
||||
<span class="sd"> :rtype: (stack, (), dictionary)</span>
|
||||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="n">tp</span> <span class="o">=</span> <span class="n">TracePrinter</span><span class="p">()</span>
|
||||
<span class="n">quote</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">s</span><span class="p">,</span> <span class="n">_</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="n">joy</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">quote</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">,</span> <span class="n">tp</span><span class="o">.</span><span class="n">viewer</span><span class="p">)</span>
|
||||
<span class="k">except</span><span class="p">:</span>
|
||||
<span class="n">tp</span><span class="o">.</span><span class="n">print_</span><span class="p">()</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'-'</span> <span class="o">*</span> <span class="mi">73</span><span class="p">)</span>
|
||||
<span class="k">raise</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="n">tp</span><span class="o">.</span><span class="n">print_</span><span class="p">()</span>
|
||||
<span class="k">return</span> <span class="n">s</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">d</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="TracePrinter"><a class="viewcode-back" href="../../../pretty.html#joy.utils.pretty_print.TracePrinter">[docs]</a><span class="k">class</span> <span class="nc">TracePrinter</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> This is what does the formatting. You instantiate it and pass the ``viewer()``</span>
|
||||
<span class="sd"> method to the :py:func:`joy.joy.joy` function, then print it to see the</span>
|
||||
<span class="sd"> trace.</span>
|
||||
<span class="sd"> '''</span>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">history</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
|
||||
<div class="viewcode-block" id="TracePrinter.viewer"><a class="viewcode-back" href="../../../pretty.html#joy.utils.pretty_print.TracePrinter.viewer">[docs]</a> <span class="k">def</span> <span class="nf">viewer</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Record the current stack and expression in the TracePrinter's history.</span>
|
||||
<span class="sd"> Pass this method as the ``viewer`` argument to the :py:func:`joy.joy.joy` function.</span>
|
||||
|
||||
<span class="sd"> :param stack quote: A stack.</span>
|
||||
<span class="sd"> :param stack expression: A stack.</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">history</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">))</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">return</span> <span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">go</span><span class="p">())</span>
|
||||
|
||||
<div class="viewcode-block" id="TracePrinter.go"><a class="viewcode-back" href="../../../pretty.html#joy.utils.pretty_print.TracePrinter.go">[docs]</a> <span class="k">def</span> <span class="nf">go</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Return a list of strings, one for each entry in the history, prefixed</span>
|
||||
<span class="sd"> with enough spaces to align all the interpreter dots.</span>
|
||||
|
||||
<span class="sd"> This method is called internally by the ``__str__()`` method.</span>
|
||||
|
||||
<span class="sd"> :rtype: list(str)</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="n">max_stack_length</span> <span class="o">=</span> <span class="mi">0</span>
|
||||
<span class="n">lines</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">for</span> <span class="n">stack</span><span class="p">,</span> <span class="n">expression</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">history</span><span class="p">:</span>
|
||||
<span class="n">stack</span> <span class="o">=</span> <span class="n">stack_to_string</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">expression_to_string</span><span class="p">(</span><span class="n">expression</span><span class="p">)</span>
|
||||
<span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="n">n</span> <span class="o">></span> <span class="n">max_stack_length</span><span class="p">:</span>
|
||||
<span class="n">max_stack_length</span> <span class="o">=</span> <span class="n">n</span>
|
||||
<span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">n</span><span class="p">,</span> <span class="s1">'</span><span class="si">%s</span><span class="s1"> • </span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">)))</span>
|
||||
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">lines</span><span class="p">)):</span> <span class="c1"># Prefix spaces to line up '•'s.</span>
|
||||
<span class="n">length</span><span class="p">,</span> <span class="n">line</span> <span class="o">=</span> <span class="n">lines</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
|
||||
<span class="n">lines</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="s1">' '</span> <span class="o">*</span> <span class="p">(</span><span class="n">max_stack_length</span> <span class="o">-</span> <span class="n">length</span><span class="p">)</span> <span class="o">+</span> <span class="n">line</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="n">lines</span></div>
|
||||
|
||||
<span class="k">def</span> <span class="nf">print_</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
||||
<span class="k">except</span><span class="p">:</span>
|
||||
<span class="n">print_exc</span><span class="p">()</span>
|
||||
<span class="nb">print</span><span class="p">(</span><span class="s1">'Exception while printing viewer.'</span><span class="p">)</span></div>
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../../../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../notebooks/Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../notebooks/index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../../../index.html">Documentation overview</a><ul>
|
||||
<li><a href="../../index.html">Module code</a><ul>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../../../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.3.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,377 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>joy.utils.stack — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../../../_static/alabaster.css" />
|
||||
<script data-url_root="../../../" id="documentation_options" src="../../../_static/documentation_options.js"></script>
|
||||
<script src="../../../_static/jquery.js"></script>
|
||||
<script src="../../../_static/underscore.js"></script>
|
||||
<script src="../../../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../../../genindex.html" />
|
||||
<link rel="search" title="Search" href="../../../search.html" />
|
||||
|
||||
<link rel="stylesheet" href="../../../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<h1>Source code for joy.utils.stack</h1><div class="highlight"><pre>
|
||||
<span></span><span class="c1"># -*- coding: utf-8 -*-</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Copyright © 2014, 2015, 2017 Simon Forman</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># This file is part of Thun</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Thun is free software: you can redistribute it and/or modify</span>
|
||||
<span class="c1"># it under the terms of the GNU General Public License as published by</span>
|
||||
<span class="c1"># the Free Software Foundation, either version 3 of the License, or</span>
|
||||
<span class="c1"># (at your option) any later version.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># Thun is distributed in the hope that it will be useful,</span>
|
||||
<span class="c1"># but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
|
||||
<span class="c1"># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
|
||||
<span class="c1"># GNU General Public License for more details.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="c1"># You should have received a copy of the GNU General Public License</span>
|
||||
<span class="c1"># along with Thun. If not see <http://www.gnu.org/licenses/>.</span>
|
||||
<span class="c1">#</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd">When talking about Joy we use the terms "stack", "quote", "sequence",</span>
|
||||
<span class="sd">"list", and others to mean the same thing: a simple linear datatype that</span>
|
||||
<span class="sd">permits certain operations such as iterating and pushing and popping</span>
|
||||
<span class="sd">values from (at least) one end.</span>
|
||||
|
||||
<span class="sd"> In describing Joy I have used the term quotation to describe all of the</span>
|
||||
<span class="sd"> above, because I needed a word to describe the arguments to combinators</span>
|
||||
<span class="sd"> which fulfill the same role in Joy as lambda abstractions (with</span>
|
||||
<span class="sd"> variables) fulfill in the more familiar functional languages. I use the</span>
|
||||
<span class="sd"> term list for those quotations whose members are what I call literals:</span>
|
||||
<span class="sd"> numbers, characters, truth values, sets, strings and other quotations.</span>
|
||||
<span class="sd"> All these I call literals because their occurrence in code results in</span>
|
||||
<span class="sd"> them being pushed onto the stack. But I also call [London Paris] a list.</span>
|
||||
<span class="sd"> So, [dup \*] is a quotation but not a list.</span>
|
||||
|
||||
<span class="sd">`"A Conversation with Manfred von Thun" w/ Stevan Apter <http://archive.vector.org.uk/art10000350>`_ </span>
|
||||
|
||||
<span class="sd">There is no "Stack" Python class, instead we use the `cons list`_, a </span>
|
||||
<span class="sd">venerable two-tuple recursive sequence datastructure, where the</span>
|
||||
<span class="sd">empty tuple ``()`` is the empty stack and ``(head, rest)`` gives the</span>
|
||||
<span class="sd">recursive form of a stack with one or more items on it::</span>
|
||||
|
||||
<span class="sd"> stack := () | (item, stack)</span>
|
||||
|
||||
<span class="sd">Putting some numbers onto a stack::</span>
|
||||
|
||||
<span class="sd"> ()</span>
|
||||
<span class="sd"> (1, ())</span>
|
||||
<span class="sd"> (2, (1, ()))</span>
|
||||
<span class="sd"> (3, (2, (1, ())))</span>
|
||||
<span class="sd"> ...</span>
|
||||
|
||||
<span class="sd">Python has very nice "tuple packing and unpacking" in its syntax which</span>
|
||||
<span class="sd">means we can directly "unpack" the expected arguments to a Joy function.</span>
|
||||
|
||||
<span class="sd">For example::</span>
|
||||
|
||||
<span class="sd"> def dup((head, tail)):</span>
|
||||
<span class="sd"> return head, (head, tail)</span>
|
||||
|
||||
<span class="sd">We replace the argument "stack" by the expected structure of the stack,</span>
|
||||
<span class="sd">in this case "(head, tail)", and Python takes care of unpacking the</span>
|
||||
<span class="sd">incoming tuple and assigning values to the names. (Note that Python</span>
|
||||
<span class="sd">syntax doesn't require parentheses around tuples used in expressions</span>
|
||||
<span class="sd">where they would be redundant.)</span>
|
||||
|
||||
<span class="sd">Unfortunately, the Sphinx documentation generator, which is used to generate this</span>
|
||||
<span class="sd">web page, doesn't handle tuples in the function parameters. And in Python 3, this</span>
|
||||
<span class="sd">syntax was removed entirely. Instead you would have to write::</span>
|
||||
|
||||
<span class="sd"> def dup(stack):</span>
|
||||
<span class="sd"> head, tail = stack</span>
|
||||
<span class="sd"> return head, (head, tail)</span>
|
||||
|
||||
|
||||
<span class="sd">We have two very simple functions, one to build up a stack from a Python</span>
|
||||
<span class="sd">list and another to iterate through a stack and yield its items</span>
|
||||
<span class="sd">one-by-one in order. There are also two functions to generate string representations</span>
|
||||
<span class="sd">of stacks. They only differ in that one prints the terms in stack from left-to-right while the other prints from right-to-left. In both functions *internal stacks* are</span>
|
||||
<span class="sd">printed left-to-right. These functions are written to support :doc:`../pretty`.</span>
|
||||
|
||||
<span class="sd">.. _cons list: https://en.wikipedia.org/wiki/Cons#Lists</span>
|
||||
|
||||
<span class="sd">'''</span>
|
||||
<span class="kn">from</span> <span class="nn">.errors</span> <span class="kn">import</span> <span class="n">NotAListError</span>
|
||||
<span class="kn">from</span> <span class="nn">.snippets</span> <span class="kn">import</span> <span class="n">Snippet</span><span class="p">,</span> <span class="n">to_string</span> <span class="k">as</span> <span class="n">snip_to_string</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="list_to_stack"><a class="viewcode-back" href="../../../stack.html#joy.utils.stack.list_to_stack">[docs]</a><span class="k">def</span> <span class="nf">list_to_stack</span><span class="p">(</span><span class="n">el</span><span class="p">,</span> <span class="n">stack</span><span class="o">=</span><span class="p">()):</span>
|
||||
<span class="sd">'''Convert a Python list (or other sequence) to a Joy stack::</span>
|
||||
|
||||
<span class="sd"> [1, 2, 3] -> (1, (2, (3, ())))</span>
|
||||
|
||||
<span class="sd"> :param list el: A Python list or other sequence (iterators and generators</span>
|
||||
<span class="sd"> won't work because ``reverse()`` is called on ``el``.)</span>
|
||||
<span class="sd"> :param stack stack: A stack, optional, defaults to the empty stack. This</span>
|
||||
<span class="sd"> allows for concatinating Python lists (or other sequence objects)</span>
|
||||
<span class="sd"> onto an existing Joy stack.</span>
|
||||
<span class="sd"> :rtype: stack</span>
|
||||
|
||||
<span class="sd"> '''</span>
|
||||
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">el</span><span class="p">):</span>
|
||||
<span class="n">stack</span> <span class="o">=</span> <span class="n">item</span><span class="p">,</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="n">stack</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="iter_stack"><a class="viewcode-back" href="../../../stack.html#joy.utils.stack.iter_stack">[docs]</a><span class="k">def</span> <span class="nf">iter_stack</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">'''Iterate through the items on the stack.</span>
|
||||
|
||||
<span class="sd"> :param stack stack: A stack.</span>
|
||||
<span class="sd"> :rtype: iterator</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="k">while</span> <span class="n">stack</span><span class="p">:</span>
|
||||
<span class="n">item</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">yield</span> <span class="n">item</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="stack_to_string"><a class="viewcode-back" href="../../../stack.html#joy.utils.stack.stack_to_string">[docs]</a><span class="k">def</span> <span class="nf">stack_to_string</span><span class="p">(</span><span class="n">stack</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Return a "pretty print" string for a stack.</span>
|
||||
|
||||
<span class="sd"> The items are written right-to-left::</span>
|
||||
|
||||
<span class="sd"> (top, (second, ...)) -> '... second top'</span>
|
||||
|
||||
<span class="sd"> :param stack stack: A stack.</span>
|
||||
<span class="sd"> :rtype: str</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="n">f</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">stack</span><span class="p">:</span> <span class="nb">reversed</span><span class="p">(</span><span class="nb">list</span><span class="p">(</span><span class="n">iter_stack</span><span class="p">(</span><span class="n">stack</span><span class="p">)))</span>
|
||||
<span class="k">return</span> <span class="n">_to_string</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="expression_to_string"><a class="viewcode-back" href="../../../stack.html#joy.utils.stack.expression_to_string">[docs]</a><span class="k">def</span> <span class="nf">expression_to_string</span><span class="p">(</span><span class="n">expression</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Return a "pretty print" string for a expression.</span>
|
||||
|
||||
<span class="sd"> The items are written left-to-right::</span>
|
||||
|
||||
<span class="sd"> (top, (second, ...)) -> 'top second ...'</span>
|
||||
|
||||
<span class="sd"> :param stack expression: A stack.</span>
|
||||
<span class="sd"> :rtype: str</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="k">return</span> <span class="n">_to_string</span><span class="p">(</span><span class="n">expression</span><span class="p">,</span> <span class="n">iter_stack</span><span class="p">)</span></div>
|
||||
|
||||
|
||||
<span class="n">JOY_BOOL_LITERALS</span> <span class="o">=</span> <span class="s1">'false'</span><span class="p">,</span> <span class="s1">'true'</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_joy_repr</span><span class="p">(</span><span class="n">thing</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">thing</span><span class="p">,</span> <span class="nb">bool</span><span class="p">):</span> <span class="k">return</span> <span class="n">JOY_BOOL_LITERALS</span><span class="p">[</span><span class="n">thing</span><span class="p">]</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">thing</span><span class="p">,</span> <span class="n">Snippet</span><span class="p">):</span> <span class="k">return</span> <span class="n">snip_to_string</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="nb">repr</span><span class="p">(</span><span class="n">thing</span><span class="p">)</span>
|
||||
|
||||
|
||||
<span class="k">def</span> <span class="nf">_to_string</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">f</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span> <span class="k">return</span> <span class="n">_joy_repr</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="n">stack</span><span class="p">:</span> <span class="k">return</span> <span class="s1">''</span> <span class="c1"># shortcut</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">Snippet</span><span class="p">):</span> <span class="k">return</span> <span class="n">snip_to_string</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span>
|
||||
<span class="k">return</span> <span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="n">_s</span><span class="p">,</span> <span class="n">f</span><span class="p">(</span><span class="n">stack</span><span class="p">)))</span>
|
||||
|
||||
|
||||
<span class="n">_s</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">s</span><span class="p">:</span> <span class="p">(</span>
|
||||
<span class="s1">'[</span><span class="si">%s</span><span class="s1">]'</span> <span class="o">%</span> <span class="n">expression_to_string</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
|
||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">)</span>
|
||||
<span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="n">Snippet</span><span class="p">)</span>
|
||||
<span class="c1"># Is it worth making a non-tuple class for Snippet?</span>
|
||||
<span class="c1"># Doing this check on each tuple seems a bit much.</span>
|
||||
<span class="k">else</span> <span class="n">_joy_repr</span><span class="p">(</span><span class="n">s</span><span class="p">)</span>
|
||||
<span class="p">)</span>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="concat"><a class="viewcode-back" href="../../../stack.html#joy.utils.stack.concat">[docs]</a><span class="k">def</span> <span class="nf">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">):</span>
|
||||
<span class="sd">'''Concatinate quote onto expression.</span>
|
||||
|
||||
<span class="sd"> In joy [1 2] [3 4] would become [1 2 3 4].</span>
|
||||
|
||||
<span class="sd"> :param stack quote: A stack.</span>
|
||||
<span class="sd"> :param stack expression: A stack.</span>
|
||||
<span class="sd"> :rtype: stack</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="c1"># This is the fastest implementation, but will trigger</span>
|
||||
<span class="c1"># RuntimeError: maximum recursion depth exceeded</span>
|
||||
<span class="c1"># on quotes longer than sys.getrecursionlimit().</span>
|
||||
<span class="c1"># :raises RuntimeError: if quote is larger than sys.getrecursionlimit().</span>
|
||||
|
||||
<span class="c1">## return (quote[0], concat(quote[1], expression)) if quote else expression</span>
|
||||
|
||||
<span class="c1"># Original implementation.</span>
|
||||
|
||||
<span class="c1">## return list_to_stack(list(iter_stack(quote)), expression)</span>
|
||||
|
||||
<span class="c1"># In-lining is slightly faster (and won't break the</span>
|
||||
<span class="c1"># recursion limit on long quotes.)</span>
|
||||
|
||||
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">):</span>
|
||||
<span class="k">raise</span> <span class="n">NotAListError</span><span class="p">(</span><span class="s1">'Not a list.'</span><span class="p">)</span>
|
||||
<span class="n">temp</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="k">while</span> <span class="n">quote</span><span class="p">:</span>
|
||||
<span class="n">item</span><span class="p">,</span> <span class="n">quote</span> <span class="o">=</span> <span class="n">quote</span>
|
||||
<span class="n">temp</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
||||
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">temp</span><span class="p">):</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">item</span><span class="p">,</span> <span class="n">expression</span>
|
||||
<span class="k">return</span> <span class="n">expression</span></div>
|
||||
|
||||
|
||||
|
||||
<div class="viewcode-block" id="dnd"><a class="viewcode-back" href="../../../stack.html#joy.utils.stack.dnd">[docs]</a><span class="k">def</span> <span class="nf">dnd</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">from_index</span><span class="p">,</span> <span class="n">to_index</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Given a stack and two indices return a rearranged stack.</span>
|
||||
<span class="sd"> First remove the item at from_index and then insert it at to_index,</span>
|
||||
<span class="sd"> the second index is relative to the stack after removal of the item</span>
|
||||
<span class="sd"> at from_index.</span>
|
||||
|
||||
<span class="sd"> This function reuses all of the items and as much of the stack as it</span>
|
||||
<span class="sd"> can. It's meant to be used by remote clients to support drag-n-drop</span>
|
||||
<span class="sd"> rearranging of the stack from e.g. the StackListbox.</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="k">assert</span> <span class="mi">0</span> <span class="o"><=</span> <span class="n">from_index</span>
|
||||
<span class="k">assert</span> <span class="mi">0</span> <span class="o"><=</span> <span class="n">to_index</span>
|
||||
<span class="k">if</span> <span class="n">from_index</span> <span class="o">==</span> <span class="n">to_index</span><span class="p">:</span>
|
||||
<span class="k">return</span> <span class="n">stack</span>
|
||||
<span class="n">head</span><span class="p">,</span> <span class="n">n</span> <span class="o">=</span> <span class="p">[],</span> <span class="n">from_index</span>
|
||||
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||||
<span class="n">item</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="n">n</span> <span class="o">-=</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
||||
<span class="k">break</span>
|
||||
<span class="n">head</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
|
||||
<span class="k">assert</span> <span class="nb">len</span><span class="p">(</span><span class="n">head</span><span class="p">)</span> <span class="o">==</span> <span class="n">from_index</span>
|
||||
<span class="c1"># now we have two cases:</span>
|
||||
<span class="n">diff</span> <span class="o">=</span> <span class="n">from_index</span> <span class="o">-</span> <span class="n">to_index</span>
|
||||
<span class="k">if</span> <span class="n">diff</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
||||
<span class="c1"># from < to</span>
|
||||
<span class="c1"># so the destination index is still in the stack</span>
|
||||
<span class="k">while</span> <span class="n">diff</span><span class="p">:</span>
|
||||
<span class="n">h</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="n">head</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">h</span><span class="p">)</span>
|
||||
<span class="n">diff</span> <span class="o">+=</span> <span class="mi">1</span>
|
||||
<span class="k">else</span><span class="p">:</span>
|
||||
<span class="c1"># from > to</span>
|
||||
<span class="c1"># so the destination is in the head list</span>
|
||||
<span class="k">while</span> <span class="n">diff</span><span class="p">:</span>
|
||||
<span class="n">stack</span> <span class="o">=</span> <span class="n">head</span><span class="o">.</span><span class="n">pop</span><span class="p">(),</span> <span class="n">stack</span>
|
||||
<span class="n">diff</span> <span class="o">-=</span> <span class="mi">1</span>
|
||||
<span class="n">stack</span> <span class="o">=</span> <span class="n">item</span><span class="p">,</span> <span class="n">stack</span>
|
||||
<span class="k">while</span> <span class="n">head</span><span class="p">:</span>
|
||||
<span class="n">stack</span> <span class="o">=</span> <span class="n">head</span><span class="o">.</span><span class="n">pop</span><span class="p">(),</span> <span class="n">stack</span>
|
||||
<span class="k">return</span> <span class="n">stack</span></div>
|
||||
|
||||
|
||||
<div class="viewcode-block" id="pick"><a class="viewcode-back" href="../../../stack.html#joy.utils.stack.pick">[docs]</a><span class="k">def</span> <span class="nf">pick</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
|
||||
<span class="sd">'''</span>
|
||||
<span class="sd"> Return the nth item on the stack.</span>
|
||||
|
||||
<span class="sd"> :param stack stack: A stack.</span>
|
||||
<span class="sd"> :param int n: An index into the stack.</span>
|
||||
<span class="sd"> :raises ValueError: if ``n`` is less than zero.</span>
|
||||
<span class="sd"> :raises IndexError: if ``n`` is equal to or greater than the length of ``stack``.</span>
|
||||
<span class="sd"> :rtype: whatever</span>
|
||||
<span class="sd"> '''</span>
|
||||
<span class="k">if</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">ValueError</span>
|
||||
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
||||
<span class="k">try</span><span class="p">:</span>
|
||||
<span class="n">item</span><span class="p">,</span> <span class="n">stack</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
||||
<span class="k">raise</span> <span class="ne">IndexError</span>
|
||||
<span class="n">n</span> <span class="o">-=</span> <span class="mi">1</span>
|
||||
<span class="k">if</span> <span class="n">n</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
||||
<span class="k">break</span>
|
||||
<span class="k">return</span> <span class="n">item</span></div>
|
||||
</pre></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../../../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../notebooks/Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../../../notebooks/index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../../../index.html">Documentation overview</a><ul>
|
||||
<li><a href="../../index.html">Module code</a><ul>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../../../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
.. Thun documentation master file, created by
|
||||
sphinx-quickstart on Sun Apr 22 15:19:55 2018.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Thun |release| Documentation
|
||||
============================
|
||||
|
||||
Thun is dialect of Joy written in Python.
|
||||
|
||||
`Joy`_ is a programming language created by Manfred von Thun that is easy to
|
||||
use and understand and has many other nice properties. This Python
|
||||
package implements an interpreter for a dialect of Joy that attempts to
|
||||
stay very close to the spirit of Joy but does not precisely match the
|
||||
behaviour of the original version(s) written in C. The main difference
|
||||
between Thun and the originals, other than being written in Python, is
|
||||
that it works by the "Continuation-Passing Style".
|
||||
|
||||
Joy is:
|
||||
|
||||
* `Purely Functional <https://en.wikipedia.org/wiki/Purely_functional_programming>`__
|
||||
* `Stack-based <https://en.wikipedia.org/wiki/Stack-oriented_programming_language>`__
|
||||
* `Concatinative`_ ( See also `concatenative.org <http://www.concatenative.org/wiki/view/Concatenative%20language>`__)
|
||||
* :doc:`Categorical <notebooks/Categorical>`
|
||||
|
||||
I hope that this package is useful in the sense that it provides an
|
||||
additional joy interpreter (the binary in the archive from La Trobe seems
|
||||
to run just fine on my modern Linux machine!) But I also hope that you
|
||||
can read and understand the Python code and play with the implementation
|
||||
itself.
|
||||
|
||||
.. _Joy: https://en.wikipedia.org/wiki/Joy_(programming_language)
|
||||
|
||||
.. _Concatinative: https://en.wikipedia.org/wiki/Concatenative_programming_language
|
||||
|
||||
|
||||
Example Code
|
||||
--------------------------------------------------
|
||||
|
||||
Here is an example of Joy code::
|
||||
|
||||
[[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
|
||||
|
||||
It might seem unreadable but with a little familiarity it becomes just as
|
||||
legible as any other notation. Some layout helps::
|
||||
|
||||
[ [[abs] ii <=]
|
||||
[
|
||||
[<>] [pop !-] ||
|
||||
] &&
|
||||
]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
This function accepts two integers on the stack and increments or
|
||||
decrements one of them such that the new pair of numbers is the next
|
||||
coordinate pair in a square spiral (like the kind used to construct an
|
||||
`Ulam Spiral`_). For more information see :doc:`notebooks/Square_Spiral`
|
||||
|
||||
.. _Ulam Spiral: https://en.wikipedia.org/wiki/Ulam_spiral
|
||||
|
||||
|
||||
Quick Start
|
||||
--------------------------------------------------
|
||||
|
||||
Install from `PyPI`_ in the usual way::
|
||||
|
||||
$ pip install Thun
|
||||
|
||||
To start the REPL::
|
||||
|
||||
$ python -m joy
|
||||
|
||||
Continue with :doc:`the introduction <notebooks/Intro>`.
|
||||
|
||||
.. _PyPI: https://pypi.org/project/Thun/
|
||||
|
||||
|
||||
Project Hosted on `OSDN`_
|
||||
-------------------------
|
||||
|
||||
* `Source Repository`_ (`mirror`_)
|
||||
* `Bug tracker`_ (`old tracker`_)
|
||||
* `Forums`_
|
||||
* `Mailing list`_
|
||||
|
||||
.. _Bug tracker: https://todo.sr.ht/~sforman/thun-der
|
||||
.. _old tracker: https://osdn.net/projects/joypy/ticket/
|
||||
.. _Forums: https://osdn.net/projects/joypy/forums/
|
||||
.. _Mailing list: https://osdn.net/projects/joypy/lists/
|
||||
.. _OSDN: https://osdn.net/projects/joypy/
|
||||
.. _Source Repository: https://osdn.net/projects/joypy/scm/git/Thun/
|
||||
.. _mirror: https://github.com/calroc/Thun
|
||||
|
||||
|
||||
Information on the Joy language
|
||||
-------------------------------
|
||||
|
||||
See `the Wikipedia article`_ and `Kevin Albrecht's mirror of Manfred von Thun's original website for the Joy Programming Language`_ for more information on the Joy language.
|
||||
|
||||
The best source (no pun intended) for learning about Joy is the
|
||||
information made available at the website of La Trobe University (see the
|
||||
mirror link above) which contains source code for the
|
||||
original C interpreter, Joy language source code for various functions,
|
||||
and a great deal of fascinating material mostly written by Von Thun on
|
||||
Joy and its deeper facets as well as how to program in it and several
|
||||
interesting aspects. It's quite a treasure trove.
|
||||
|
||||
.. _the Wikipedia article: https://en.wikipedia.org/wiki/Joy_(programming_language)
|
||||
|
||||
.. _Kevin Albrecht's mirror of Manfred von Thun's original website for the Joy Programming Language: http://www.kevinalbrecht.com/code/joy-mirror/index.html
|
||||
|
||||
|
||||
Documentation on Thun Dialect
|
||||
-----------------------------
|
||||
|
||||
The following is specific information for this dialect of Joy.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
notebooks/Intro
|
||||
joy
|
||||
stack
|
||||
parser
|
||||
pretty
|
||||
library
|
||||
lib
|
||||
types
|
||||
notebooks/index
|
||||
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
Joy Interpreter
|
||||
===============
|
||||
|
||||
|
||||
``joy.joy``
|
||||
---------------
|
||||
|
||||
|
||||
.. automodule:: joy.joy
|
||||
:members:
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
Function Reference
|
||||
======================================
|
||||
|
||||
|
||||
``joy.library``
|
||||
----------------------
|
||||
|
||||
|
||||
.. automodule:: joy.library
|
||||
:members:
|
||||
|
||||
|
||||
Auto-generated Functions
|
||||
---------------------------
|
||||
|
||||
.. automodule:: joy.utils.generated_library
|
||||
:members:
|
||||
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
|
||||
***********************
|
||||
Categorical Programming
|
||||
***********************
|
||||
|
||||
DRAFT
|
||||
|
||||
`Categorical <https://en.wikipedia.org/wiki/Category_theory>`__
|
||||
|
||||
In Manfred von Thun's article `Joy compared with other functional languages <http://www.kevinalbrecht.com/code/joy-mirror/j08cnt.html>`__ he asks, "Could the language of categories be used for writing programs? Any lambda expression can be translated into a categorical expression, so the language of categories is expressively complete. But this does not make it a suitable language for writing programs. As it stands it is a very low-level language."
|
||||
|
||||
In `Compiling to categories <http://conal.net/papers/compiling-to-categories/>`__ Conal Elliott give a taste of what this might mean.
|
||||
|
||||
It is well-known that the simply typed lambda-calculus is modeled by any cartesian closed category (CCC). This correspondence suggests giving typed functional programs a variety of interpretations, each corresponding to a different category. A convenient way to realize this idea is as a collection of meaning-preserving transformations added to an existing compiler, such as GHC for Haskell. This paper describes such an implementation and demonstrates its use for a variety of interpretations including hardware circuits, automatic differentiation, incremental computation, and interval analysis. Each such interpretation is a category easily defined in Haskell (outside of the compiler). The general technique appears to provide a compelling alternative to deeply embedded domain-specific languages.
|
||||
|
||||
What he's doing is translating lambda forms into a kind of "point-free" style that is very close to Joy code (although more verbose) and then showing how to instantiate that code over different categories to get several different kinds of program out of the same code.
|
||||
|
||||
|
|
@ -1,946 +0,0 @@
|
|||
∂RE
|
||||
===
|
||||
|
||||
Brzozowski’s Derivatives of Regular Expressions
|
||||
-----------------------------------------------
|
||||
|
||||
Legend:
|
||||
|
||||
::
|
||||
|
||||
∧ intersection
|
||||
∨ union
|
||||
∘ concatenation (see below)
|
||||
¬ complement
|
||||
ϕ empty set (aka ∅)
|
||||
λ singleton set containing just the empty string
|
||||
I set of all letters in alphabet
|
||||
|
||||
Derivative of a set ``R`` of strings and a string ``a``:
|
||||
|
||||
::
|
||||
|
||||
∂a(R)
|
||||
|
||||
∂a(a) → λ
|
||||
∂a(λ) → ϕ
|
||||
∂a(ϕ) → ϕ
|
||||
∂a(¬a) → ϕ
|
||||
∂a(R*) → ∂a(R)∘R*
|
||||
∂a(¬R) → ¬∂a(R)
|
||||
∂a(R∘S) → ∂a(R)∘S ∨ δ(R)∘∂a(S)
|
||||
∂a(R ∧ S) → ∂a(R) ∧ ∂a(S)
|
||||
∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
|
||||
∂ab(R) = ∂b(∂a(R))
|
||||
|
||||
Auxiliary predicate function ``δ`` (I call it ``nully``) returns either
|
||||
``λ`` if ``λ ⊆ R`` or ``ϕ`` otherwise:
|
||||
|
||||
::
|
||||
|
||||
δ(a) → ϕ
|
||||
δ(λ) → λ
|
||||
δ(ϕ) → ϕ
|
||||
δ(R*) → λ
|
||||
δ(¬R) δ(R)≟ϕ → λ
|
||||
δ(¬R) δ(R)≟λ → ϕ
|
||||
δ(R∘S) → δ(R) ∧ δ(S)
|
||||
δ(R ∧ S) → δ(R) ∧ δ(S)
|
||||
δ(R ∨ S) → δ(R) ∨ δ(S)
|
||||
|
||||
Some rules we will use later for “compaction”:
|
||||
|
||||
::
|
||||
|
||||
R ∧ ϕ = ϕ ∧ R = ϕ
|
||||
|
||||
R ∧ I = I ∧ R = R
|
||||
|
||||
R ∨ ϕ = ϕ ∨ R = R
|
||||
|
||||
R ∨ I = I ∨ R = I
|
||||
|
||||
R∘ϕ = ϕ∘R = ϕ
|
||||
|
||||
R∘λ = λ∘R = R
|
||||
|
||||
Concatination of sets: for two sets A and B the set A∘B is defined as:
|
||||
|
||||
{a∘b for a in A for b in B}
|
||||
|
||||
E.g.:
|
||||
|
||||
{‘a’, ‘b’}∘{‘c’, ‘d’} → {‘ac’, ‘ad’, ‘bc’, ‘bd’}
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from functools import partial as curry
|
||||
from itertools import product
|
||||
|
||||
``ϕ`` and ``λ``
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The empty set and the set of just the empty string.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
phi = frozenset() # ϕ
|
||||
y = frozenset({''}) # λ
|
||||
|
||||
Two-letter Alphabet
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
I’m only going to use two symbols (at first) becaase this is enough to
|
||||
illustrate the algorithm and because you can represent any other
|
||||
alphabet with two symbols (if you had to.)
|
||||
|
||||
I chose the names ``O`` and ``l`` (uppercase “o” and lowercase “L”) to
|
||||
look like ``0`` and ``1`` (zero and one) respectively.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
syms = O, l = frozenset({'0'}), frozenset({'1'})
|
||||
|
||||
Representing Regular Expressions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To represent REs in Python I’m going to use tagged tuples. A *regular
|
||||
expression* is one of:
|
||||
|
||||
::
|
||||
|
||||
O
|
||||
l
|
||||
(KSTAR, R)
|
||||
(NOT, R)
|
||||
(AND, R, S)
|
||||
(CONS, R, S)
|
||||
(OR, R, S)
|
||||
|
||||
Where ``R`` and ``S`` stand for *regular expressions*.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
AND, CONS, KSTAR, NOT, OR = 'and cons * not or'.split() # Tags are just strings.
|
||||
|
||||
Because they are formed of ``frozenset``, ``tuple`` and ``str`` objects
|
||||
only, these datastructures are immutable.
|
||||
|
||||
String Representation of RE Datastructures
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def stringy(re):
|
||||
'''
|
||||
Return a nice string repr for a regular expression datastructure.
|
||||
'''
|
||||
if re == I: return '.'
|
||||
if re in syms: return next(iter(re))
|
||||
if re == y: return '^'
|
||||
if re == phi: return 'X'
|
||||
|
||||
assert isinstance(re, tuple), repr(re)
|
||||
tag = re[0]
|
||||
|
||||
if tag == KSTAR:
|
||||
body = stringy(re[1])
|
||||
if not body: return body
|
||||
if len(body) > 1: return '(' + body + ")*"
|
||||
return body + '*'
|
||||
|
||||
if tag == NOT:
|
||||
body = stringy(re[1])
|
||||
if not body: return body
|
||||
if len(body) > 1: return '(' + body + ")'"
|
||||
return body + "'"
|
||||
|
||||
r, s = stringy(re[1]), stringy(re[2])
|
||||
if tag == CONS: return r + s
|
||||
if tag == OR: return '%s | %s' % (r, s)
|
||||
if tag == AND: return '(%s) & (%s)' % (r, s)
|
||||
|
||||
raise ValueError
|
||||
|
||||
``I``
|
||||
~~~~~
|
||||
|
||||
Match anything. Often spelled “.”
|
||||
|
||||
::
|
||||
|
||||
I = (0|1)*
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
I = (KSTAR, (OR, O, l))
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
print stringy(I)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
.
|
||||
|
||||
|
||||
``(.111.) & (.01 + 11*)'``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The example expression from Brzozowski:
|
||||
|
||||
::
|
||||
|
||||
(.111.) & (.01 + 11*)'
|
||||
a & (b + c)'
|
||||
|
||||
Note that it contains one of everything.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
a = (CONS, I, (CONS, l, (CONS, l, (CONS, l, I))))
|
||||
b = (CONS, I, (CONS, O, l))
|
||||
c = (CONS, l, (KSTAR, l))
|
||||
it = (AND, a, (NOT, (OR, b, c)))
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
print stringy(it)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
(.111.) & ((.01 | 11*)')
|
||||
|
||||
|
||||
``nully()``
|
||||
~~~~~~~~~~~
|
||||
|
||||
Let’s get that auxiliary predicate function ``δ`` out of the way.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def nully(R):
|
||||
'''
|
||||
δ - Return λ if λ ⊆ R otherwise ϕ.
|
||||
'''
|
||||
|
||||
# δ(a) → ϕ
|
||||
# δ(ϕ) → ϕ
|
||||
if R in syms or R == phi:
|
||||
return phi
|
||||
|
||||
# δ(λ) → λ
|
||||
if R == y:
|
||||
return y
|
||||
|
||||
tag = R[0]
|
||||
|
||||
# δ(R*) → λ
|
||||
if tag == KSTAR:
|
||||
return y
|
||||
|
||||
# δ(¬R) δ(R)≟ϕ → λ
|
||||
# δ(¬R) δ(R)≟λ → ϕ
|
||||
if tag == NOT:
|
||||
return phi if nully(R[1]) else y
|
||||
|
||||
# δ(R∘S) → δ(R) ∧ δ(S)
|
||||
# δ(R ∧ S) → δ(R) ∧ δ(S)
|
||||
# δ(R ∨ S) → δ(R) ∨ δ(S)
|
||||
r, s = nully(R[1]), nully(R[2])
|
||||
return r & s if tag in {AND, CONS} else r | s
|
||||
|
||||
No “Compaction”
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
This is the straightforward version with no “compaction”. It works fine,
|
||||
but does waaaay too much work because the expressions grow each
|
||||
derivation.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def D(symbol):
|
||||
|
||||
def derv(R):
|
||||
|
||||
# ∂a(a) → λ
|
||||
if R == {symbol}:
|
||||
return y
|
||||
|
||||
# ∂a(λ) → ϕ
|
||||
# ∂a(ϕ) → ϕ
|
||||
# ∂a(¬a) → ϕ
|
||||
if R == y or R == phi or R in syms:
|
||||
return phi
|
||||
|
||||
tag = R[0]
|
||||
|
||||
# ∂a(R*) → ∂a(R)∘R*
|
||||
if tag == KSTAR:
|
||||
return (CONS, derv(R[1]), R)
|
||||
|
||||
# ∂a(¬R) → ¬∂a(R)
|
||||
if tag == NOT:
|
||||
return (NOT, derv(R[1]))
|
||||
|
||||
r, s = R[1:]
|
||||
|
||||
# ∂a(R∘S) → ∂a(R)∘S ∨ δ(R)∘∂a(S)
|
||||
if tag == CONS:
|
||||
A = (CONS, derv(r), s) # A = ∂a(R)∘S
|
||||
# A ∨ δ(R) ∘ ∂a(S)
|
||||
# A ∨ λ ∘ ∂a(S) → A ∨ ∂a(S)
|
||||
# A ∨ ϕ ∘ ∂a(S) → A ∨ ϕ → A
|
||||
return (OR, A, derv(s)) if nully(r) else A
|
||||
|
||||
# ∂a(R ∧ S) → ∂a(R) ∧ ∂a(S)
|
||||
# ∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
return (tag, derv(r), derv(s))
|
||||
|
||||
return derv
|
||||
|
||||
Compaction Rules
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def _compaction_rule(relation, one, zero, a, b):
|
||||
return (
|
||||
b if a == one else # R*1 = 1*R = R
|
||||
a if b == one else
|
||||
zero if a == zero or b == zero else # R*0 = 0*R = 0
|
||||
(relation, a, b)
|
||||
)
|
||||
|
||||
An elegant symmetry.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
# R ∧ I = I ∧ R = R
|
||||
# R ∧ ϕ = ϕ ∧ R = ϕ
|
||||
_and = curry(_compaction_rule, AND, I, phi)
|
||||
|
||||
# R ∨ ϕ = ϕ ∨ R = R
|
||||
# R ∨ I = I ∨ R = I
|
||||
_or = curry(_compaction_rule, OR, phi, I)
|
||||
|
||||
# R∘λ = λ∘R = R
|
||||
# R∘ϕ = ϕ∘R = ϕ
|
||||
_cons = curry(_compaction_rule, CONS, y, phi)
|
||||
|
||||
Memoizing
|
||||
~~~~~~~~~
|
||||
|
||||
We can save re-processing by remembering results we have already
|
||||
computed. RE datastructures are immutable and the ``derv()`` functions
|
||||
are *pure* so this is fine.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
class Memo(object):
|
||||
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
self.calls = self.hits = 0
|
||||
self.mem = {}
|
||||
|
||||
def __call__(self, key):
|
||||
self.calls += 1
|
||||
try:
|
||||
result = self.mem[key]
|
||||
self.hits += 1
|
||||
except KeyError:
|
||||
result = self.mem[key] = self.f(key)
|
||||
return result
|
||||
|
||||
With “Compaction”
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
This version uses the rules above to perform compaction. It keeps the
|
||||
expressions from growing too large.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def D_compaction(symbol):
|
||||
|
||||
@Memo
|
||||
def derv(R):
|
||||
|
||||
# ∂a(a) → λ
|
||||
if R == {symbol}:
|
||||
return y
|
||||
|
||||
# ∂a(λ) → ϕ
|
||||
# ∂a(ϕ) → ϕ
|
||||
# ∂a(¬a) → ϕ
|
||||
if R == y or R == phi or R in syms:
|
||||
return phi
|
||||
|
||||
tag = R[0]
|
||||
|
||||
# ∂a(R*) → ∂a(R)∘R*
|
||||
if tag == KSTAR:
|
||||
return _cons(derv(R[1]), R)
|
||||
|
||||
# ∂a(¬R) → ¬∂a(R)
|
||||
if tag == NOT:
|
||||
return (NOT, derv(R[1]))
|
||||
|
||||
r, s = R[1:]
|
||||
|
||||
# ∂a(R∘S) → ∂a(R)∘S ∨ δ(R)∘∂a(S)
|
||||
if tag == CONS:
|
||||
A = _cons(derv(r), s) # A = ∂a(r)∘s
|
||||
# A ∨ δ(R) ∘ ∂a(S)
|
||||
# A ∨ λ ∘ ∂a(S) → A ∨ ∂a(S)
|
||||
# A ∨ ϕ ∘ ∂a(S) → A ∨ ϕ → A
|
||||
return _or(A, derv(s)) if nully(r) else A
|
||||
|
||||
# ∂a(R ∧ S) → ∂a(R) ∧ ∂a(S)
|
||||
# ∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
dr, ds = derv(r), derv(s)
|
||||
return _and(dr, ds) if tag == AND else _or(dr, ds)
|
||||
|
||||
return derv
|
||||
|
||||
Let’s try it out…
|
||||
-----------------
|
||||
|
||||
(FIXME: redo.)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
o, z = D_compaction('0'), D_compaction('1')
|
||||
REs = set()
|
||||
N = 5
|
||||
names = list(product(*(N * [(0, 1)])))
|
||||
dervs = list(product(*(N * [(o, z)])))
|
||||
for name, ds in zip(names, dervs):
|
||||
R = it
|
||||
ds = list(ds)
|
||||
while ds:
|
||||
R = ds.pop()(R)
|
||||
if R == phi or R == I:
|
||||
break
|
||||
REs.add(R)
|
||||
|
||||
print stringy(it) ; print
|
||||
print o.hits, '/', o.calls
|
||||
print z.hits, '/', z.calls
|
||||
print
|
||||
for s in sorted(map(stringy, REs), key=lambda n: (len(n), n)):
|
||||
print s
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
(.111.) & ((.01 | 11*)')
|
||||
|
||||
92 / 122
|
||||
92 / 122
|
||||
|
||||
(.01)'
|
||||
(.01 | 1)'
|
||||
(.01 | ^)'
|
||||
(.01 | 1*)'
|
||||
(.111.) & ((.01 | 1)')
|
||||
(.111. | 11.) & ((.01 | ^)')
|
||||
(.111. | 11. | 1.) & ((.01)')
|
||||
(.111. | 11.) & ((.01 | 1*)')
|
||||
(.111. | 11. | 1.) & ((.01 | 1*)')
|
||||
|
||||
|
||||
Should match:
|
||||
|
||||
::
|
||||
|
||||
(.111.) & ((.01 | 11*)')
|
||||
|
||||
92 / 122
|
||||
92 / 122
|
||||
|
||||
(.01 )'
|
||||
(.01 | 1 )'
|
||||
(.01 | ^ )'
|
||||
(.01 | 1*)'
|
||||
(.111.) & ((.01 | 1 )')
|
||||
(.111. | 11.) & ((.01 | ^ )')
|
||||
(.111. | 11.) & ((.01 | 1*)')
|
||||
(.111. | 11. | 1.) & ((.01 )')
|
||||
(.111. | 11. | 1.) & ((.01 | 1*)')
|
||||
|
||||
Larger Alphabets
|
||||
----------------
|
||||
|
||||
We could parse larger alphabets by defining patterns for e.g. each byte
|
||||
of the ASCII code. Or we can generalize this code. If you study the code
|
||||
above you’ll see that we never use the “set-ness” of the symbols ``O``
|
||||
and ``l``. The only time Python set operators (``&`` and ``|``) appear
|
||||
is in the ``nully()`` function, and there they operate on (recursively
|
||||
computed) outputs of that function, never ``O`` and ``l``.
|
||||
|
||||
What if we try:
|
||||
|
||||
::
|
||||
|
||||
(OR, O, l)
|
||||
|
||||
∂1((OR, O, l))
|
||||
∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
∂1(O) ∨ ∂1(l)
|
||||
∂a(¬a) → ϕ
|
||||
ϕ ∨ ∂1(l)
|
||||
∂a(a) → λ
|
||||
ϕ ∨ λ
|
||||
ϕ ∨ R = R
|
||||
λ
|
||||
|
||||
And compare it to:
|
||||
|
||||
::
|
||||
|
||||
{'0', '1')
|
||||
|
||||
∂1({'0', '1'))
|
||||
∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
∂1({'0')) ∨ ∂1({'1'))
|
||||
∂a(¬a) → ϕ
|
||||
ϕ ∨ ∂1({'1'))
|
||||
∂a(a) → λ
|
||||
ϕ ∨ λ
|
||||
ϕ ∨ R = R
|
||||
λ
|
||||
|
||||
This suggests that we should be able to alter the functions above to
|
||||
detect sets and deal with them appropriately. Exercise for the Reader
|
||||
for now.
|
||||
|
||||
State Machine
|
||||
-------------
|
||||
|
||||
We can drive the regular expressions to flesh out the underlying state
|
||||
machine transition table.
|
||||
|
||||
::
|
||||
|
||||
.111. & (.01 + 11*)'
|
||||
|
||||
Says, “Three or more 1’s and not ending in 01 nor composed of all 1’s.”
|
||||
|
||||
.. figure:: omg.svg
|
||||
:alt: State Machine Graph
|
||||
|
||||
State Machine Graph
|
||||
|
||||
Start at ``a`` and follow the transition arrows according to their
|
||||
labels. Accepting states have a double outline. (Graphic generated with
|
||||
`Dot from Graphviz <http://www.graphviz.org/>`__.) You’ll see that only
|
||||
paths that lead to one of the accepting states will match the regular
|
||||
expression. All other paths will terminate at one of the non-accepting
|
||||
states.
|
||||
|
||||
There’s a happy path to ``g`` along 111:
|
||||
|
||||
::
|
||||
|
||||
a→c→e→g
|
||||
|
||||
After you reach ``g`` you’re stuck there eating 1’s until you see a 0,
|
||||
which takes you to the ``i→j→i|i→j→h→i`` “trap”. You can’t reach any
|
||||
other states from those two loops.
|
||||
|
||||
If you see a 0 before you see 111 you will reach ``b``, which forms
|
||||
another “trap” with ``d`` and ``f``. The only way out is another happy
|
||||
path along 111 to ``h``:
|
||||
|
||||
::
|
||||
|
||||
b→d→f→h
|
||||
|
||||
Once you have reached ``h`` you can see as many 1’s or as many 0’ in a
|
||||
row and still be either still at ``h`` (for 1’s) or move to ``i`` (for
|
||||
0’s). If you find yourself at ``i`` you can see as many 0’s, or
|
||||
repetitions of 10, as there are, but if you see just a 1 you move to
|
||||
``j``.
|
||||
|
||||
RE to FSM
|
||||
~~~~~~~~~
|
||||
|
||||
So how do we get the state machine from the regular expression?
|
||||
|
||||
It turns out that each RE is effectively a state, and each arrow points
|
||||
to the derivative RE in respect to the arrow’s symbol.
|
||||
|
||||
If we label the initial RE ``a``, we can say:
|
||||
|
||||
::
|
||||
|
||||
a --0--> ∂0(a)
|
||||
a --1--> ∂1(a)
|
||||
|
||||
And so on, each new unique RE is a new state in the FSM table.
|
||||
|
||||
Here are the derived REs at each state:
|
||||
|
||||
::
|
||||
|
||||
a = (.111.) & ((.01 | 11*)')
|
||||
b = (.111.) & ((.01 | 1)')
|
||||
c = (.111. | 11.) & ((.01 | 1*)')
|
||||
d = (.111. | 11.) & ((.01 | ^)')
|
||||
e = (.111. | 11. | 1.) & ((.01 | 1*)')
|
||||
f = (.111. | 11. | 1.) & ((.01)')
|
||||
g = (.01 | 1*)'
|
||||
h = (.01)'
|
||||
i = (.01 | 1)'
|
||||
j = (.01 | ^)'
|
||||
|
||||
You can see the one-way nature of the ``g`` state and the ``hij`` “trap”
|
||||
in the way that the ``.111.`` on the left-hand side of the ``&``
|
||||
disappears once it has been matched.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from collections import defaultdict
|
||||
from pprint import pprint
|
||||
from string import ascii_lowercase
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
d0, d1 = D_compaction('0'), D_compaction('1')
|
||||
|
||||
``explore()``
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def explore(re):
|
||||
|
||||
# Don't have more than 26 states...
|
||||
names = defaultdict(iter(ascii_lowercase).next)
|
||||
|
||||
table, accepting = dict(), set()
|
||||
|
||||
to_check = {re}
|
||||
while to_check:
|
||||
|
||||
re = to_check.pop()
|
||||
state_name = names[re]
|
||||
|
||||
if (state_name, 0) in table:
|
||||
continue
|
||||
|
||||
if nully(re):
|
||||
accepting.add(state_name)
|
||||
|
||||
o, i = d0(re), d1(re)
|
||||
table[state_name, 0] = names[o] ; to_check.add(o)
|
||||
table[state_name, 1] = names[i] ; to_check.add(i)
|
||||
|
||||
return table, accepting
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
table, accepting = explore(it)
|
||||
table
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
{('a', 0): 'b',
|
||||
('a', 1): 'c',
|
||||
('b', 0): 'b',
|
||||
('b', 1): 'd',
|
||||
('c', 0): 'b',
|
||||
('c', 1): 'e',
|
||||
('d', 0): 'b',
|
||||
('d', 1): 'f',
|
||||
('e', 0): 'b',
|
||||
('e', 1): 'g',
|
||||
('f', 0): 'b',
|
||||
('f', 1): 'h',
|
||||
('g', 0): 'i',
|
||||
('g', 1): 'g',
|
||||
('h', 0): 'i',
|
||||
('h', 1): 'h',
|
||||
('i', 0): 'i',
|
||||
('i', 1): 'j',
|
||||
('j', 0): 'i',
|
||||
('j', 1): 'h'}
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
accepting
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
{'h', 'i'}
|
||||
|
||||
|
||||
|
||||
Generate Diagram
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Once we have the FSM table and the set of accepting states we can
|
||||
generate the diagram above.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
_template = '''\
|
||||
digraph finite_state_machine {
|
||||
rankdir=LR;
|
||||
size="8,5"
|
||||
node [shape = doublecircle]; %s;
|
||||
node [shape = circle];
|
||||
%s
|
||||
}
|
||||
'''
|
||||
|
||||
def link(fr, nm, label):
|
||||
return ' %s -> %s [ label = "%s" ];' % (fr, nm, label)
|
||||
|
||||
|
||||
def make_graph(table, accepting):
|
||||
return _template % (
|
||||
' '.join(accepting),
|
||||
'\n'.join(
|
||||
link(from_, to, char)
|
||||
for (from_, char), (to) in sorted(table.iteritems())
|
||||
)
|
||||
)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
print make_graph(table, accepting)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
digraph finite_state_machine {
|
||||
rankdir=LR;
|
||||
size="8,5"
|
||||
node [shape = doublecircle]; i h;
|
||||
node [shape = circle];
|
||||
a -> b [ label = "0" ];
|
||||
a -> c [ label = "1" ];
|
||||
b -> b [ label = "0" ];
|
||||
b -> d [ label = "1" ];
|
||||
c -> b [ label = "0" ];
|
||||
c -> e [ label = "1" ];
|
||||
d -> b [ label = "0" ];
|
||||
d -> f [ label = "1" ];
|
||||
e -> b [ label = "0" ];
|
||||
e -> g [ label = "1" ];
|
||||
f -> b [ label = "0" ];
|
||||
f -> h [ label = "1" ];
|
||||
g -> i [ label = "0" ];
|
||||
g -> g [ label = "1" ];
|
||||
h -> i [ label = "0" ];
|
||||
h -> h [ label = "1" ];
|
||||
i -> i [ label = "0" ];
|
||||
i -> j [ label = "1" ];
|
||||
j -> i [ label = "0" ];
|
||||
j -> h [ label = "1" ];
|
||||
}
|
||||
|
||||
|
||||
|
||||
Drive a FSM
|
||||
~~~~~~~~~~~
|
||||
|
||||
There are *lots* of FSM libraries already. Once you have the state
|
||||
transition table they should all be straightforward to use. State
|
||||
Machine code is very simple. Just for fun, here is an implementation in
|
||||
Python that imitates what “compiled” FSM code might look like in an
|
||||
“unrolled” form. Most FSM code uses a little driver loop and a table
|
||||
datastructure, the code below instead acts like JMP instructions
|
||||
(“jump”, or GOTO in higher-level-but-still-low-level languages) to
|
||||
hard-code the information in the table into a little patch of branches.
|
||||
|
||||
Trampoline Function
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Python has no GOTO statement but we can fake it with a “trampoline”
|
||||
function.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def trampoline(input_, jump_from, accepting):
|
||||
I = iter(input_)
|
||||
while True:
|
||||
try:
|
||||
bounce_to = jump_from(I)
|
||||
except StopIteration:
|
||||
return jump_from in accepting
|
||||
jump_from = bounce_to
|
||||
|
||||
Stream Functions
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
Little helpers to process the iterator of our data (a “stream” of “1”
|
||||
and “0” characters, not bits.)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
getch = lambda I: int(next(I))
|
||||
|
||||
|
||||
def _1(I):
|
||||
'''Loop on ones.'''
|
||||
while getch(I): pass
|
||||
|
||||
|
||||
def _0(I):
|
||||
'''Loop on zeros.'''
|
||||
while not getch(I): pass
|
||||
|
||||
A Finite State Machine
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
With those preliminaries out of the way, from the state table of
|
||||
``.111. & (.01 + 11*)'`` we can immediately write down state machine
|
||||
code. (You have to imagine that these are GOTO statements in C or
|
||||
branches in assembly and that the state names are branch destination
|
||||
labels.)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
a = lambda I: c if getch(I) else b
|
||||
b = lambda I: _0(I) or d
|
||||
c = lambda I: e if getch(I) else b
|
||||
d = lambda I: f if getch(I) else b
|
||||
e = lambda I: g if getch(I) else b
|
||||
f = lambda I: h if getch(I) else b
|
||||
g = lambda I: _1(I) or i
|
||||
h = lambda I: _1(I) or i
|
||||
i = lambda I: _0(I) or j
|
||||
j = lambda I: h if getch(I) else i
|
||||
|
||||
Note that the implementations of ``h`` and ``g`` are identical ergo
|
||||
``h = g`` and we could eliminate one in the code but ``h`` is an
|
||||
accepting state and ``g`` isn’t.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def acceptable(input_):
|
||||
return trampoline(input_, a, {h, i})
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
for n in range(2**5):
|
||||
s = bin(n)[2:]
|
||||
print '%05s' % s, acceptable(s)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
0 False
|
||||
1 False
|
||||
10 False
|
||||
11 False
|
||||
100 False
|
||||
101 False
|
||||
110 False
|
||||
111 False
|
||||
1000 False
|
||||
1001 False
|
||||
1010 False
|
||||
1011 False
|
||||
1100 False
|
||||
1101 False
|
||||
1110 True
|
||||
1111 False
|
||||
10000 False
|
||||
10001 False
|
||||
10010 False
|
||||
10011 False
|
||||
10100 False
|
||||
10101 False
|
||||
10110 False
|
||||
10111 True
|
||||
11000 False
|
||||
11001 False
|
||||
11010 False
|
||||
11011 False
|
||||
11100 True
|
||||
11101 False
|
||||
11110 True
|
||||
11111 False
|
||||
|
||||
|
||||
Reversing the Derivatives to Generate Matching Strings
|
||||
------------------------------------------------------
|
||||
|
||||
(UNFINISHED) Brzozowski also shewed how to go from the state machine to
|
||||
strings and expressions…
|
||||
|
||||
Each of these states is just a name for a Brzozowskian RE, and so, other
|
||||
than the initial state ``a``, they can can be described in terms of the
|
||||
derivative-with-respect-to-N of some other state/RE:
|
||||
|
||||
::
|
||||
|
||||
c = d1(a)
|
||||
b = d0(a)
|
||||
b = d0(c)
|
||||
...
|
||||
i = d0(j)
|
||||
j = d1(i)
|
||||
|
||||
Consider:
|
||||
|
||||
::
|
||||
|
||||
c = d1(a)
|
||||
b = d0(c)
|
||||
|
||||
Substituting:
|
||||
|
||||
::
|
||||
|
||||
b = d0(d1(a))
|
||||
|
||||
Unwrapping:
|
||||
|
||||
::
|
||||
|
||||
b = d10(a)
|
||||
|
||||
’’’
|
||||
|
||||
::
|
||||
|
||||
j = d1(d0(j))
|
||||
|
||||
Unwrapping:
|
||||
|
||||
::
|
||||
|
||||
j = d1(d0(j)) = d01(j)
|
||||
|
||||
We have a loop or “fixed point”.
|
||||
|
||||
::
|
||||
|
||||
j = d01(j) = d0101(j) = d010101(j) = ...
|
||||
|
||||
hmm…
|
||||
|
||||
::
|
||||
|
||||
j = (01)*
|
||||
|
||||
|
||||
|
|
@ -1,815 +0,0 @@
|
|||
***************************
|
||||
Developing a Program in Joy
|
||||
***************************
|
||||
|
||||
As an example of developing a program in Joy let's take the first problem from the Project Euler website.
|
||||
|
||||
`Project Euler, first problem: "Multiples of 3 and 5" <https://projecteuler.net/problem=1>`__
|
||||
=============================================================================================
|
||||
|
||||
|
||||
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
|
||||
|
||||
Find the sum of all the multiples of 3 or 5 below 1000.
|
||||
|
||||
.. code:: python
|
||||
|
||||
from notebook_preamble import J, V, define
|
||||
|
||||
Sum a range filtered by a predicate
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Let's create a predicate that returns ``True`` if a number is a multiple
|
||||
of 3 or 5 and ``False`` otherwise.
|
||||
|
||||
.. code:: python
|
||||
|
||||
define('P == [3 % not] dupdip 5 % not or')
|
||||
|
||||
.. code:: python
|
||||
|
||||
V('80 P')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 80 P
|
||||
80 . P
|
||||
80 . [3 % not] dupdip 5 % not or
|
||||
80 [3 % not] . dupdip 5 % not or
|
||||
80 . 3 % not 80 5 % not or
|
||||
80 3 . % not 80 5 % not or
|
||||
2 . not 80 5 % not or
|
||||
False . 80 5 % not or
|
||||
False 80 . 5 % not or
|
||||
False 80 5 . % not or
|
||||
False 0 . not or
|
||||
False True . or
|
||||
True .
|
||||
|
||||
|
||||
Given the predicate function ``P`` a suitable program is:
|
||||
|
||||
::
|
||||
|
||||
PE1 == 1000 range [P] filter sum
|
||||
|
||||
This function generates a list of the integers from 0 to 999, filters
|
||||
that list by ``P``, and then sums the result.
|
||||
|
||||
Logically this is fine, but pragmatically we are doing more work than we
|
||||
should be; we generate one thousand integers but actually use less than
|
||||
half of them. A better solution would be to generate just the multiples
|
||||
we want to sum, and to add them as we go rather than storing them and
|
||||
and summing them at the end.
|
||||
|
||||
Generate just the multiples
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
At first I had the idea to use two counters and increase them by three
|
||||
and five, respectively. This way we only generate the terms that we
|
||||
actually want to sum. We have to proceed by incrementing the counter
|
||||
that is lower, or if they are equal, the three counter, and we have to
|
||||
take care not to double add numbers like 15 that are multiples of both
|
||||
three and five.
|
||||
|
||||
This seemed a little clunky, so I tried a different approach.
|
||||
|
||||
Consider the first few terms in the series:
|
||||
|
||||
::
|
||||
|
||||
3 5 6 9 10 12 15 18 20 21 ...
|
||||
|
||||
Subtract each number from the one after it (subtracting 0 from 3):
|
||||
|
||||
::
|
||||
|
||||
3 5 6 9 10 12 15 18 20 21 24 25 27 30 ...
|
||||
0 3 5 6 9 10 12 15 18 20 21 24 25 27 ...
|
||||
-------------------------------------------
|
||||
3 2 1 3 1 2 3 3 2 1 3 1 2 3 ...
|
||||
|
||||
You get this lovely repeating palindromic sequence:
|
||||
|
||||
::
|
||||
|
||||
3 2 1 3 1 2 3
|
||||
|
||||
To make a counter that increments by factors of 3 and 5 you just add
|
||||
these differences to the counter one-by-one in a loop.
|
||||
|
||||
To make use of this sequence to increment a counter and sum terms as we
|
||||
go we need a function that will accept the sum, the counter, and the
|
||||
next term to add, and that adds the term to the counter and a copy of
|
||||
the counter to the running sum. This function will do that:
|
||||
|
||||
::
|
||||
|
||||
PE1.1 == + [+] dupdip
|
||||
|
||||
.. code:: python
|
||||
|
||||
define('PE1.1 == + [+] dupdip')
|
||||
|
||||
.. code:: python
|
||||
|
||||
V('0 0 3 PE1.1')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 0 0 3 PE1.1
|
||||
0 . 0 3 PE1.1
|
||||
0 0 . 3 PE1.1
|
||||
0 0 3 . PE1.1
|
||||
0 0 3 . + [+] dupdip
|
||||
0 3 . [+] dupdip
|
||||
0 3 [+] . dupdip
|
||||
0 3 . + 3
|
||||
3 . 3
|
||||
3 3 .
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
V('0 0 [3 2 1 3 1 2 3] [PE1.1] step')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 0 0 [3 2 1 3 1 2 3] [PE1.1] step
|
||||
0 . 0 [3 2 1 3 1 2 3] [PE1.1] step
|
||||
0 0 . [3 2 1 3 1 2 3] [PE1.1] step
|
||||
0 0 [3 2 1 3 1 2 3] . [PE1.1] step
|
||||
0 0 [3 2 1 3 1 2 3] [PE1.1] . step
|
||||
0 0 3 [PE1.1] . i [2 1 3 1 2 3] [PE1.1] step
|
||||
0 0 3 . PE1.1 [2 1 3 1 2 3] [PE1.1] step
|
||||
0 0 3 . + [+] dupdip [2 1 3 1 2 3] [PE1.1] step
|
||||
0 3 . [+] dupdip [2 1 3 1 2 3] [PE1.1] step
|
||||
0 3 [+] . dupdip [2 1 3 1 2 3] [PE1.1] step
|
||||
0 3 . + 3 [2 1 3 1 2 3] [PE1.1] step
|
||||
3 . 3 [2 1 3 1 2 3] [PE1.1] step
|
||||
3 3 . [2 1 3 1 2 3] [PE1.1] step
|
||||
3 3 [2 1 3 1 2 3] . [PE1.1] step
|
||||
3 3 [2 1 3 1 2 3] [PE1.1] . step
|
||||
3 3 2 [PE1.1] . i [1 3 1 2 3] [PE1.1] step
|
||||
3 3 2 . PE1.1 [1 3 1 2 3] [PE1.1] step
|
||||
3 3 2 . + [+] dupdip [1 3 1 2 3] [PE1.1] step
|
||||
3 5 . [+] dupdip [1 3 1 2 3] [PE1.1] step
|
||||
3 5 [+] . dupdip [1 3 1 2 3] [PE1.1] step
|
||||
3 5 . + 5 [1 3 1 2 3] [PE1.1] step
|
||||
8 . 5 [1 3 1 2 3] [PE1.1] step
|
||||
8 5 . [1 3 1 2 3] [PE1.1] step
|
||||
8 5 [1 3 1 2 3] . [PE1.1] step
|
||||
8 5 [1 3 1 2 3] [PE1.1] . step
|
||||
8 5 1 [PE1.1] . i [3 1 2 3] [PE1.1] step
|
||||
8 5 1 . PE1.1 [3 1 2 3] [PE1.1] step
|
||||
8 5 1 . + [+] dupdip [3 1 2 3] [PE1.1] step
|
||||
8 6 . [+] dupdip [3 1 2 3] [PE1.1] step
|
||||
8 6 [+] . dupdip [3 1 2 3] [PE1.1] step
|
||||
8 6 . + 6 [3 1 2 3] [PE1.1] step
|
||||
14 . 6 [3 1 2 3] [PE1.1] step
|
||||
14 6 . [3 1 2 3] [PE1.1] step
|
||||
14 6 [3 1 2 3] . [PE1.1] step
|
||||
14 6 [3 1 2 3] [PE1.1] . step
|
||||
14 6 3 [PE1.1] . i [1 2 3] [PE1.1] step
|
||||
14 6 3 . PE1.1 [1 2 3] [PE1.1] step
|
||||
14 6 3 . + [+] dupdip [1 2 3] [PE1.1] step
|
||||
14 9 . [+] dupdip [1 2 3] [PE1.1] step
|
||||
14 9 [+] . dupdip [1 2 3] [PE1.1] step
|
||||
14 9 . + 9 [1 2 3] [PE1.1] step
|
||||
23 . 9 [1 2 3] [PE1.1] step
|
||||
23 9 . [1 2 3] [PE1.1] step
|
||||
23 9 [1 2 3] . [PE1.1] step
|
||||
23 9 [1 2 3] [PE1.1] . step
|
||||
23 9 1 [PE1.1] . i [2 3] [PE1.1] step
|
||||
23 9 1 . PE1.1 [2 3] [PE1.1] step
|
||||
23 9 1 . + [+] dupdip [2 3] [PE1.1] step
|
||||
23 10 . [+] dupdip [2 3] [PE1.1] step
|
||||
23 10 [+] . dupdip [2 3] [PE1.1] step
|
||||
23 10 . + 10 [2 3] [PE1.1] step
|
||||
33 . 10 [2 3] [PE1.1] step
|
||||
33 10 . [2 3] [PE1.1] step
|
||||
33 10 [2 3] . [PE1.1] step
|
||||
33 10 [2 3] [PE1.1] . step
|
||||
33 10 2 [PE1.1] . i [3] [PE1.1] step
|
||||
33 10 2 . PE1.1 [3] [PE1.1] step
|
||||
33 10 2 . + [+] dupdip [3] [PE1.1] step
|
||||
33 12 . [+] dupdip [3] [PE1.1] step
|
||||
33 12 [+] . dupdip [3] [PE1.1] step
|
||||
33 12 . + 12 [3] [PE1.1] step
|
||||
45 . 12 [3] [PE1.1] step
|
||||
45 12 . [3] [PE1.1] step
|
||||
45 12 [3] . [PE1.1] step
|
||||
45 12 [3] [PE1.1] . step
|
||||
45 12 3 [PE1.1] . i
|
||||
45 12 3 . PE1.1
|
||||
45 12 3 . + [+] dupdip
|
||||
45 15 . [+] dupdip
|
||||
45 15 [+] . dupdip
|
||||
45 15 . + 15
|
||||
60 . 15
|
||||
60 15 .
|
||||
|
||||
|
||||
So one ``step`` through all seven terms brings the counter to 15 and the
|
||||
total to 60.
|
||||
|
||||
How many multiples to sum?
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code:: python
|
||||
|
||||
1000 / 15
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
66
|
||||
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
66 * 15
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
990
|
||||
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
1000 - 990
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
10
|
||||
|
||||
|
||||
|
||||
We only want the terms *less than* 1000.
|
||||
|
||||
.. code:: python
|
||||
|
||||
999 - 990
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
9
|
||||
|
||||
|
||||
|
||||
That means we want to run the full list of numbers sixty-six times to
|
||||
get to 990 and then the first four numbers 3 2 1 3 to get to 999.
|
||||
|
||||
.. code:: python
|
||||
|
||||
define('PE1 == 0 0 66 [[3 2 1 3 1 2 3] [PE1.1] step] times [3 2 1 3] [PE1.1] step pop')
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('PE1')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
233168
|
||||
|
||||
Packing the terms into an integer
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This form uses no extra storage and produces no unused summands. It's
|
||||
good but there's one more trick we can apply. The list of seven terms
|
||||
takes up at least seven bytes. But notice that all of the terms are less
|
||||
than four, and so each can fit in just two bits. We could store all
|
||||
seven terms in just fourteen bits and use masking and shifts to pick out
|
||||
each term as we go. This will use less space and save time loading whole
|
||||
integer terms from the list.
|
||||
|
||||
::
|
||||
|
||||
3 2 1 3 1 2 3
|
||||
0b 11 10 01 11 01 10 11 == 14811
|
||||
|
||||
.. code:: python
|
||||
|
||||
0b11100111011011
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
14811
|
||||
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
define('PE1.2 == [3 & PE1.1] dupdip 2 >>')
|
||||
|
||||
.. code:: python
|
||||
|
||||
V('0 0 14811 PE1.2')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 0 0 14811 PE1.2
|
||||
0 . 0 14811 PE1.2
|
||||
0 0 . 14811 PE1.2
|
||||
0 0 14811 . PE1.2
|
||||
0 0 14811 . [3 & PE1.1] dupdip 2 >>
|
||||
0 0 14811 [3 & PE1.1] . dupdip 2 >>
|
||||
0 0 14811 . 3 & PE1.1 14811 2 >>
|
||||
0 0 14811 3 . & PE1.1 14811 2 >>
|
||||
0 0 3 . PE1.1 14811 2 >>
|
||||
0 0 3 . + [+] dupdip 14811 2 >>
|
||||
0 3 . [+] dupdip 14811 2 >>
|
||||
0 3 [+] . dupdip 14811 2 >>
|
||||
0 3 . + 3 14811 2 >>
|
||||
3 . 3 14811 2 >>
|
||||
3 3 . 14811 2 >>
|
||||
3 3 14811 . 2 >>
|
||||
3 3 14811 2 . >>
|
||||
3 3 3702 .
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
V('3 3 3702 PE1.2')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 3 3 3702 PE1.2
|
||||
3 . 3 3702 PE1.2
|
||||
3 3 . 3702 PE1.2
|
||||
3 3 3702 . PE1.2
|
||||
3 3 3702 . [3 & PE1.1] dupdip 2 >>
|
||||
3 3 3702 [3 & PE1.1] . dupdip 2 >>
|
||||
3 3 3702 . 3 & PE1.1 3702 2 >>
|
||||
3 3 3702 3 . & PE1.1 3702 2 >>
|
||||
3 3 2 . PE1.1 3702 2 >>
|
||||
3 3 2 . + [+] dupdip 3702 2 >>
|
||||
3 5 . [+] dupdip 3702 2 >>
|
||||
3 5 [+] . dupdip 3702 2 >>
|
||||
3 5 . + 5 3702 2 >>
|
||||
8 . 5 3702 2 >>
|
||||
8 5 . 3702 2 >>
|
||||
8 5 3702 . 2 >>
|
||||
8 5 3702 2 . >>
|
||||
8 5 925 .
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
V('0 0 14811 7 [PE1.2] times pop')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 0 0 14811 7 [PE1.2] times pop
|
||||
0 . 0 14811 7 [PE1.2] times pop
|
||||
0 0 . 14811 7 [PE1.2] times pop
|
||||
0 0 14811 . 7 [PE1.2] times pop
|
||||
0 0 14811 7 . [PE1.2] times pop
|
||||
0 0 14811 7 [PE1.2] . times pop
|
||||
0 0 14811 [PE1.2] . i 6 [PE1.2] times pop
|
||||
0 0 14811 . PE1.2 6 [PE1.2] times pop
|
||||
0 0 14811 . [3 & PE1.1] dupdip 2 >> 6 [PE1.2] times pop
|
||||
0 0 14811 [3 & PE1.1] . dupdip 2 >> 6 [PE1.2] times pop
|
||||
0 0 14811 . 3 & PE1.1 14811 2 >> 6 [PE1.2] times pop
|
||||
0 0 14811 3 . & PE1.1 14811 2 >> 6 [PE1.2] times pop
|
||||
0 0 3 . PE1.1 14811 2 >> 6 [PE1.2] times pop
|
||||
0 0 3 . + [+] dupdip 14811 2 >> 6 [PE1.2] times pop
|
||||
0 3 . [+] dupdip 14811 2 >> 6 [PE1.2] times pop
|
||||
0 3 [+] . dupdip 14811 2 >> 6 [PE1.2] times pop
|
||||
0 3 . + 3 14811 2 >> 6 [PE1.2] times pop
|
||||
3 . 3 14811 2 >> 6 [PE1.2] times pop
|
||||
3 3 . 14811 2 >> 6 [PE1.2] times pop
|
||||
3 3 14811 . 2 >> 6 [PE1.2] times pop
|
||||
3 3 14811 2 . >> 6 [PE1.2] times pop
|
||||
3 3 3702 . 6 [PE1.2] times pop
|
||||
3 3 3702 6 . [PE1.2] times pop
|
||||
3 3 3702 6 [PE1.2] . times pop
|
||||
3 3 3702 [PE1.2] . i 5 [PE1.2] times pop
|
||||
3 3 3702 . PE1.2 5 [PE1.2] times pop
|
||||
3 3 3702 . [3 & PE1.1] dupdip 2 >> 5 [PE1.2] times pop
|
||||
3 3 3702 [3 & PE1.1] . dupdip 2 >> 5 [PE1.2] times pop
|
||||
3 3 3702 . 3 & PE1.1 3702 2 >> 5 [PE1.2] times pop
|
||||
3 3 3702 3 . & PE1.1 3702 2 >> 5 [PE1.2] times pop
|
||||
3 3 2 . PE1.1 3702 2 >> 5 [PE1.2] times pop
|
||||
3 3 2 . + [+] dupdip 3702 2 >> 5 [PE1.2] times pop
|
||||
3 5 . [+] dupdip 3702 2 >> 5 [PE1.2] times pop
|
||||
3 5 [+] . dupdip 3702 2 >> 5 [PE1.2] times pop
|
||||
3 5 . + 5 3702 2 >> 5 [PE1.2] times pop
|
||||
8 . 5 3702 2 >> 5 [PE1.2] times pop
|
||||
8 5 . 3702 2 >> 5 [PE1.2] times pop
|
||||
8 5 3702 . 2 >> 5 [PE1.2] times pop
|
||||
8 5 3702 2 . >> 5 [PE1.2] times pop
|
||||
8 5 925 . 5 [PE1.2] times pop
|
||||
8 5 925 5 . [PE1.2] times pop
|
||||
8 5 925 5 [PE1.2] . times pop
|
||||
8 5 925 [PE1.2] . i 4 [PE1.2] times pop
|
||||
8 5 925 . PE1.2 4 [PE1.2] times pop
|
||||
8 5 925 . [3 & PE1.1] dupdip 2 >> 4 [PE1.2] times pop
|
||||
8 5 925 [3 & PE1.1] . dupdip 2 >> 4 [PE1.2] times pop
|
||||
8 5 925 . 3 & PE1.1 925 2 >> 4 [PE1.2] times pop
|
||||
8 5 925 3 . & PE1.1 925 2 >> 4 [PE1.2] times pop
|
||||
8 5 1 . PE1.1 925 2 >> 4 [PE1.2] times pop
|
||||
8 5 1 . + [+] dupdip 925 2 >> 4 [PE1.2] times pop
|
||||
8 6 . [+] dupdip 925 2 >> 4 [PE1.2] times pop
|
||||
8 6 [+] . dupdip 925 2 >> 4 [PE1.2] times pop
|
||||
8 6 . + 6 925 2 >> 4 [PE1.2] times pop
|
||||
14 . 6 925 2 >> 4 [PE1.2] times pop
|
||||
14 6 . 925 2 >> 4 [PE1.2] times pop
|
||||
14 6 925 . 2 >> 4 [PE1.2] times pop
|
||||
14 6 925 2 . >> 4 [PE1.2] times pop
|
||||
14 6 231 . 4 [PE1.2] times pop
|
||||
14 6 231 4 . [PE1.2] times pop
|
||||
14 6 231 4 [PE1.2] . times pop
|
||||
14 6 231 [PE1.2] . i 3 [PE1.2] times pop
|
||||
14 6 231 . PE1.2 3 [PE1.2] times pop
|
||||
14 6 231 . [3 & PE1.1] dupdip 2 >> 3 [PE1.2] times pop
|
||||
14 6 231 [3 & PE1.1] . dupdip 2 >> 3 [PE1.2] times pop
|
||||
14 6 231 . 3 & PE1.1 231 2 >> 3 [PE1.2] times pop
|
||||
14 6 231 3 . & PE1.1 231 2 >> 3 [PE1.2] times pop
|
||||
14 6 3 . PE1.1 231 2 >> 3 [PE1.2] times pop
|
||||
14 6 3 . + [+] dupdip 231 2 >> 3 [PE1.2] times pop
|
||||
14 9 . [+] dupdip 231 2 >> 3 [PE1.2] times pop
|
||||
14 9 [+] . dupdip 231 2 >> 3 [PE1.2] times pop
|
||||
14 9 . + 9 231 2 >> 3 [PE1.2] times pop
|
||||
23 . 9 231 2 >> 3 [PE1.2] times pop
|
||||
23 9 . 231 2 >> 3 [PE1.2] times pop
|
||||
23 9 231 . 2 >> 3 [PE1.2] times pop
|
||||
23 9 231 2 . >> 3 [PE1.2] times pop
|
||||
23 9 57 . 3 [PE1.2] times pop
|
||||
23 9 57 3 . [PE1.2] times pop
|
||||
23 9 57 3 [PE1.2] . times pop
|
||||
23 9 57 [PE1.2] . i 2 [PE1.2] times pop
|
||||
23 9 57 . PE1.2 2 [PE1.2] times pop
|
||||
23 9 57 . [3 & PE1.1] dupdip 2 >> 2 [PE1.2] times pop
|
||||
23 9 57 [3 & PE1.1] . dupdip 2 >> 2 [PE1.2] times pop
|
||||
23 9 57 . 3 & PE1.1 57 2 >> 2 [PE1.2] times pop
|
||||
23 9 57 3 . & PE1.1 57 2 >> 2 [PE1.2] times pop
|
||||
23 9 1 . PE1.1 57 2 >> 2 [PE1.2] times pop
|
||||
23 9 1 . + [+] dupdip 57 2 >> 2 [PE1.2] times pop
|
||||
23 10 . [+] dupdip 57 2 >> 2 [PE1.2] times pop
|
||||
23 10 [+] . dupdip 57 2 >> 2 [PE1.2] times pop
|
||||
23 10 . + 10 57 2 >> 2 [PE1.2] times pop
|
||||
33 . 10 57 2 >> 2 [PE1.2] times pop
|
||||
33 10 . 57 2 >> 2 [PE1.2] times pop
|
||||
33 10 57 . 2 >> 2 [PE1.2] times pop
|
||||
33 10 57 2 . >> 2 [PE1.2] times pop
|
||||
33 10 14 . 2 [PE1.2] times pop
|
||||
33 10 14 2 . [PE1.2] times pop
|
||||
33 10 14 2 [PE1.2] . times pop
|
||||
33 10 14 [PE1.2] . i 1 [PE1.2] times pop
|
||||
33 10 14 . PE1.2 1 [PE1.2] times pop
|
||||
33 10 14 . [3 & PE1.1] dupdip 2 >> 1 [PE1.2] times pop
|
||||
33 10 14 [3 & PE1.1] . dupdip 2 >> 1 [PE1.2] times pop
|
||||
33 10 14 . 3 & PE1.1 14 2 >> 1 [PE1.2] times pop
|
||||
33 10 14 3 . & PE1.1 14 2 >> 1 [PE1.2] times pop
|
||||
33 10 2 . PE1.1 14 2 >> 1 [PE1.2] times pop
|
||||
33 10 2 . + [+] dupdip 14 2 >> 1 [PE1.2] times pop
|
||||
33 12 . [+] dupdip 14 2 >> 1 [PE1.2] times pop
|
||||
33 12 [+] . dupdip 14 2 >> 1 [PE1.2] times pop
|
||||
33 12 . + 12 14 2 >> 1 [PE1.2] times pop
|
||||
45 . 12 14 2 >> 1 [PE1.2] times pop
|
||||
45 12 . 14 2 >> 1 [PE1.2] times pop
|
||||
45 12 14 . 2 >> 1 [PE1.2] times pop
|
||||
45 12 14 2 . >> 1 [PE1.2] times pop
|
||||
45 12 3 . 1 [PE1.2] times pop
|
||||
45 12 3 1 . [PE1.2] times pop
|
||||
45 12 3 1 [PE1.2] . times pop
|
||||
45 12 3 [PE1.2] . i pop
|
||||
45 12 3 . PE1.2 pop
|
||||
45 12 3 . [3 & PE1.1] dupdip 2 >> pop
|
||||
45 12 3 [3 & PE1.1] . dupdip 2 >> pop
|
||||
45 12 3 . 3 & PE1.1 3 2 >> pop
|
||||
45 12 3 3 . & PE1.1 3 2 >> pop
|
||||
45 12 3 . PE1.1 3 2 >> pop
|
||||
45 12 3 . + [+] dupdip 3 2 >> pop
|
||||
45 15 . [+] dupdip 3 2 >> pop
|
||||
45 15 [+] . dupdip 3 2 >> pop
|
||||
45 15 . + 15 3 2 >> pop
|
||||
60 . 15 3 2 >> pop
|
||||
60 15 . 3 2 >> pop
|
||||
60 15 3 . 2 >> pop
|
||||
60 15 3 2 . >> pop
|
||||
60 15 0 . pop
|
||||
60 15 .
|
||||
|
||||
|
||||
And so we have at last:
|
||||
|
||||
.. code:: python
|
||||
|
||||
define('PE1 == 0 0 66 [14811 7 [PE1.2] times pop] times 14811 4 [PE1.2] times popop')
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('PE1')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
233168
|
||||
|
||||
|
||||
Let's refactor
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
14811 7 [PE1.2] times pop
|
||||
14811 4 [PE1.2] times pop
|
||||
14811 n [PE1.2] times pop
|
||||
n 14811 swap [PE1.2] times pop
|
||||
|
||||
.. code:: python
|
||||
|
||||
define('PE1.3 == 14811 swap [PE1.2] times pop')
|
||||
|
||||
Now we can simplify the definition above:
|
||||
|
||||
.. code:: python
|
||||
|
||||
define('PE1 == 0 0 66 [7 PE1.3] times 4 PE1.3 pop')
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('PE1')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
233168
|
||||
|
||||
|
||||
Here's our joy program all in one place. It doesn't make so much sense,
|
||||
but if you have read through the above description of how it was derived
|
||||
I hope it's clear.
|
||||
|
||||
::
|
||||
|
||||
PE1.1 == + [+] dupdip
|
||||
PE1.2 == [3 & PE1.1] dupdip 2 >>
|
||||
PE1.3 == 14811 swap [PE1.2] times pop
|
||||
PE1 == 0 0 66 [7 PE1.3] times 4 PE1.3 pop
|
||||
|
||||
Generator Version
|
||||
=================
|
||||
|
||||
It's a little clunky iterating sixty-six times though the seven numbers
|
||||
then four more. In the *Generator Programs* notebook we derive a
|
||||
generator that can be repeatedly driven by the ``x`` combinator to
|
||||
produce a stream of the seven numbers repeating over and over again.
|
||||
|
||||
.. code:: python
|
||||
|
||||
define('PE1.terms == [0 swap [dup [pop 14811] [] branch [3 &] dupdip 2 >>] dip rest cons]')
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('PE1.terms 21 [x] times')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 [0 swap [dup [pop 14811] [] branch [3 &] dupdip 2 >>] dip rest cons]
|
||||
|
||||
|
||||
We know from above that we need sixty-six times seven then four more
|
||||
terms to reach up to but not over one thousand.
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('7 66 * 4 +')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
466
|
||||
|
||||
|
||||
Here they are...
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('PE1.terms 466 [x] times pop')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3
|
||||
|
||||
|
||||
...and they do sum to 999.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('[PE1.terms 466 [x] times pop] run sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
999
|
||||
|
||||
|
||||
Now we can use ``PE1.1`` to accumulate the terms as we go, and then
|
||||
``pop`` the generator and the counter from the stack when we're done,
|
||||
leaving just the sum.
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('0 0 PE1.terms 466 [x [PE1.1] dip] times popop')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
233168
|
||||
|
||||
|
||||
A little further analysis renders iteration unnecessary.
|
||||
========================================================
|
||||
|
||||
Consider finding the sum of the positive integers less than or equal to
|
||||
ten.
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('[10 9 8 7 6 5 4 3 2 1] sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
55
|
||||
|
||||
|
||||
Instead of summing them,
|
||||
`observe <https://en.wikipedia.org/wiki/File:Animated_proof_for_the_formula_giving_the_sum_of_the_first_integers_1%2B2%2B...%2Bn.gif>`__:
|
||||
|
||||
::
|
||||
|
||||
10 9 8 7 6
|
||||
+ 1 2 3 4 5
|
||||
---- -- -- -- --
|
||||
11 11 11 11 11
|
||||
|
||||
11 * 5 = 55
|
||||
|
||||
From the above example we can deduce that the sum of the first N
|
||||
positive integers is:
|
||||
|
||||
::
|
||||
|
||||
(N + 1) * N / 2
|
||||
|
||||
(The formula also works for odd values of N, I'll leave that to you if
|
||||
you want to work it out or you can take my word for it.)
|
||||
|
||||
.. code:: python
|
||||
|
||||
define('F == dup ++ * 2 floordiv')
|
||||
|
||||
.. code:: python
|
||||
|
||||
V('10 F')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 10 F
|
||||
10 . F
|
||||
10 . dup ++ * 2 floordiv
|
||||
10 10 . ++ * 2 floordiv
|
||||
10 11 . * 2 floordiv
|
||||
110 . 2 floordiv
|
||||
110 2 . floordiv
|
||||
55 .
|
||||
|
||||
|
||||
Generalizing to Blocks of Terms
|
||||
-------------------------------
|
||||
|
||||
We can apply the same reasoning to the PE1 problem.
|
||||
|
||||
Between 0 and 990 inclusive there are sixty-six "blocks" of seven terms
|
||||
each, starting with:
|
||||
|
||||
::
|
||||
|
||||
[3 5 6 9 10 12 15]
|
||||
|
||||
And ending with:
|
||||
|
||||
::
|
||||
|
||||
[978 980 981 984 985 987 990]
|
||||
|
||||
If we reverse one of these two blocks and sum pairs...
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('[3 5 6 9 10 12 15] reverse [978 980 981 984 985 987 990] zip')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[[978 15] [980 12] [981 10] [984 9] [985 6] [987 5] [990 3]]
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('[3 5 6 9 10 12 15] reverse [978 980 981 984 985 987 990] zip [sum] map')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[993 992 991 993 991 992 993]
|
||||
|
||||
|
||||
(Interesting that the sequence of seven numbers appears again in the
|
||||
rightmost digit of each term.)
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('[ 3 5 6 9 10 12 15] reverse [978 980 981 984 985 987 990] zip [sum] map sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
6945
|
||||
|
||||
|
||||
Since there are sixty-six blocks and we are pairing them up, there must
|
||||
be thirty-three pairs, each of which sums to 6945. We also have these
|
||||
additional unpaired terms between 990 and 1000:
|
||||
|
||||
::
|
||||
|
||||
993 995 996 999
|
||||
|
||||
So we can give the "sum of all the multiples of 3 or 5 below 1000" like
|
||||
so:
|
||||
|
||||
.. code:: python
|
||||
|
||||
J('6945 33 * [993 995 996 999] cons sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
233168
|
||||
|
||||
|
||||
It's worth noting, I think, that this same reasoning holds for any two
|
||||
numbers :math:`n` and :math:`m` the multiples of which we hope to sum.
|
||||
The multiples would have a cycle of differences of length :math:`k` and
|
||||
so we could compute the sum of :math:`Nk` multiples as above.
|
||||
|
||||
The sequence of differences will always be a palidrome. Consider an
|
||||
interval spanning the least common multiple of :math:`n` and :math:`m`:
|
||||
|
||||
::
|
||||
|
||||
| | | | | | | |
|
||||
| | | | |
|
||||
|
||||
Here we have 4 and 7, and you can read off the sequence of differences
|
||||
directly from the diagram: 4 3 1 4 2 2 4 1 3 4.
|
||||
|
||||
Geometrically, the actual values of :math:`n` and :math:`m` and their
|
||||
*lcm* don't matter, the pattern they make will always be symmetrical
|
||||
around its midpoint. The same reasoning holds for multiples of more than
|
||||
two numbers.
|
||||
|
||||
The Simplest Program
|
||||
====================
|
||||
|
||||
Of course, the simplest joy program for the first Project Euler problem
|
||||
is just:
|
||||
|
||||
::
|
||||
|
||||
PE1 == 233168
|
||||
|
||||
Fin.
|
||||
|
|
@ -1,635 +0,0 @@
|
|||
Using ``x`` to Generate Values
|
||||
==============================
|
||||
|
||||
Cf. jp-reprod.html
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import J, V, define
|
||||
|
||||
Consider the ``x`` combinator:
|
||||
|
||||
::
|
||||
|
||||
x == dup i
|
||||
|
||||
We can apply it to a quoted program consisting of some value ``a`` and
|
||||
some function ``B``:
|
||||
|
||||
::
|
||||
|
||||
[a B] x
|
||||
[a B] a B
|
||||
|
||||
Let ``B`` function ``swap`` the ``a`` with the quote and run some
|
||||
function ``C`` on it to generate a new value ``b``:
|
||||
|
||||
::
|
||||
|
||||
B == swap [C] dip
|
||||
|
||||
[a B] a B
|
||||
[a B] a swap [C] dip
|
||||
a [a B] [C] dip
|
||||
a C [a B]
|
||||
b [a B]
|
||||
|
||||
Now discard the quoted ``a`` with ``rest`` then ``cons`` ``b``:
|
||||
|
||||
::
|
||||
|
||||
b [a B] rest cons
|
||||
b [B] cons
|
||||
[b B]
|
||||
|
||||
Altogether, this is the definition of ``B``:
|
||||
|
||||
::
|
||||
|
||||
B == swap [C] dip rest cons
|
||||
|
||||
We can make a generator for the Natural numbers (0, 1, 2, …) by using
|
||||
``0`` for ``a`` and ``[dup ++]`` for ``[C]``:
|
||||
|
||||
::
|
||||
|
||||
[0 swap [dup ++] dip rest cons]
|
||||
|
||||
Let’s try it:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('[0 swap [dup ++] dip rest cons] x')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. [0 swap [dup ++] dip rest cons] x
|
||||
[0 swap [dup ++] dip rest cons] . x
|
||||
[0 swap [dup ++] dip rest cons] . 0 swap [dup ++] dip rest cons
|
||||
[0 swap [dup ++] dip rest cons] 0 . swap [dup ++] dip rest cons
|
||||
0 [0 swap [dup ++] dip rest cons] . [dup ++] dip rest cons
|
||||
0 [0 swap [dup ++] dip rest cons] [dup ++] . dip rest cons
|
||||
0 . dup ++ [0 swap [dup ++] dip rest cons] rest cons
|
||||
0 0 . ++ [0 swap [dup ++] dip rest cons] rest cons
|
||||
0 1 . [0 swap [dup ++] dip rest cons] rest cons
|
||||
0 1 [0 swap [dup ++] dip rest cons] . rest cons
|
||||
0 1 [swap [dup ++] dip rest cons] . cons
|
||||
0 [1 swap [dup ++] dip rest cons] .
|
||||
|
||||
|
||||
After one application of ``x`` the quoted program contains ``1`` and
|
||||
``0`` is below it on the stack.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[0 swap [dup ++] dip rest cons] x x x x x pop')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
0 1 2 3 4
|
||||
|
||||
|
||||
``direco``
|
||||
----------
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('direco == dip rest cons')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('[0 swap [dup ++] direco] x')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. [0 swap [dup ++] direco] x
|
||||
[0 swap [dup ++] direco] . x
|
||||
[0 swap [dup ++] direco] . 0 swap [dup ++] direco
|
||||
[0 swap [dup ++] direco] 0 . swap [dup ++] direco
|
||||
0 [0 swap [dup ++] direco] . [dup ++] direco
|
||||
0 [0 swap [dup ++] direco] [dup ++] . direco
|
||||
0 [0 swap [dup ++] direco] [dup ++] . dip rest cons
|
||||
0 . dup ++ [0 swap [dup ++] direco] rest cons
|
||||
0 0 . ++ [0 swap [dup ++] direco] rest cons
|
||||
0 1 . [0 swap [dup ++] direco] rest cons
|
||||
0 1 [0 swap [dup ++] direco] . rest cons
|
||||
0 1 [swap [dup ++] direco] . cons
|
||||
0 [1 swap [dup ++] direco] .
|
||||
|
||||
|
||||
Making Generators
|
||||
-----------------
|
||||
|
||||
We want to define a function that accepts ``a`` and ``[C]`` and builds
|
||||
our quoted program:
|
||||
|
||||
::
|
||||
|
||||
a [C] G
|
||||
-------------------------
|
||||
[a swap [C] direco]
|
||||
|
||||
Working in reverse:
|
||||
|
||||
::
|
||||
|
||||
[a swap [C] direco] cons
|
||||
a [swap [C] direco] concat
|
||||
a [swap] [[C] direco] swap
|
||||
a [[C] direco] [swap]
|
||||
a [C] [direco] cons [swap]
|
||||
|
||||
Reading from the bottom up:
|
||||
|
||||
::
|
||||
|
||||
G == [direco] cons [swap] swap concat cons
|
||||
G == [direco] cons [swap] swoncat cons
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('G == [direco] cons [swap] swoncat cons')
|
||||
|
||||
Let’s try it out:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('0 [dup ++] G')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 swap [dup ++] direco]
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('0 [dup ++] G x x x pop')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
0 1 2
|
||||
|
||||
|
||||
Powers of 2
|
||||
~~~~~~~~~~~
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('1 [dup 1 <<] G x x x x x x x x x pop')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
1 2 4 8 16 32 64 128 256
|
||||
|
||||
|
||||
``[x] times``
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
If we have one of these quoted programs we can drive it using ``times``
|
||||
with the ``x`` combinator.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('23 [dup ++] G 5 [x] times')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
23 24 25 26 27 [28 swap [dup ++] direco]
|
||||
|
||||
|
||||
Generating Multiples of Three and Five
|
||||
--------------------------------------
|
||||
|
||||
Look at the treatment of the Project Euler Problem One in the
|
||||
“Developing a Program” notebook and you’ll see that we might be
|
||||
interested in generating an endless cycle of:
|
||||
|
||||
::
|
||||
|
||||
3 2 1 3 1 2 3
|
||||
|
||||
To do this we want to encode the numbers as pairs of bits in a single
|
||||
int:
|
||||
|
||||
::
|
||||
|
||||
3 2 1 3 1 2 3
|
||||
0b 11 10 01 11 01 10 11 == 14811
|
||||
|
||||
And pick them off by masking with 3 (binary 11) and then shifting the
|
||||
int right two bits.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('PE1.1 == dup [3 &] dip 2 >>')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('14811 PE1.1')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 14811 PE1.1
|
||||
14811 . PE1.1
|
||||
14811 . dup [3 &] dip 2 >>
|
||||
14811 14811 . [3 &] dip 2 >>
|
||||
14811 14811 [3 &] . dip 2 >>
|
||||
14811 . 3 & 14811 2 >>
|
||||
14811 3 . & 14811 2 >>
|
||||
3 . 14811 2 >>
|
||||
3 14811 . 2 >>
|
||||
3 14811 2 . >>
|
||||
3 3702 .
|
||||
|
||||
|
||||
If we plug ``14811`` and ``[PE1.1]`` into our generator form…
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('14811 [PE1.1] G')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[14811 swap [PE1.1] direco]
|
||||
|
||||
|
||||
…we get a generator that works for seven cycles before it reaches zero:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[14811 swap [PE1.1] direco] 7 [x] times')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
3 2 1 3 1 2 3 [0 swap [PE1.1] direco]
|
||||
|
||||
|
||||
Reset at Zero
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
We need a function that checks if the int has reached zero and resets it
|
||||
if so.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('PE1.1.check == dup [pop 14811] [] branch')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('14811 [PE1.1.check PE1.1] G')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[14811 swap [PE1.1.check PE1.1] direco]
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[14811 swap [PE1.1.check PE1.1] direco] 21 [x] times')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 [0 swap [PE1.1.check PE1.1] direco]
|
||||
|
||||
|
||||
(It would be more efficient to reset the int every seven cycles but
|
||||
that’s a little beyond the scope of this article. This solution does
|
||||
extra work, but not much, and we’re not using it “in production” as they
|
||||
say.)
|
||||
|
||||
Run 466 times
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
In the PE1 problem we are asked to sum all the multiples of three and
|
||||
five less than 1000. It’s worked out that we need to use all seven
|
||||
numbers sixty-six times and then four more.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('7 66 * 4 +')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
466
|
||||
|
||||
|
||||
If we drive our generator 466 times and sum the stack we get 999.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 1 2 3 3 2 1 3 [57 swap [PE1.1.check PE1.1] direco]
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[14811 swap [PE1.1.check PE1.1] direco] 466 [x] times pop enstacken sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
999
|
||||
|
||||
|
||||
Project Euler Problem One
|
||||
-------------------------
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('PE1.2 == + dup [+] dip')
|
||||
|
||||
Now we can add ``PE1.2`` to the quoted program given to ``G``.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('0 0 0 [PE1.1.check PE1.1] G 466 [x [PE1.2] dip] times popop')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
233168
|
||||
|
||||
|
||||
A generator for the Fibonacci Sequence.
|
||||
---------------------------------------
|
||||
|
||||
Consider:
|
||||
|
||||
::
|
||||
|
||||
[b a F] x
|
||||
[b a F] b a F
|
||||
|
||||
The obvious first thing to do is just add ``b`` and ``a``:
|
||||
|
||||
::
|
||||
|
||||
[b a F] b a +
|
||||
[b a F] b+a
|
||||
|
||||
From here we want to arrive at:
|
||||
|
||||
::
|
||||
|
||||
b [b+a b F]
|
||||
|
||||
Let’s start with ``swons``:
|
||||
|
||||
::
|
||||
|
||||
[b a F] b+a swons
|
||||
[b+a b a F]
|
||||
|
||||
Considering this quote as a stack:
|
||||
|
||||
::
|
||||
|
||||
F a b b+a
|
||||
|
||||
We want to get it to:
|
||||
|
||||
::
|
||||
|
||||
F b b+a b
|
||||
|
||||
So:
|
||||
|
||||
::
|
||||
|
||||
F a b b+a popdd over
|
||||
F b b+a b
|
||||
|
||||
And therefore:
|
||||
|
||||
::
|
||||
|
||||
[b+a b a F] [popdd over] infra
|
||||
[b b+a b F]
|
||||
|
||||
But we can just use ``cons`` to carry ``b+a`` into the quote:
|
||||
|
||||
::
|
||||
|
||||
[b a F] b+a [popdd over] cons infra
|
||||
[b a F] [b+a popdd over] infra
|
||||
[b b+a b F]
|
||||
|
||||
Lastly:
|
||||
|
||||
::
|
||||
|
||||
[b b+a b F] uncons
|
||||
b [b+a b F]
|
||||
|
||||
Putting it all together:
|
||||
|
||||
::
|
||||
|
||||
F == + [popdd over] cons infra uncons
|
||||
fib_gen == [1 1 F]
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('fib == + [popdd over] cons infra uncons')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('fib_gen == [1 1 fib]')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('fib_gen 10 [x] times')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
1 2 3 5 8 13 21 34 55 89 [144 89 fib]
|
||||
|
||||
|
||||
Project Euler Problem Two
|
||||
-------------------------
|
||||
|
||||
By considering the terms in the Fibonacci sequence whose values do
|
||||
not exceed four million, find the sum of the even-valued terms.
|
||||
|
||||
Now that we have a generator for the Fibonacci sequence, we need a
|
||||
function that adds a term in the sequence to a sum if it is even, and
|
||||
``pop``\ s it otherwise.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('PE2.1 == dup 2 % [+] [pop] branch')
|
||||
|
||||
And a predicate function that detects when the terms in the series
|
||||
“exceed four million”.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('>4M == 4000000 >')
|
||||
|
||||
Now it’s straightforward to define ``PE2`` as a recursive function that
|
||||
generates terms in the Fibonacci sequence until they exceed four million
|
||||
and sums the even ones.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('PE2 == 0 fib_gen x [pop >4M] [popop] [[PE2.1] dip x] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('PE2')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
4613732
|
||||
|
||||
|
||||
Here’s the collected program definitions:
|
||||
|
||||
::
|
||||
|
||||
fib == + swons [popdd over] infra uncons
|
||||
fib_gen == [1 1 fib]
|
||||
|
||||
even == dup 2 %
|
||||
>4M == 4000000 >
|
||||
|
||||
PE2.1 == even [+] [pop] branch
|
||||
PE2 == 0 fib_gen x [pop >4M] [popop] [[PE2.1] dip x] primrec
|
||||
|
||||
Even-valued Fibonacci Terms
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Using ``o`` for odd and ``e`` for even:
|
||||
|
||||
::
|
||||
|
||||
o + o = e
|
||||
e + e = e
|
||||
o + e = o
|
||||
|
||||
So the Fibonacci sequence considered in terms of just parity would be:
|
||||
|
||||
::
|
||||
|
||||
o o e o o e o o e o o e o o e o o e
|
||||
1 1 2 3 5 8 . . .
|
||||
|
||||
Every third term is even.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1 0 fib] x x x') # To start the sequence with 1 1 2 3 instead of 1 2 3.
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
1 1 2 [3 2 fib]
|
||||
|
||||
|
||||
Drive the generator three times and ``popop`` the two odd terms.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1 0 fib] x x x [popop] dipd')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
2 [3 2 fib]
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('PE2.2 == x x x [popop] dipd')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1 0 fib] 10 [PE2.2] times')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
2 8 34 144 610 2584 10946 46368 196418 832040 [1346269 832040 fib]
|
||||
|
||||
|
||||
Replace ``x`` with our new driver function ``PE2.2`` and start our
|
||||
``fib`` generator at ``1 0``.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('0 [1 0 fib] PE2.2 [pop >4M] [popop] [[PE2.1] dip PE2.2] primrec')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
4613732
|
||||
|
||||
|
||||
How to compile these?
|
||||
---------------------
|
||||
|
||||
You would probably start with a special version of ``G``, and perhaps
|
||||
modifications to the default ``x``?
|
||||
|
||||
An Interesting Variation
|
||||
------------------------
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('codireco == cons dip rest cons')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('[0 [dup ++] codireco] x')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. [0 [dup ++] codireco] x
|
||||
[0 [dup ++] codireco] . x
|
||||
[0 [dup ++] codireco] . 0 [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 . [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
|
||||
[0 [dup ++] codireco] [0 dup ++] . dip rest cons
|
||||
. 0 dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 . dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 0 . ++ [0 [dup ++] codireco] rest cons
|
||||
0 1 . [0 [dup ++] codireco] rest cons
|
||||
0 1 [0 [dup ++] codireco] . rest cons
|
||||
0 1 [[dup ++] codireco] . cons
|
||||
0 [1 [dup ++] codireco] .
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('G == [codireco] cons cons')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('230 [dup ++] G 5 [x] times pop')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
230 231 232 233 234
|
||||
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
|
||||
*******************
|
||||
Thun: Joy in Python
|
||||
*******************
|
||||
|
||||
This implementation is meant as a tool for exploring the programming
|
||||
model and method of Joy. Python seems like a great implementation
|
||||
language for Joy for several reasons.
|
||||
|
||||
* We can lean on the Python immutable types for our basic semantics and types: ints, floats, strings, and tuples, which enforces functional purity.
|
||||
* We get garbage collection for free.
|
||||
* Compilation via Cython.
|
||||
* Python is a "glue language" with loads of libraries which we can wrap in Joy functions.
|
||||
|
||||
|
||||
`Read-Eval-Print Loop (REPL) <https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop>`__
|
||||
====================================================================================================
|
||||
|
||||
The main way to interact with the Joy interpreter is through a simple
|
||||
`REPL <https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop>`__
|
||||
that you start by running the package:
|
||||
|
||||
::
|
||||
|
||||
$ python3 -m joy
|
||||
Thun - Copyright © 2017 Simon Forman
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type "warranty".
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type "sharing" for details.
|
||||
Type "words" to see a list of all words, and "[<name>] help" to print the
|
||||
docs for a word.
|
||||
|
||||
|
||||
<-top
|
||||
|
||||
joy? _
|
||||
|
||||
The ``<-top`` marker points to the top of the (initially empty) stack.
|
||||
You can enter Joy notation at the prompt and a :doc:`trace of evaluation <../pretty>` will
|
||||
be printed followed by the stack and prompt again::
|
||||
|
||||
joy? 23 sqr 18 +
|
||||
|
||||
547 <-top
|
||||
|
||||
joy?
|
||||
|
||||
There is a `trace` combinator::
|
||||
|
||||
joy? 23 [sqr 18 +] trace
|
||||
23 . sqr 18 +
|
||||
23 . dup mul 18 +
|
||||
23 23 . mul 18 +
|
||||
529 . 18 +
|
||||
529 18 . +
|
||||
547 .
|
||||
|
||||
547 <-top
|
||||
|
||||
joy?
|
||||
|
||||
|
||||
The Stack
|
||||
=============
|
||||
|
||||
In Joy, in addition to the types Boolean, integer, float, and string,
|
||||
there is a :doc:`single sequence type <../stack>` represented by enclosing a sequence of
|
||||
terms in brackets ``[...]``. This sequence type is used to represent
|
||||
both the stack and the expression. It is a `cons
|
||||
list <https://en.wikipedia.org/wiki/Cons#Lists>`__ made from Python
|
||||
tuples.
|
||||
|
||||
|
||||
Purely Functional Datastructures
|
||||
=================================
|
||||
|
||||
Because Joy stacks are made out of Python tuples they are immutable, as are the other Python types we "borrow" for Joy, so all Joy datastructures are `purely functional <https://en.wikipedia.org/wiki/Purely_functional_data_structure>`__.
|
||||
|
||||
|
||||
The ``joy()`` function
|
||||
=======================
|
||||
|
||||
An Interpreter
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``joy()`` interpreter function is extrememly simple. It accepts a stack, an
|
||||
expression, and a dictionary, and it iterates through the expression
|
||||
putting values onto the stack and delegating execution to functions which it
|
||||
looks up in the dictionary.
|
||||
|
||||
|
||||
`Continuation-Passing Style <https://en.wikipedia.org/wiki/Continuation-passing_style>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
One day I thought, What happens if you rewrite Joy to use
|
||||
`CPS <https://en.wikipedia.org/wiki/Continuation-passing_style>`__? I
|
||||
made all the functions accept and return the expression as well as the
|
||||
stack and found that all the combinators could be rewritten to work by
|
||||
modifying the expression rather than making recursive calls to the
|
||||
``joy()`` function.
|
||||
|
||||
|
||||
View function
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The ``joy()`` function accepts an optional ``viewer`` argument that
|
||||
is a function which it calls on
|
||||
each iteration passing the current stack and expression just before
|
||||
evaluation. This can be used for tracing, breakpoints, retrying after
|
||||
exceptions, or interrupting an evaluation and saving to disk or sending
|
||||
over the network to resume later. The stack and expression together
|
||||
contain all the state of the computation at each step.
|
||||
|
||||
|
||||
The ``TracePrinter``.
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A ``viewer`` records each step of the evaluation of a Joy program. The
|
||||
``TracePrinter`` has a facility for printing out a trace of the
|
||||
evaluation, one line per step. Each step is aligned to the current
|
||||
interpreter position, signified by a period separating the stack on the
|
||||
left from the pending expression ("continuation") on the right.
|
||||
|
||||
|
||||
Parser
|
||||
======
|
||||
|
||||
The parser is extremely simple. The undocumented ``re.Scanner`` class
|
||||
does the tokenizing and then the parser builds the tuple
|
||||
structure out of the tokens. There's no Abstract Syntax Tree or anything
|
||||
like that.
|
||||
|
||||
|
||||
Symbols
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
TODO: Symbols are just a string subclass; used by the parser to represent function names and by the interpreter to look up functions in the dictionary. N.B.: Symbols are not looked up at parse-time. You *could* define recursive functions, er, recusively, without ``genrec`` or other recursion combinators ``foo == ... foo ...`` but don't do that.
|
||||
|
||||
|
||||
Token Regular Expressions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
123 1.2 'single quotes' "double quotes" function
|
||||
|
||||
TBD (look in the :module: joy.parser module.)
|
||||
|
||||
|
||||
Examples
|
||||
~~~~~~~~~~~
|
||||
|
||||
.. code:: python
|
||||
|
||||
joy.parser.text_to_expression('1 2 3 4 5') # A simple sequence.
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
(1, (2, (3, (4, (5, ())))))
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
joy.parser.text_to_expression('[1 2 3] 4 5') # Three items, the first is a list with three items
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
((1, (2, (3, ()))), (4, (5, ())))
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
joy.parser.text_to_expression('1 23 ["four" [-5.0] cons] 8888') # A mixed bag. cons is
|
||||
# a Symbol, no lookup at
|
||||
# parse-time. Haiku docs.
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
(1, (23, (('four', ((-5.0, ()), (cons, ()))), (8888, ()))))
|
||||
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
joy.parser.text_to_expression('[][][][][]') # Five empty lists.
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
((), ((), ((), ((), ((), ())))))
|
||||
|
||||
|
||||
|
||||
.. code:: python
|
||||
|
||||
joy.parser.text_to_expression('[[[[[]]]]]') # Five nested lists.
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
((((((), ()), ()), ()), ()), ())
|
||||
|
||||
|
||||
|
||||
Library
|
||||
=======
|
||||
|
||||
The Joy library of functions (aka commands, or "words" after Forth
|
||||
usage) encapsulates all the actual functionality (no pun intended) of
|
||||
the Joy system. There are simple functions such as addition ``add`` (or
|
||||
``+``, the library module supports aliases), and combinators which
|
||||
provide control-flow and higher-order operations.
|
||||
|
||||
Many of the functions are defined in Python, like ``dip``:
|
||||
|
||||
.. code:: python
|
||||
|
||||
print inspect.getsource(joy.library.dip)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
def dip(stack, expression, dictionary):
|
||||
(quote, (x, stack)) = stack
|
||||
expression = x, expression
|
||||
return stack, concat(quote, expression), dictionary
|
||||
|
||||
|
||||
Some functions are defined in equations in terms of other functions.
|
||||
When the interpreter executes a definition function that function just
|
||||
pushes its body expression onto the pending expression (the
|
||||
continuation) and returns control to the interpreter.
|
||||
|
||||
.. code:: python
|
||||
|
||||
print joy.library.definitions
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
second == rest first
|
||||
third == rest rest first
|
||||
product == 1 swap [*] step
|
||||
swons == swap cons
|
||||
swoncat == swap concat
|
||||
flatten == [] swap [concat] step
|
||||
unit == [] cons
|
||||
quoted == [unit] dip
|
||||
unquoted == [i] dip
|
||||
enstacken == stack [clear] dip
|
||||
disenstacken == ? [uncons ?] loop pop
|
||||
? == dup truthy
|
||||
dinfrirst == dip infra first
|
||||
nullary == [stack] dinfrirst
|
||||
unary == [stack [pop] dip] dinfrirst
|
||||
binary == [stack [popop] dip] dinfrirst
|
||||
ternary == [stack [popop pop] dip] dinfrirst
|
||||
pam == [i] map
|
||||
run == [] swap infra
|
||||
sqr == dup mul
|
||||
size == 0 swap [pop ++] step
|
||||
cleave == [i] app2 [popd] dip
|
||||
average == [sum 1.0 *] [size] cleave /
|
||||
gcd == 1 [tuck modulus dup 0 >] loop pop
|
||||
least_fraction == dup [gcd] infra [div] concat map
|
||||
*fraction == [uncons] dip uncons [swap] dip concat [*] infra [*] dip cons
|
||||
*fraction0 == concat [[swap] dip * [*] dip] infra
|
||||
down_to_zero == [0 >] [dup --] while
|
||||
range_to_zero == unit [down_to_zero] infra
|
||||
anamorphism == [pop []] swap [dip swons] genrec
|
||||
range == [0 <=] [1 - dup] anamorphism
|
||||
while == swap [nullary] cons dup dipd concat loop
|
||||
dudipd == dup dipd
|
||||
primrec == [i] genrec
|
||||
|
||||
|
||||
|
||||
Currently, there's no function to add new definitions to the dictionary
|
||||
from "within" Joy code itself. Adding new definitions remains a
|
||||
meta-interpreter action. You have to do it yourself, in Python, and wash
|
||||
your hands afterward.
|
||||
|
||||
It would be simple enough to define one, but it would open the door to
|
||||
*name binding* and break the idea that all state is captured in the
|
||||
stack and expression. There's an implicit *standard dictionary* that
|
||||
defines the actual semantics of the syntactic stack and expression
|
||||
datastructures (which only contain symbols, not the actual functions.
|
||||
Pickle some and see for yourself.)
|
||||
|
||||
"There should be only one."
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Which brings me to talking about one of my hopes and dreams for this
|
||||
notation: "There should be only one." What I mean is that there should
|
||||
be one universal standard dictionary of commands, and all bespoke work
|
||||
done in a UI for purposes takes place by direct interaction and macros.
|
||||
There would be a *Grand Refactoring* biannually (two years, not six
|
||||
months, that's semi-annually) where any new definitions factored out of
|
||||
the usage and macros of the previous time, along with new algorithms and
|
||||
such, were entered into the dictionary and posted to e.g. IPFS.
|
||||
|
||||
Code should not burgeon wildly, as it does today. The variety of code
|
||||
should map more-or-less to the well-factored variety of human
|
||||
computably-solvable problems. There shouldn't be dozens of chat apps, JS
|
||||
frameworks, programming languages. It's a waste of time, a `fractal
|
||||
"thundering herd"
|
||||
attack <https://en.wikipedia.org/wiki/Thundering_herd_problem>`__ on
|
||||
human mentality.
|
||||
|
||||
Literary Code Library
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you read over the other notebooks you'll see that developing code in
|
||||
Joy is a lot like doing simple mathematics, and the descriptions of the
|
||||
code resemble math papers. The code also works the first time, no bugs.
|
||||
If you have any experience programming at all, you are probably
|
||||
skeptical, as I was, but it seems to work: deriving code mathematically
|
||||
seems to lead to fewer errors.
|
||||
|
||||
But my point now is that this great ratio of textual explanation to wind
|
||||
up with code that consists of a few equations and could fit on an index
|
||||
card is highly desirable. Less code has fewer errors. The structure of
|
||||
Joy engenders a kind of thinking that seems to be very effective for
|
||||
developing structured processes.
|
||||
|
||||
There seems to be an elegance and power to the notation.
|
||||
|
||||
|
|
@ -1,257 +0,0 @@
|
|||
`Newton's method <https://en.wikipedia.org/wiki/Newton%27s_method>`__
|
||||
=====================================================================
|
||||
|
||||
Let's use the Newton-Raphson method for finding the root of an equation
|
||||
to write a function that can compute the square root of a number.
|
||||
|
||||
Cf. `"Why Functional Programming Matters" by John
|
||||
Hughes <https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf>`__
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
from notebook_preamble import J, V, define
|
||||
|
||||
A Generator for Approximations
|
||||
------------------------------
|
||||
|
||||
To make a generator that generates successive approximations let’s start
|
||||
by assuming an initial approximation and then derive the function that
|
||||
computes the next approximation:
|
||||
|
||||
::
|
||||
|
||||
a F
|
||||
---------
|
||||
a'
|
||||
|
||||
A Function to Compute the Next Approximation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is the equation for computing the next approximate value of the
|
||||
square root:
|
||||
|
||||
:math:`a_{i+1} = \frac{(a_i+\frac{n}{a_i})}{2}`
|
||||
|
||||
::
|
||||
|
||||
a n over / + 2 /
|
||||
a n a / + 2 /
|
||||
a n/a + 2 /
|
||||
a+n/a 2 /
|
||||
(a+n/a)/2
|
||||
|
||||
The function we want has the argument ``n`` in it:
|
||||
|
||||
::
|
||||
|
||||
F == n over / + 2 /
|
||||
|
||||
Make it into a Generator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Our generator would be created by:
|
||||
|
||||
::
|
||||
|
||||
a [dup F] make_generator
|
||||
|
||||
With n as part of the function F, but n is the input to the sqrt
|
||||
function we’re writing. If we let 1 be the initial approximation:
|
||||
|
||||
::
|
||||
|
||||
1 n 1 / + 2 /
|
||||
1 n/1 + 2 /
|
||||
1 n + 2 /
|
||||
n+1 2 /
|
||||
(n+1)/2
|
||||
|
||||
The generator can be written as:
|
||||
|
||||
::
|
||||
|
||||
23 1 swap [over / + 2 /] cons [dup] swoncat make_generator
|
||||
1 23 [over / + 2 /] cons [dup] swoncat make_generator
|
||||
1 [23 over / + 2 /] [dup] swoncat make_generator
|
||||
1 [dup 23 over / + 2 /] make_generator
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('gsra 1 swap [over / + 2 /] cons [dup] swoncat make_generator')
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('23 gsra')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1 [dup 23 over / + 2 /] codireco]
|
||||
|
||||
|
||||
Let's drive the generator a few time (with the ``x`` combinator) and
|
||||
square the approximation to see how well it works...
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('23 gsra 6 [x popd] times first sqr')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
23.0000000001585
|
||||
|
||||
|
||||
Finding Consecutive Approximations within a Tolerance
|
||||
-----------------------------------------------------
|
||||
|
||||
From `"Why Functional Programming Matters" by John
|
||||
Hughes <https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf>`__:
|
||||
|
||||
The remainder of a square root finder is a function *within*, which
|
||||
takes a tolerance and a list of approximations and looks down the
|
||||
list for two successive approximations that differ by no more than
|
||||
the given tolerance.
|
||||
|
||||
(And note that by “list” he means a lazily-evaluated list.)
|
||||
|
||||
Using the *output* ``[a G]`` of the above generator for square root
|
||||
approximations, and further assuming that the first term a has been
|
||||
generated already and epsilon ε is handy on the stack...
|
||||
|
||||
::
|
||||
|
||||
a [b G] ε within
|
||||
---------------------- a b - abs ε <=
|
||||
b
|
||||
|
||||
|
||||
a [b G] ε within
|
||||
---------------------- a b - abs ε >
|
||||
b [c G] ε within
|
||||
|
||||
Predicate
|
||||
~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
a [b G] ε [first - abs] dip <=
|
||||
a [b G] first - abs ε <=
|
||||
a b - abs ε <=
|
||||
a-b abs ε <=
|
||||
abs(a-b) ε <=
|
||||
(abs(a-b)<=ε)
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('_within_P [first - abs] dip <=')
|
||||
|
||||
Base-Case
|
||||
~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
a [b G] ε roll< popop first
|
||||
[b G] ε a popop first
|
||||
[b G] first
|
||||
b
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('_within_B roll< popop first')
|
||||
|
||||
Recur
|
||||
~~~~~
|
||||
|
||||
::
|
||||
|
||||
a [b G] ε R0 [within] R1
|
||||
|
||||
1. Discard a.
|
||||
2. Use ``x`` combinator to generate next term from ``G``.
|
||||
3. Run ``within`` with ``i`` (it is a "tail-recursive" function.)
|
||||
|
||||
Pretty straightforward:
|
||||
|
||||
::
|
||||
|
||||
a [b G] ε R0 [within] R1
|
||||
a [b G] ε [popd x] dip [within] i
|
||||
a [b G] popd x ε [within] i
|
||||
[b G] x ε [within] i
|
||||
b [c G] ε [within] i
|
||||
b [c G] ε within
|
||||
|
||||
b [c G] ε within
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('_within_R [popd x] dip')
|
||||
|
||||
Setting up
|
||||
~~~~~~~~~~
|
||||
|
||||
The recursive function we have defined so far needs a slight preamble:
|
||||
``x`` to prime the generator and the epsilon value to use:
|
||||
|
||||
::
|
||||
|
||||
[a G] x ε ...
|
||||
a [b G] ε ...
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('within x 0.000000001 [_within_P] [_within_B] [_within_R] tailrec')
|
||||
define('sqrt gsra within')
|
||||
|
||||
Try it out...
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('36 sqrt')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
6.0
|
||||
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('23 sqrt')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
4.795831523312719
|
||||
|
||||
|
||||
Check it.
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
4.795831523312719**2
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
22.999999999999996
|
||||
|
||||
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
from math import sqrt
|
||||
|
||||
sqrt(23)
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
4.795831523312719
|
||||
|
||||
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
|
||||
**************
|
||||
No Updates
|
||||
**************
|
||||
|
||||
DRAFT
|
||||
|
||||
1. Joy doesn't need to change.
|
||||
|
||||
A. The interpreter doesn't need to change, ``viewer`` function can customize mainloop. Or use a sub-interpreter (Joy in Joy.) The base interpreter remains static.
|
||||
B. Once a function has been named and defined *never change that name*. It's just not allowed. If you need to change a function ``foo`` you have to call it ``foo_II`` or something. Once a function (name mapped to behavior) is released to the public *that's it*, it's done.
|
||||
C. The language evolves by adding new definitions and refactoring, always choosing new names for new functions.
|
||||
|
||||
2. Following `Semantic Versioning`_ there will never be a version 2.0.
|
||||
|
||||
A. `Major version must be incremented if any backwards incompatible changes are introduced to the public API. <https://semver.org/#spec-item-8>`__
|
||||
B. We never implement any backwards incompatible changes, so...
|
||||
C. We could see e.g. Thun version 1.273.3!
|
||||
|
||||
|
||||
.. _Semantic Versioning: https://semver.org
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,158 +0,0 @@
|
|||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import J, V, define
|
||||
|
||||
`Quadratic formula <https://en.wikipedia.org/wiki/Quadratic_formula>`__
|
||||
=======================================================================
|
||||
|
||||
Cf.
|
||||
`jp-quadratic.html <http://www.kevinalbrecht.com/code/joy-mirror/jp-quadratic.html>`__
|
||||
|
||||
::
|
||||
|
||||
-b ± sqrt(b^2 - 4 * a * c)
|
||||
--------------------------------
|
||||
2 * a
|
||||
|
||||
:math:`\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}`
|
||||
|
||||
Write a straightforward program with variable names.
|
||||
----------------------------------------------------
|
||||
|
||||
This math translates to Joy code in a straightforward manner. We are
|
||||
going to use named variables to keep track of the arguments, then write
|
||||
a definition without them.
|
||||
|
||||
``-b``
|
||||
~~~~~~
|
||||
|
||||
::
|
||||
|
||||
b neg
|
||||
|
||||
``sqrt(b^2 - 4 * a * c)``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
b sqr 4 a c * * - sqrt
|
||||
|
||||
``/2a``
|
||||
~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
a 2 * /
|
||||
|
||||
``±``
|
||||
~~~~~
|
||||
|
||||
There is a function ``pm`` that accepts two values on the stack and
|
||||
replaces them with their sum and difference.
|
||||
|
||||
::
|
||||
|
||||
pm == [+] [-] cleave popdd
|
||||
|
||||
Putting Them Together
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
|
||||
We use ``app2`` to compute both roots by using a quoted program
|
||||
``[2a /]`` built with ``cons``.
|
||||
|
||||
Derive a definition.
|
||||
--------------------
|
||||
|
||||
Working backwards we use ``dip`` and ``dipd`` to extract the code from
|
||||
the variables:
|
||||
|
||||
::
|
||||
|
||||
b neg b sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b [neg] dupdip sqr 4 a c * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c [[neg] dupdip sqr 4] dipd * * - sqrt pm a 2 * [/] cons app2
|
||||
b a c a [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
b a c over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
|
||||
The three arguments are to the left, so we can “chop off” everything to
|
||||
the right and say it’s the definition of the ``quadratic`` function:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')
|
||||
|
||||
Let’s try it out:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('3 1 1 quadratic')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
-0.3819660112501051 -2.618033988749895
|
||||
|
||||
|
||||
If you look at the Joy evaluation trace you can see that the first few
|
||||
lines are the ``dip`` and ``dipd`` combinators building the main program
|
||||
by incorporating the values on the stack. Then that program runs and you
|
||||
get the results. This is pretty typical of Joy code.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('-5 1 4 quadratic')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. -5 1 4 quadratic
|
||||
-5 . 1 4 quadratic
|
||||
-5 1 . 4 quadratic
|
||||
-5 1 4 . quadratic
|
||||
-5 1 4 . over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 . [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2
|
||||
-5 1 4 1 [[[neg] dupdip sqr 4] dipd * * - sqrt pm] . dip 2 * [/] cons app2
|
||||
-5 1 4 . [[neg] dupdip sqr 4] dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 1 4 [[neg] dupdip sqr 4] . dipd * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . [neg] dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 [neg] . dupdip sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
-5 . neg -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 . -5 sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . sqr 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 . dup mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 -5 -5 . mul 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 . 4 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 . 1 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 . 4 * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 1 4 . * * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 4 4 . * - sqrt pm 1 2 * [/] cons app2
|
||||
5 25 16 . - sqrt pm 1 2 * [/] cons app2
|
||||
5 9 . sqrt pm 1 2 * [/] cons app2
|
||||
5 3.0 . pm 1 2 * [/] cons app2
|
||||
8.0 2.0 . 1 2 * [/] cons app2
|
||||
8.0 2.0 1 . 2 * [/] cons app2
|
||||
8.0 2.0 1 2 . * [/] cons app2
|
||||
8.0 2.0 2 . [/] cons app2
|
||||
8.0 2.0 2 [/] . cons app2
|
||||
8.0 2.0 [2 /] . app2
|
||||
[8.0] [2 /] . infra first [2.0] [2 /] infra first
|
||||
8.0 . 2 / [] swaack first [2.0] [2 /] infra first
|
||||
8.0 2 . / [] swaack first [2.0] [2 /] infra first
|
||||
4.0 . [] swaack first [2.0] [2 /] infra first
|
||||
4.0 [] . swaack first [2.0] [2 /] infra first
|
||||
[4.0] . first [2.0] [2 /] infra first
|
||||
4.0 . [2.0] [2 /] infra first
|
||||
4.0 [2.0] . [2 /] infra first
|
||||
4.0 [2.0] [2 /] . infra first
|
||||
2.0 . 2 / [4.0] swaack first
|
||||
2.0 2 . / [4.0] swaack first
|
||||
1.0 . [4.0] swaack first
|
||||
1.0 [4.0] . swaack first
|
||||
4.0 [1.0] . first
|
||||
4.0 1.0 .
|
||||
|
||||
|
||||
|
|
@ -1,690 +0,0 @@
|
|||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import D, DefinitionWrapper, J, V, define
|
||||
|
||||
Recursion Combinators
|
||||
=====================
|
||||
|
||||
This article describes the ``genrec`` combinator, how to use it, and
|
||||
several generic specializations.
|
||||
|
||||
::
|
||||
|
||||
[if] [then] [rec1] [rec2] genrec
|
||||
---------------------------------------------------------------------
|
||||
[if] [then] [rec1 [[if] [then] [rec1] [rec2] genrec] rec2] ifte
|
||||
|
||||
From “Recursion Theory and Joy” (j05cmp.html) by Manfred von Thun:
|
||||
|
||||
“The genrec combinator takes four program parameters in addition to
|
||||
whatever data parameters it needs. Fourth from the top is an if-part,
|
||||
followed by a then-part. If the if-part yields true, then the
|
||||
then-part is executed and the combinator terminates. The other two
|
||||
parameters are the rec1-part and the rec2-part. If the if-part yields
|
||||
false, the rec1-part is executed. Following that the four program
|
||||
parameters and the combinator are again pushed onto the stack bundled
|
||||
up in a quoted form. Then the rec2-part is executed, where it will
|
||||
find the bundled form. Typically it will then execute the bundled
|
||||
form, either with i or with app2, or some other combinator.”
|
||||
|
||||
Designing Recursive Functions
|
||||
-----------------------------
|
||||
|
||||
The way to design one of these is to fix your base case and test and
|
||||
then treat ``R1`` and ``R2`` as an else-part “sandwiching” a quotation
|
||||
of the whole function.
|
||||
|
||||
For example, given a (general recursive) function ``F``:
|
||||
|
||||
::
|
||||
|
||||
F == [I] [T] [R1] [R2] genrec
|
||||
== [I] [T] [R1 [F] R2] ifte
|
||||
|
||||
If the ``[I]`` predicate is false you must derive ``R1`` and ``R2``
|
||||
from:
|
||||
|
||||
::
|
||||
|
||||
... R1 [F] R2
|
||||
|
||||
Set the stack arguments in front and figure out what ``R1`` and ``R2``
|
||||
have to do to apply the quoted ``[F]`` in the proper way.
|
||||
|
||||
Primitive Recursive Functions
|
||||
-----------------------------
|
||||
|
||||
Primitive recursive functions are those where ``R2 == i``.
|
||||
|
||||
::
|
||||
|
||||
P == [I] [T] [R] primrec
|
||||
== [I] [T] [R [P] i] ifte
|
||||
== [I] [T] [R P] ifte
|
||||
|
||||
`Hylomorphism <https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>`__
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
A
|
||||
`hylomorphism <https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29>`__
|
||||
is a recursive function ``H :: A -> C`` that converts a value of type
|
||||
``A`` into a value of type ``C`` by means of:
|
||||
|
||||
- A generator ``G :: A -> (B, A)``
|
||||
- A combiner ``F :: (B, C) -> C``
|
||||
- A predicate ``P :: A -> Bool`` to detect the base case
|
||||
- A base case value ``c :: C``
|
||||
- Recursive calls (zero or more); it has a “call stack in the form of a
|
||||
cons list”.
|
||||
|
||||
It may be helpful to see this function implemented in imperative Python
|
||||
code.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
def hylomorphism(c, F, P, G):
|
||||
'''Return a hylomorphism function H.'''
|
||||
|
||||
def H(a):
|
||||
if P(a):
|
||||
result = c
|
||||
else:
|
||||
b, aa = G(a)
|
||||
result = F(b, H(aa)) # b is stored in the stack frame during recursive call to H().
|
||||
return result
|
||||
|
||||
return H
|
||||
|
||||
Cf. `“Bananas, Lenses, & Barbed
|
||||
Wire” <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125>`__
|
||||
|
||||
Note that during evaluation of ``H()`` the intermediate ``b`` values are
|
||||
stored in the Python call stack. This is what is meant by “call stack in
|
||||
the form of a cons list”.
|
||||
|
||||
Hylomorphism in Joy
|
||||
-------------------
|
||||
|
||||
We can define a combinator ``hylomorphism`` that will make a
|
||||
hylomorphism combinator ``H`` from constituent parts.
|
||||
|
||||
::
|
||||
|
||||
H == [P] c [G] [F] hylomorphism
|
||||
|
||||
The function ``H`` is recursive, so we start with ``ifte`` and set the
|
||||
else-part to some function ``J`` that will contain a quoted copy of
|
||||
``H``. (The then-part just discards the leftover ``a`` and replaces it
|
||||
with the base case value ``c``.)
|
||||
|
||||
::
|
||||
|
||||
H == [P] [pop c] [J] ifte
|
||||
|
||||
The else-part ``J`` gets just the argument ``a`` on the stack.
|
||||
|
||||
::
|
||||
|
||||
a J
|
||||
a G The first thing to do is use the generator G
|
||||
aa b which produces b and a new aa
|
||||
aa b [H] dip we recur with H on the new aa
|
||||
aa H b F and run F on the result.
|
||||
|
||||
This gives us a definition for ``J``.
|
||||
|
||||
::
|
||||
|
||||
J == G [H] dip F
|
||||
|
||||
Plug it in and convert to genrec.
|
||||
|
||||
::
|
||||
|
||||
H == [P] [pop c] [G [H] dip F] ifte
|
||||
H == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
This is the form of a hylomorphism in Joy, which nicely illustrates that
|
||||
it is a simple specialization of the general recursion combinator.
|
||||
|
||||
::
|
||||
|
||||
H == [P] c [G] [F] hylomorphism == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Derivation of ``hylomorphism`` combinator
|
||||
-----------------------------------------
|
||||
|
||||
Now we just need to derive a definition that builds the ``genrec``
|
||||
arguments out of the pieces given to the ``hylomorphism`` combinator.
|
||||
|
||||
::
|
||||
|
||||
[P] c [G] [F] hylomorphism
|
||||
------------------------------------------
|
||||
[P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Working in reverse:
|
||||
|
||||
- Use ``swoncat`` twice to decouple ``[c]`` and ``[F]``.
|
||||
- Use ``unit`` to dequote ``c``.
|
||||
- Use ``dipd`` to untangle ``[unit [pop] swoncat]`` from the givens.
|
||||
|
||||
So:
|
||||
|
||||
::
|
||||
|
||||
H == [P] [pop c] [G] [dip F] genrec
|
||||
[P] [c] [pop] swoncat [G] [F] [dip] swoncat genrec
|
||||
[P] c unit [pop] swoncat [G] [F] [dip] swoncat genrec
|
||||
[P] c [G] [F] [unit [pop] swoncat] dipd [dip] swoncat genrec
|
||||
|
||||
At this point all of the arguments (givens) to the hylomorphism are to
|
||||
the left so we have a definition for ``hylomorphism``:
|
||||
|
||||
::
|
||||
|
||||
hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')
|
||||
|
||||
Example: Finding `Triangular Numbers <https://en.wikipedia.org/wiki/Triangular_number>`__
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Let’s write a function that, given a positive integer, returns the sum
|
||||
of all positive integers less than that one. (In this case the types
|
||||
``A``, ``B`` and ``C`` are all ``int``.)
|
||||
|
||||
To sum a range of integers from 0 to *n* - 1:
|
||||
|
||||
- ``[P]`` is ``[1 <=]``
|
||||
- ``c`` is ``0``
|
||||
- ``[G]`` is ``[-- dup]``
|
||||
- ``[F]`` is ``[+]``
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')
|
||||
|
||||
Let’s try it:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 triangular_number')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
10
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[0 1 2 3 4 5 6] [triangular_number] map')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 0 1 3 6 10 15]
|
||||
|
||||
|
||||
Four Specializations
|
||||
--------------------
|
||||
|
||||
There are at least four kinds of recursive combinator, depending on two
|
||||
choices. The first choice is whether the combiner function ``F`` should
|
||||
be evaluated during the recursion or pushed into the pending expression
|
||||
to be “collapsed” at the end. The second choice is whether the combiner
|
||||
needs to operate on the current value of the datastructure or the
|
||||
generator’s output, in other words, whether ``F`` or ``G`` should run
|
||||
first in the recursive branch.
|
||||
|
||||
::
|
||||
|
||||
H1 == [P] [pop c] [G ] [dip F] genrec
|
||||
H2 == c swap [P] [pop] [G [F] dip ] [i] genrec
|
||||
H3 == [P] [pop c] [ [G] dupdip ] [dip F] genrec
|
||||
H4 == c swap [P] [pop] [ [F] dupdip G] [i] genrec
|
||||
|
||||
The working of the generator function ``G`` differs slightly for each.
|
||||
Consider the recursive branches:
|
||||
|
||||
::
|
||||
|
||||
... a G [H1] dip F w/ a G == a′ b
|
||||
|
||||
... c a G [F] dip H2 a G == b a′
|
||||
|
||||
... a [G] dupdip [H3] dip F a G == a′
|
||||
|
||||
... c a [F] dupdip G H4 a G == a′
|
||||
|
||||
The following four sections illustrate how these work, omitting the
|
||||
predicate evaluation.
|
||||
|
||||
``H1``
|
||||
~~~~~~
|
||||
|
||||
::
|
||||
|
||||
H1 == [P] [pop c] [G] [dip F] genrec
|
||||
|
||||
Iterate n times.
|
||||
|
||||
::
|
||||
|
||||
... a G [H1] dip F
|
||||
... a′ b [H1] dip F
|
||||
... a′ H1 b F
|
||||
... a′ G [H1] dip F b F
|
||||
... a″ b′ [H1] dip F b F
|
||||
... a″ H1 b′ F b F
|
||||
... a″ G [H1] dip F b′ F b F
|
||||
... a‴ b″ [H1] dip F b′ F b F
|
||||
... a‴ H1 b″ F b′ F b F
|
||||
... a‴ pop c b″ F b′ F b F
|
||||
... c b″ F b′ F b F
|
||||
... d b′ F b F
|
||||
... d′ b F
|
||||
... d″
|
||||
|
||||
This form builds up a pending expression (continuation) that contains
|
||||
the intermediate results along with the pending combiner functions. When
|
||||
the base case is reached the last term is replaced by the identity value
|
||||
``c`` and the continuation “collapses” into the final result using the
|
||||
combiner ``F``.
|
||||
|
||||
``H2``
|
||||
~~~~~~
|
||||
|
||||
When you can start with the identity value ``c`` on the stack and the
|
||||
combiner ``F`` can operate as you go using the intermediate results
|
||||
immediately rather than queuing them up, use this form. An important
|
||||
difference is that the generator function must return its results in the
|
||||
reverse order.
|
||||
|
||||
::
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
|
||||
... c a G [F] dip H2
|
||||
... c b a′ [F] dip H2
|
||||
... c b F a′ H2
|
||||
... d a′ H2
|
||||
... d a′ G [F] dip H2
|
||||
... d b′ a″ [F] dip H2
|
||||
... d b′ F a″ H2
|
||||
... d′ a″ H2
|
||||
... d′ a″ G [F] dip H2
|
||||
... d′ b″ a‴ [F] dip H2
|
||||
... d′ b″ F a‴ H2
|
||||
... d″ a‴ H2
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
|
||||
``H3``
|
||||
~~~~~~
|
||||
|
||||
If you examine the traces above you’ll see that the combiner ``F`` only
|
||||
gets to operate on the results of ``G``, it never “sees” the first value
|
||||
``a``. If the combiner and the generator both need to work on the
|
||||
current value then ``dup`` must be used, and the generator must produce
|
||||
one item instead of two (the b is instead the duplicate of a.)
|
||||
|
||||
::
|
||||
|
||||
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||
|
||||
... a [G] dupdip [H3] dip F
|
||||
... a G a [H3] dip F
|
||||
... a′ a [H3] dip F
|
||||
... a′ H3 a F
|
||||
... a′ [G] dupdip [H3] dip F a F
|
||||
... a′ G a′ [H3] dip F a F
|
||||
... a″ a′ [H3] dip F a F
|
||||
... a″ H3 a′ F a F
|
||||
... a″ [G] dupdip [H3] dip F a′ F a F
|
||||
... a″ G a″ [H3] dip F a′ F a F
|
||||
... a‴ a″ [H3] dip F a′ F a F
|
||||
... a‴ H3 a″ F a′ F a F
|
||||
... a‴ pop c a″ F a′ F a F
|
||||
... c a″ F a′ F a F
|
||||
... d a′ F a F
|
||||
... d′ a F
|
||||
... d″
|
||||
|
||||
``H4``
|
||||
~~~~~~
|
||||
|
||||
And, last but not least, if you can combine as you go, starting with
|
||||
``c``, and the combiner ``F`` needs to work on the current item, this is
|
||||
the form:
|
||||
|
||||
::
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G] primrec
|
||||
|
||||
... c a [F] dupdip G H4
|
||||
... c a F a G H4
|
||||
... d a G H4
|
||||
... d a′ H4
|
||||
... d a′ [F] dupdip G H4
|
||||
... d a′ F a′ G H4
|
||||
... d′ a′ G H4
|
||||
... d′ a″ H4
|
||||
... d′ a″ [F] dupdip G H4
|
||||
... d′ a″ F a″ G H4
|
||||
... d″ a″ G H4
|
||||
... d″ a‴ H4
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
|
||||
Anamorphism
|
||||
-----------
|
||||
|
||||
An anamorphism can be defined as a hylomorphism that uses ``[]`` for
|
||||
``c`` and ``swons`` for ``F``. An anamorphic function builds a list of
|
||||
values.
|
||||
|
||||
::
|
||||
|
||||
A == [P] [] [G] [swons] hylomorphism
|
||||
|
||||
``range`` et. al. An example of an anamorphism is the ``range`` function which generates the list of integers from 0 to *n* - 1 given *n*.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Each of the above variations can be used to make four slightly different
|
||||
``range`` functions.
|
||||
|
||||
``range`` with ``H1``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H1 == [P] [pop c] [G] [dip F] genrec
|
||||
== [0 <=] [pop []] [-- dup] [dip swons] genrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('range == [0 <=] [] [-- dup] [swons] hylomorphism')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 range')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[4 3 2 1 0]
|
||||
|
||||
|
||||
``range`` with ``H2``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
== [] swap [0 <=] [pop] [-- dup [swons] dip] primrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 range_reverse')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 1 2 3 4]
|
||||
|
||||
|
||||
``range`` with ``H3``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||
== [0 <=] [pop []] [[--] dupdip] [dip swons] genrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 ranger')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[5 4 3 2 1]
|
||||
|
||||
|
||||
``range`` with ``H4``
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
::
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G ] primrec
|
||||
== [] swap [0 <=] [pop] [[swons] dupdip --] primrec
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 ranger_reverse')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1 2 3 4 5]
|
||||
|
||||
|
||||
Hopefully this illustrates the workings of the variations. For more
|
||||
insight you can run the cells using the ``V()`` function instead of the
|
||||
``J()`` function to get a trace of the Joy evaluation.
|
||||
|
||||
Catamorphism
|
||||
------------
|
||||
|
||||
A catamorphism can be defined as a hylomorphism that uses
|
||||
``[uncons swap]`` for ``[G]`` and ``[[] =]`` (or just ``[not]``) for the
|
||||
predicate ``[P]``. A catamorphic function tears down a list term-by-term
|
||||
and makes some new value.
|
||||
|
||||
::
|
||||
|
||||
C == [not] c [uncons swap] [F] hylomorphism
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('swuncons == uncons swap') # Awkward name.
|
||||
|
||||
An example of a catamorphism is the sum function.
|
||||
|
||||
::
|
||||
|
||||
sum == [not] 0 [swuncons] [+] hylomorphism
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('sum == [not] 0 [swuncons] [+] hylomorphism')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[5 4 3 2 1] sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
15
|
||||
|
||||
|
||||
The ``step`` combinator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``step`` combinator will usually be better to use than
|
||||
``catamorphism``.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[step] help')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
Run a quoted program on each item in a sequence.
|
||||
::
|
||||
|
||||
... [] [Q] . step
|
||||
-----------------------
|
||||
... .
|
||||
|
||||
|
||||
... [a] [Q] . step
|
||||
------------------------
|
||||
... a . Q
|
||||
|
||||
|
||||
... [a b c] [Q] . step
|
||||
----------------------------------------
|
||||
... a . Q [b c] [Q] step
|
||||
|
||||
The step combinator executes the quotation on each member of the list
|
||||
on top of the stack.
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('sum == 0 swap [+] step')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[5 4 3 2 1] sum')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
15
|
||||
|
||||
|
||||
Example: Factorial Function
|
||||
---------------------------
|
||||
|
||||
For the Factorial function:
|
||||
|
||||
::
|
||||
|
||||
H4 == c swap [P] [pop] [[F] dupdip G] primrec
|
||||
|
||||
With:
|
||||
|
||||
::
|
||||
|
||||
c == 1
|
||||
F == *
|
||||
G == --
|
||||
P == 1 <=
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('5 factorial')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
120
|
||||
|
||||
|
||||
Example: ``tails``
|
||||
------------------
|
||||
|
||||
An example of a paramorphism for lists given in the `“Bananas…”
|
||||
paper <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125>`__
|
||||
is ``tails`` which returns the list of “tails” of a list.
|
||||
|
||||
::
|
||||
|
||||
[1 2 3] tails
|
||||
--------------------
|
||||
[[] [3] [2 3]]
|
||||
|
||||
We can build as we go, and we want ``F`` to run after ``G``, so we use
|
||||
pattern ``H2``:
|
||||
|
||||
::
|
||||
|
||||
H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
|
||||
We would use:
|
||||
|
||||
::
|
||||
|
||||
c == []
|
||||
F == swons
|
||||
G == rest dup
|
||||
P == not
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1 2 3] tails')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[[] [3] [2 3]]
|
||||
|
||||
|
||||
Conclusion: Patterns of Recursion
|
||||
---------------------------------
|
||||
|
||||
Our story so far…
|
||||
|
||||
Hylo-, Ana-, Cata-
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
H == [P ] [pop c ] [G ] [dip F ] genrec
|
||||
A == [P ] [pop []] [G ] [dip swap cons] genrec
|
||||
C == [not] [pop c ] [uncons swap] [dip F ] genrec
|
||||
|
||||
Para-, ?-, ?-
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
P == c swap [P ] [pop] [[F ] dupdip G ] primrec
|
||||
? == [] swap [P ] [pop] [[swap cons] dupdip G ] primrec
|
||||
? == c swap [not] [pop] [[F ] dupdip uncons swap] primrec
|
||||
|
||||
Appendix: Fun with Symbols
|
||||
--------------------------
|
||||
|
||||
::
|
||||
|
||||
|[ (c, F), (G, P) ]| == (|c, F|) • [(G, P)]
|
||||
|
||||
`“Bananas, Lenses, & Barbed
|
||||
Wire” <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125>`__
|
||||
|
||||
::
|
||||
|
||||
(|...|) [(...)] [<...>]
|
||||
|
||||
I think they are having slightly too much fun with the symbols. However,
|
||||
“Too much is always better than not enough.”
|
||||
|
|
@ -1,147 +0,0 @@
|
|||
Replacing Functions in the Dictionary
|
||||
=====================================
|
||||
|
||||
For now, there is no way to define new functions from within the Joy
|
||||
language. All functions (and the interpreter) all accept and return a
|
||||
dictionary parameter (in addition to the stack and expression) so that
|
||||
we can implement e.g. a function that adds new functions to the
|
||||
dictionary. However, there’s no function that does that. Adding a new
|
||||
function to the dictionary is a meta-interpreter action, you have to do
|
||||
it in Python, not Joy.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import D, J, V
|
||||
|
||||
A long trace
|
||||
------------
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('[23 18] average')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. [23 18] average
|
||||
[23 18] . average
|
||||
[23 18] . [sum 1.0 *] [size] cleave /
|
||||
[23 18] [sum 1.0 *] . [size] cleave /
|
||||
[23 18] [sum 1.0 *] [size] . cleave /
|
||||
[23 18] [sum 1.0 *] [size] . [i] app2 [popd] dip /
|
||||
[23 18] [sum 1.0 *] [size] [i] . app2 [popd] dip /
|
||||
[23 18] [[sum 1.0 *] [23 18]] [i] . infra first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] [sum 1.0 *] . i [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] . sum 1.0 * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
41 . 1.0 * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
41 1.0 . * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
41.0 . [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
41.0 [[23 18]] . swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] [41.0] . first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] 41.0 . [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] 41.0 [[size] [23 18]] . [i] infra first [popd] dip /
|
||||
[23 18] 41.0 [[size] [23 18]] [i] . infra first [popd] dip /
|
||||
[23 18] [size] . i [41.0 [23 18]] swaack first [popd] dip /
|
||||
[23 18] . size [41.0 [23 18]] swaack first [popd] dip /
|
||||
[23 18] . 0 swap [pop ++] step [41.0 [23 18]] swaack first [popd] dip /
|
||||
[23 18] 0 . swap [pop ++] step [41.0 [23 18]] swaack first [popd] dip /
|
||||
0 [23 18] . [pop ++] step [41.0 [23 18]] swaack first [popd] dip /
|
||||
0 [23 18] [pop ++] . step [41.0 [23 18]] swaack first [popd] dip /
|
||||
0 23 [pop ++] . i [18] [pop ++] step [41.0 [23 18]] swaack first [popd] dip /
|
||||
0 23 . pop ++ [18] [pop ++] step [41.0 [23 18]] swaack first [popd] dip /
|
||||
0 . ++ [18] [pop ++] step [41.0 [23 18]] swaack first [popd] dip /
|
||||
1 . [18] [pop ++] step [41.0 [23 18]] swaack first [popd] dip /
|
||||
1 [18] . [pop ++] step [41.0 [23 18]] swaack first [popd] dip /
|
||||
1 [18] [pop ++] . step [41.0 [23 18]] swaack first [popd] dip /
|
||||
1 18 [pop ++] . i [41.0 [23 18]] swaack first [popd] dip /
|
||||
1 18 . pop ++ [41.0 [23 18]] swaack first [popd] dip /
|
||||
1 . ++ [41.0 [23 18]] swaack first [popd] dip /
|
||||
2 . [41.0 [23 18]] swaack first [popd] dip /
|
||||
2 [41.0 [23 18]] . swaack first [popd] dip /
|
||||
[23 18] 41.0 [2] . first [popd] dip /
|
||||
[23 18] 41.0 2 . [popd] dip /
|
||||
[23 18] 41.0 2 [popd] . dip /
|
||||
[23 18] 41.0 . popd 2 /
|
||||
41.0 . 2 /
|
||||
41.0 2 . /
|
||||
20.5 .
|
||||
|
||||
|
||||
Replacing ``size`` with a Python version
|
||||
----------------------------------------
|
||||
|
||||
Both ``sum`` and ``size`` each convert a sequence to a single value.
|
||||
|
||||
::
|
||||
|
||||
sum == 0 swap [+] step
|
||||
size == 0 swap [pop ++] step
|
||||
|
||||
An efficient ``sum`` function is already in the library. But for
|
||||
``size`` we can use a “compiled” version hand-written in Python to speed
|
||||
up evaluation and make the trace more readable.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from joy.library import SimpleFunctionWrapper
|
||||
from joy.utils.stack import iter_stack
|
||||
|
||||
|
||||
@SimpleFunctionWrapper
|
||||
def size(stack):
|
||||
'''Return the size of the sequence on the stack.'''
|
||||
sequence, stack = stack
|
||||
n = 0
|
||||
for _ in iter_stack(sequence):
|
||||
n += 1
|
||||
return n, stack
|
||||
|
||||
Now we replace the old version in the dictionary with the new version,
|
||||
and re-evaluate the expression.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
D['size'] = size
|
||||
|
||||
A shorter trace
|
||||
---------------
|
||||
|
||||
You can see that ``size`` now executes in a single step.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('[23 18] average')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. [23 18] average
|
||||
[23 18] . average
|
||||
[23 18] . [sum 1.0 *] [size] cleave /
|
||||
[23 18] [sum 1.0 *] . [size] cleave /
|
||||
[23 18] [sum 1.0 *] [size] . cleave /
|
||||
[23 18] [sum 1.0 *] [size] . [i] app2 [popd] dip /
|
||||
[23 18] [sum 1.0 *] [size] [i] . app2 [popd] dip /
|
||||
[23 18] [[sum 1.0 *] [23 18]] [i] . infra first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] [sum 1.0 *] . i [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] . sum 1.0 * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
41 . 1.0 * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
41 1.0 . * [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
41.0 . [[23 18]] swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
41.0 [[23 18]] . swaack first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] [41.0] . first [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] 41.0 . [[size] [23 18]] [i] infra first [popd] dip /
|
||||
[23 18] 41.0 [[size] [23 18]] . [i] infra first [popd] dip /
|
||||
[23 18] 41.0 [[size] [23 18]] [i] . infra first [popd] dip /
|
||||
[23 18] [size] . i [41.0 [23 18]] swaack first [popd] dip /
|
||||
[23 18] . size [41.0 [23 18]] swaack first [popd] dip /
|
||||
2 . [41.0 [23 18]] swaack first [popd] dip /
|
||||
2 [41.0 [23 18]] . swaack first [popd] dip /
|
||||
[23 18] 41.0 [2] . first [popd] dip /
|
||||
[23 18] 41.0 2 . [popd] dip /
|
||||
[23 18] 41.0 2 [popd] . dip /
|
||||
[23 18] 41.0 . popd 2 /
|
||||
41.0 . 2 /
|
||||
41.0 2 . /
|
||||
20.5 .
|
||||
|
||||
|
|
@ -1,421 +0,0 @@
|
|||
.. code:: ipython3
|
||||
|
||||
from notebook_preamble import J, V, define
|
||||
|
||||
Square Spiral Example Joy Code
|
||||
==============================
|
||||
|
||||
Here is the example of Joy code from the ``README`` file:
|
||||
|
||||
::
|
||||
|
||||
[[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
|
||||
|
||||
It might seem unreadable but with a little familiarity it becomes just
|
||||
as legible as any other notation. Some layout helps:
|
||||
|
||||
::
|
||||
|
||||
[ [[abs] ii <=]
|
||||
[
|
||||
[<>] [pop !-] ||
|
||||
] &&
|
||||
]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
This function accepts two integers on the stack and increments or
|
||||
decrements one of them such that the new pair of numbers is the next
|
||||
coordinate pair in a square spiral (like the kind used to construct an
|
||||
Ulam Spiral).
|
||||
|
||||
Original Form
|
||||
-------------
|
||||
|
||||
It's adapted from `the original code on
|
||||
StackOverflow <https://stackoverflow.com/questions/398299/looping-in-a-spiral/31864777#31864777>`__:
|
||||
|
||||
If all you're trying to do is generate the first N points in the
|
||||
spiral (without the original problem's constraint of masking to an N
|
||||
x M region), the code becomes very simple:
|
||||
|
||||
::
|
||||
|
||||
void spiral(const int N)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for(int i = 0; i < N; ++i)
|
||||
{
|
||||
cout << x << '\t' << y << '\n';
|
||||
if(abs(x) <= abs(y) && (x != y || x >= 0))
|
||||
x += ((y >= 0) ? 1 : -1);
|
||||
else
|
||||
y += ((x >= 0) ? -1 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
Translation to Joy
|
||||
------------------
|
||||
|
||||
I'm going to make a function that take two ints (``x`` and ``y``) and
|
||||
generates the next pair, we'll turn it into a generator later using the
|
||||
``x`` combinator.
|
||||
|
||||
First Boolean Predicate
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We need a function that computes ``abs(x) <= abs(y)``, we can use ``ii``
|
||||
to apply ``abs`` to both values and then compare them with ``<=``:
|
||||
|
||||
::
|
||||
|
||||
[abs] ii <=
|
||||
|
||||
I've defined two short-circuiting Boolean combinators ``&&`` and ``||``
|
||||
that each accept two quoted predicate programs, run the first, and
|
||||
conditionally run the second only if required (to compute the final
|
||||
Boolean value). They run their predicate arguments ``nullary``.
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('&& [nullary] cons [nullary [0]] dip branch')
|
||||
define('|| [nullary] cons [nullary] dip [1] branch')
|
||||
|
||||
Given those, we can define ``x != y || x >= 0`` as:
|
||||
|
||||
::
|
||||
|
||||
[<>] [pop 0 >=] ||
|
||||
|
||||
And ``(abs(x) <= abs(y) && (x != y || x >= 0))`` as:
|
||||
|
||||
::
|
||||
|
||||
[[abs] ii <=] [[<>] [pop 0 >=] ||] &&
|
||||
|
||||
It's a little rough, but, as I say, with a little familiarity it becomes
|
||||
legible.
|
||||
|
||||
The Increment / Decrement Branches
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Turning to the branches of the main ``if`` statement:
|
||||
|
||||
::
|
||||
|
||||
x += ((y >= 0) ? 1 : -1);
|
||||
|
||||
Rewrite as a hybrid (pseudo-code) ``ifte`` expression:
|
||||
|
||||
::
|
||||
|
||||
[y >= 0] [x += 1] [X -= 1] ifte
|
||||
|
||||
Change each C phrase to Joy code:
|
||||
|
||||
::
|
||||
|
||||
[0 >=] [[++] dip] [[--] dip] ifte
|
||||
|
||||
Factor out the dip from each branch:
|
||||
|
||||
::
|
||||
|
||||
[0 >=] [[++]] [[--]] ifte dip
|
||||
|
||||
Similar logic applies to the other branch:
|
||||
|
||||
::
|
||||
|
||||
y += ((x >= 0) ? -1 : 1);
|
||||
|
||||
[x >= 0] [y -= 1] [y += 1] ifte
|
||||
|
||||
[pop 0 >=] [--] [++] ifte
|
||||
|
||||
"Not Negative"
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('!- 0 >=')
|
||||
|
||||
Putting the Pieces Together
|
||||
---------------------------
|
||||
|
||||
We can assemble the three functions we just defined in quotes and give
|
||||
them them to the ``ifte`` combinator. With some arrangement to show off
|
||||
the symmetry of the two branches, we have:
|
||||
|
||||
::
|
||||
|
||||
[[[abs] ii <=] [[<>] [pop !-] ||] &&]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
|
||||
As I was writing this up I realized that, since the ``&&`` combinator
|
||||
doesn't consume the stack (below its quoted args), I can unquote the
|
||||
predicate, swap the branches, and use the ``branch`` combinator instead
|
||||
of ``ifte``:
|
||||
|
||||
::
|
||||
|
||||
[[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
branch
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte')
|
||||
|
||||
Let's try it out:
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('0 0 spiral_next')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
1 0
|
||||
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('1 0 spiral_next')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
1 -1
|
||||
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('1 -1 spiral_next')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
0 -1
|
||||
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('0 -1 spiral_next')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
-1 -1
|
||||
|
||||
|
||||
Turning it into a Generator with ``x``
|
||||
--------------------------------------
|
||||
|
||||
It can be used with the x combinator to make a kind of generator for
|
||||
spiral square coordinates.
|
||||
|
||||
We can use ``codireco`` to make a generator
|
||||
|
||||
::
|
||||
|
||||
codireco ::= cons dip rest cons
|
||||
|
||||
It will look like this:
|
||||
|
||||
::
|
||||
|
||||
[value [F] codireco]
|
||||
|
||||
Here's a trace of how it works:
|
||||
|
||||
::
|
||||
|
||||
[0 [dup ++] codireco] . x
|
||||
[0 [dup ++] codireco] . 0 [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 . [dup ++] codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . codireco
|
||||
[0 [dup ++] codireco] 0 [dup ++] . cons dip rest cons
|
||||
[0 [dup ++] codireco] [0 dup ++] . dip rest cons
|
||||
. 0 dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 . dup ++ [0 [dup ++] codireco] rest cons
|
||||
0 0 . ++ [0 [dup ++] codireco] rest cons
|
||||
0 1 . [0 [dup ++] codireco] rest cons
|
||||
0 1 [0 [dup ++] codireco] . rest cons
|
||||
0 1 [[dup ++] codireco] . cons
|
||||
0 [1 [dup ++] codireco] .
|
||||
|
||||
But first we have to change the ``spiral_next`` function to work on a
|
||||
quoted pair of integers, and leave a copy of the pair on the stack.
|
||||
From:
|
||||
|
||||
::
|
||||
|
||||
y x spiral_next
|
||||
---------------------
|
||||
y' x'
|
||||
|
||||
to:
|
||||
|
||||
::
|
||||
|
||||
[x y] [spiral_next] infra
|
||||
-------------------------------
|
||||
[x' y']
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('[0 0] [spiral_next] infra')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 1]
|
||||
|
||||
|
||||
So our generator is:
|
||||
|
||||
::
|
||||
|
||||
[[x y] [dup [spiral_next] infra] codireco]
|
||||
|
||||
Or rather:
|
||||
|
||||
::
|
||||
|
||||
[[0 0] [dup [spiral_next] infra] codireco]
|
||||
|
||||
There is a function ``make_generator`` that will build the generator for
|
||||
us out of the value and stepper function:
|
||||
|
||||
::
|
||||
|
||||
[0 0] [dup [spiral_next] infra] make_generator
|
||||
----------------------------------------------------
|
||||
[[0 0] [dup [spiral_next] infra] codireco]
|
||||
|
||||
Here it is in action:
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[0 0] [0 1] [-1 1] [-1 0]
|
||||
|
||||
|
||||
Four ``x`` combinators, four pairs of coordinates.
|
||||
|
||||
Conclusion
|
||||
----------
|
||||
|
||||
So that's an example of Joy code. It's a straightforward translation of
|
||||
the original. It's a little long for a single definition, you might
|
||||
break it up like so:
|
||||
|
||||
::
|
||||
|
||||
_spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
|
||||
_spn_T ::= [ !-] [[++]] [[--]] ifte dip
|
||||
_spn_E ::= [pop !-] [--] [++] ifte
|
||||
|
||||
spiral_next ::= _spn_P [_spn_E] [_spn_T] branch
|
||||
|
||||
This way it's easy to see that the function is a branch with two
|
||||
quasi-symmetrical paths.
|
||||
|
||||
We then used this function to make a simple generator of coordinate
|
||||
pairs, where the next pair in the series can be generated at any time by
|
||||
using the ``x`` combinator on the generator (which is just a quoted
|
||||
expression containing a copy of the current pair and the "stepper
|
||||
function" to generate the next pair from that.)
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&')
|
||||
define('_spn_T [!-] [[++]] [[--]] ifte dip')
|
||||
define('_spn_E [pop !-] [--] [++] ifte')
|
||||
define('spiral_next _spn_P [_spn_E] [_spn_T] branch')
|
||||
|
||||
.. code:: ipython3
|
||||
|
||||
V('23 18 spiral_next')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 23 18 spiral_next
|
||||
23 . 18 spiral_next
|
||||
23 18 . spiral_next
|
||||
23 18 . _spn_P [_spn_E] [_spn_T] branch
|
||||
23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch
|
||||
23 18 . 0 [_spn_E] [_spn_T] branch
|
||||
23 18 0 . [_spn_E] [_spn_T] branch
|
||||
23 18 0 [_spn_E] . [_spn_T] branch
|
||||
23 18 0 [_spn_E] [_spn_T] . branch
|
||||
23 18 . _spn_E
|
||||
23 18 . [pop !-] [--] [++] ifte
|
||||
23 18 [pop !-] . [--] [++] ifte
|
||||
23 18 [pop !-] [--] . [++] ifte
|
||||
23 18 [pop !-] [--] [++] . ifte
|
||||
23 18 [pop !-] [--] [++] . [nullary not] dipd branch
|
||||
23 18 [pop !-] [--] [++] [nullary not] . dipd branch
|
||||
23 18 [pop !-] . nullary not [--] [++] branch
|
||||
23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch
|
||||
23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch
|
||||
23 18 [pop !-] [stack] . dip infra first not [--] [++] branch
|
||||
23 18 . stack [pop !-] infra first not [--] [++] branch
|
||||
23 18 [18 23] . [pop !-] infra first not [--] [++] branch
|
||||
23 18 [18 23] [pop !-] . infra first not [--] [++] branch
|
||||
23 18 . pop !- [18 23] swaack first not [--] [++] branch
|
||||
23 . !- [18 23] swaack first not [--] [++] branch
|
||||
23 . 0 >= [18 23] swaack first not [--] [++] branch
|
||||
23 0 . >= [18 23] swaack first not [--] [++] branch
|
||||
True . [18 23] swaack first not [--] [++] branch
|
||||
True [18 23] . swaack first not [--] [++] branch
|
||||
23 18 [True] . first not [--] [++] branch
|
||||
23 18 True . not [--] [++] branch
|
||||
23 18 False . [--] [++] branch
|
||||
23 18 False [--] . [++] branch
|
||||
23 18 False [--] [++] . branch
|
||||
23 18 . --
|
||||
23 17 .
|
||||
|
||||
|
|
@ -1,336 +0,0 @@
|
|||
The Four Fundamental Operations of Definite Action
|
||||
==================================================
|
||||
|
||||
All definite actions (computer program) can be defined by four
|
||||
fundamental patterns of combination:
|
||||
|
||||
1. Sequence
|
||||
2. Branch
|
||||
3. Loop
|
||||
4. Parallel
|
||||
|
||||
Sequence
|
||||
--------
|
||||
|
||||
Do one thing after another. In joy this is represented by putting two
|
||||
symbols together, juxtaposition:
|
||||
|
||||
::
|
||||
|
||||
foo bar
|
||||
|
||||
Operations have inputs and outputs. The outputs of ``foo`` must be
|
||||
compatible in “arity”, type, and shape with the inputs of ``bar``.
|
||||
|
||||
Branch
|
||||
------
|
||||
|
||||
Do one thing or another.
|
||||
|
||||
::
|
||||
|
||||
boolean [F] [T] branch
|
||||
|
||||
|
||||
t [F] [T] branch
|
||||
----------------------
|
||||
T
|
||||
|
||||
|
||||
f [F] [T] branch
|
||||
----------------------
|
||||
F
|
||||
|
||||
|
||||
branch == unit cons swap pick i
|
||||
|
||||
boolean [F] [T] branch
|
||||
boolean [F] [T] unit cons swap pick i
|
||||
boolean [F] [[T]] cons swap pick i
|
||||
boolean [[F] [T]] swap pick i
|
||||
[[F] [T]] boolean pick i
|
||||
[F-or-T] i
|
||||
|
||||
Given some branch function ``G``:
|
||||
|
||||
::
|
||||
|
||||
G == [F] [T] branch
|
||||
|
||||
Used in a sequence like so:
|
||||
|
||||
::
|
||||
|
||||
foo G bar
|
||||
|
||||
The inputs and outputs of ``F`` and ``T`` must be compatible with the
|
||||
outputs for ``foo`` and the inputs of ``bar``, respectively.
|
||||
|
||||
::
|
||||
|
||||
foo F bar
|
||||
|
||||
foo T bar
|
||||
|
||||
``ifte``
|
||||
~~~~~~~~
|
||||
|
||||
Often it will be easier on the programmer to write branching code with
|
||||
the predicate specified in a quote. The ``ifte`` combinator provides
|
||||
this (``T`` for “then” and ``E`` for “else”):
|
||||
|
||||
::
|
||||
|
||||
[P] [T] [E] ifte
|
||||
|
||||
Defined in terms of ``branch``:
|
||||
|
||||
::
|
||||
|
||||
ifte == [nullary not] dip branch
|
||||
|
||||
In this case, ``P`` must be compatible with the stack and return a
|
||||
Boolean value, and ``T`` and ``E`` both must be compatible with the
|
||||
preceeding and following functions, as described above for ``F`` and
|
||||
``T``. (Note that in the current implementation we are depending on
|
||||
Python for the underlying semantics, so the Boolean value doesn’t *have*
|
||||
to be Boolean because Python’s rules for “truthiness” will be used to
|
||||
evaluate it. I reflect this in the structure of the stack effect comment
|
||||
of ``branch``, it will only accept Boolean values, and in the definition
|
||||
of ``ifte`` above by including ``not`` in the quote, which also has the
|
||||
effect that the subject quotes are in the proper order for ``branch``.)
|
||||
|
||||
Loop
|
||||
----
|
||||
|
||||
Do one thing zero or more times.
|
||||
|
||||
::
|
||||
|
||||
boolean [Q] loop
|
||||
|
||||
|
||||
t [Q] loop
|
||||
----------------
|
||||
Q [Q] loop
|
||||
|
||||
|
||||
... f [Q] loop
|
||||
--------------------
|
||||
...
|
||||
|
||||
The ``loop`` combinator generates a copy of itself in the true branch.
|
||||
This is the hallmark of recursive defintions. In Thun there is no
|
||||
equivalent to conventional loops. (There is, however, the ``x``
|
||||
combinator, defined as ``x == dup i``, which permits recursive
|
||||
constructs that do not need to be directly self-referential, unlike
|
||||
``loop`` and ``genrec``.)
|
||||
|
||||
::
|
||||
|
||||
loop == [] swap [dup dip loop] cons branch
|
||||
|
||||
boolean [Q] loop
|
||||
boolean [Q] [] swap [dup dip loop] cons branch
|
||||
boolean [] [Q] [dup dip loop] cons branch
|
||||
boolean [] [[Q] dup dip loop] branch
|
||||
|
||||
In action the false branch does nothing while the true branch does:
|
||||
|
||||
::
|
||||
|
||||
t [] [[Q] dup dip loop] branch
|
||||
[Q] dup dip loop
|
||||
[Q] [Q] dip loop
|
||||
Q [Q] loop
|
||||
|
||||
Because ``loop`` expects and consumes a Boolean value, the ``Q``
|
||||
function must be compatible with the previous stack *and itself* with a
|
||||
boolean flag for the next iteration:
|
||||
|
||||
::
|
||||
|
||||
Q == G b
|
||||
|
||||
Q [Q] loop
|
||||
G b [Q] loop
|
||||
G Q [Q] loop
|
||||
G G b [Q] loop
|
||||
G G Q [Q] loop
|
||||
G G G b [Q] loop
|
||||
G G G
|
||||
|
||||
``while``
|
||||
~~~~~~~~~
|
||||
|
||||
Keep doing ``B`` *while* some predicate ``P`` is true. This is
|
||||
convenient as the predicate function is made nullary automatically and
|
||||
the body function can be designed without regard to leaving a Boolean
|
||||
flag for the next iteration:
|
||||
|
||||
::
|
||||
|
||||
[P] [B] while
|
||||
--------------------------------------
|
||||
[P] nullary [B [P] nullary] loop
|
||||
|
||||
|
||||
while == swap [nullary] cons dup dipd concat loop
|
||||
|
||||
|
||||
[P] [B] while
|
||||
[P] [B] swap [nullary] cons dup dipd concat loop
|
||||
[B] [P] [nullary] cons dup dipd concat loop
|
||||
[B] [[P] nullary] dup dipd concat loop
|
||||
[B] [[P] nullary] [[P] nullary] dipd concat loop
|
||||
[P] nullary [B] [[P] nullary] concat loop
|
||||
[P] nullary [B [P] nullary] loop
|
||||
|
||||
Parallel
|
||||
--------
|
||||
|
||||
The *parallel* operation indicates that two (or more) functions *do not
|
||||
interfere* with each other and so can run in parallel. The main
|
||||
difficulty in this sort of thing is orchestrating the recombining
|
||||
(“join” or “wait”) of the results of the functions after they finish.
|
||||
|
||||
The current implementaions and the following definitions *are not
|
||||
actually parallel* (yet), but there is no reason they couldn’t be
|
||||
reimplemented in terms of e.g. Python threads. I am not concerned with
|
||||
performance of the system just yet, only the elegance of the code it
|
||||
allows us to write.
|
||||
|
||||
``cleave``
|
||||
~~~~~~~~~~
|
||||
|
||||
Joy has a few parallel combinators, the main one being ``cleave``:
|
||||
|
||||
::
|
||||
|
||||
... x [A] [B] cleave
|
||||
---------------------------------------------------------
|
||||
... [x ...] [A] infra first [x ...] [B] infra first
|
||||
---------------------------------------------------------
|
||||
... a b
|
||||
|
||||
The ``cleave`` combinator expects a value and two quotes and it executes
|
||||
each quote in “separate universes” such that neither can affect the
|
||||
other, then it takes the first item from the stack in each universe and
|
||||
replaces the value and quotes with their respective results.
|
||||
|
||||
(I think this corresponds to the “fork” operator, the little
|
||||
upward-pointed triangle, that takes two functions ``A :: x -> a`` and
|
||||
``B :: x -> b`` and returns a function ``F :: x -> (a, b)``, in Conal
|
||||
Elliott’s “Compiling to Categories” paper, et. al.)
|
||||
|
||||
Just a thought, if you ``cleave`` two jobs and one requires more time to
|
||||
finish than the other you’d like to be able to assign resources
|
||||
accordingly so that they both finish at the same time.
|
||||
|
||||
“Apply” Functions
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are also ``app2`` and ``app3`` which run a single quote on more
|
||||
than one value:
|
||||
|
||||
::
|
||||
|
||||
... y x [Q] app2
|
||||
---------------------------------------------------------
|
||||
... [y ...] [Q] infra first [x ...] [Q] infra first
|
||||
|
||||
|
||||
... z y x [Q] app3
|
||||
---------------------------------
|
||||
... [z ...] [Q] infra first
|
||||
[y ...] [Q] infra first
|
||||
[x ...] [Q] infra first
|
||||
|
||||
Because the quoted program can be ``i`` we can define ``cleave`` in
|
||||
terms of ``app2``:
|
||||
|
||||
::
|
||||
|
||||
cleave == [i] app2 [popd] dip
|
||||
|
||||
(I’m not sure why ``cleave`` was specified to take that value, I may
|
||||
make a combinator that does the same thing but without expecting a
|
||||
value.)
|
||||
|
||||
::
|
||||
|
||||
clv == [i] app2
|
||||
|
||||
[A] [B] clv
|
||||
------------------
|
||||
a b
|
||||
|
||||
``map``
|
||||
~~~~~~~
|
||||
|
||||
The common ``map`` function in Joy should also be though of as a
|
||||
*parallel* operator:
|
||||
|
||||
::
|
||||
|
||||
[a b c ...] [Q] map
|
||||
|
||||
There is no reason why the implementation of ``map`` couldn’t distribute
|
||||
the ``Q`` function over e.g. a pool of worker CPUs.
|
||||
|
||||
``pam``
|
||||
~~~~~~~
|
||||
|
||||
One of my favorite combinators, the ``pam`` combinator is just:
|
||||
|
||||
::
|
||||
|
||||
pam == [i] map
|
||||
|
||||
This can be used to run any number of programs separately on the current
|
||||
stack and combine their (first) outputs in a result list.
|
||||
|
||||
::
|
||||
|
||||
[[A] [B] [C] ...] [i] map
|
||||
-------------------------------
|
||||
[ a b c ...]
|
||||
|
||||
Handling Other Kinds of Join
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ``cleave`` operators and others all have pretty brutal join
|
||||
semantics: everything works and we always wait for every
|
||||
sub-computation. We can imagine a few different potentially useful
|
||||
patterns of “joining” results from parallel combinators.
|
||||
|
||||
first-to-finish
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
Thinking about variations of ``pam`` there could be one that only
|
||||
returns the first result of the first-to-finish sub-program, or the
|
||||
stack could be replaced by its output stack.
|
||||
|
||||
The other sub-programs would be cancelled.
|
||||
|
||||
“Fulminators”
|
||||
^^^^^^^^^^^^^
|
||||
|
||||
Also known as “Futures” or “Promises” (by *everybody* else. “Fulminators”
|
||||
is what I was going to call them when I was thinking about implementing
|
||||
them in Thun.)
|
||||
|
||||
The runtime could be amended to permit “thunks” representing the results
|
||||
of in-progress computations to be left on the stack and picked up by
|
||||
subsequent functions. These would themselves be able to leave behind
|
||||
more “thunks”, the values of which depend on the eventual resolution of
|
||||
the values of the previous thunks.
|
||||
|
||||
In this way you can create “chains” (and more complex shapes) out of
|
||||
normal-looking code that consist of a kind of call-graph interspersed
|
||||
with “asyncronous” … events?
|
||||
|
||||
In any case, until I can find a rigorous theory that shows that this
|
||||
sort of thing works perfectly in Joy code I’m not going to worry about
|
||||
it. (And I think the Categories can deal with it anyhow? Incremental
|
||||
evaluation, yeah?)
|
||||
|
|
@ -1,620 +0,0 @@
|
|||
Treating Trees II: ``treestep``
|
||||
===============================
|
||||
|
||||
Let’s consider a tree structure, similar to one described `“Why
|
||||
functional programming matters” by John
|
||||
Hughes <https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf>`__,
|
||||
that consists of a node value followed by zero or more child trees. (The
|
||||
asterisk is meant to indicate the `Kleene
|
||||
star <https://en.wikipedia.org/wiki/Kleene_star>`__.)
|
||||
|
||||
::
|
||||
|
||||
tree = [] | [node tree*]
|
||||
|
||||
In the spirit of ``step`` we are going to define a combinator
|
||||
``treestep`` which expects a tree and three additional items: a
|
||||
base-case function ``[B]``, and two quoted programs ``[N]`` and ``[C]``.
|
||||
|
||||
::
|
||||
|
||||
tree [B] [N] [C] treestep
|
||||
|
||||
If the current tree node is empty then just execute ``B``:
|
||||
|
||||
::
|
||||
|
||||
[] [B] [N] [C] treestep
|
||||
---------------------------
|
||||
[] B
|
||||
|
||||
Otherwise, evaluate ``N`` on the node value, ``map`` the whole function
|
||||
(abbreviated here as ``K``) over the child trees recursively, and then
|
||||
combine the result with ``C``.
|
||||
|
||||
::
|
||||
|
||||
[node tree*] [B] [N] [C] treestep
|
||||
--------------------------------------- w/ K == [B] [N] [C] treestep
|
||||
node N [tree*] [K] map C
|
||||
|
||||
(Later on we’ll experiment with making ``map`` part of ``C`` so you can
|
||||
use other combinators.)
|
||||
|
||||
Derive the recursive function.
|
||||
------------------------------
|
||||
|
||||
We can begin to derive it by finding the ``ifte`` stage that ``genrec``
|
||||
will produce.
|
||||
|
||||
::
|
||||
|
||||
K == [not] [B] [R0] [R1] genrec
|
||||
== [not] [B] [R0 [K] R1] ifte
|
||||
|
||||
So we just have to derive ``J``:
|
||||
|
||||
::
|
||||
|
||||
J == R0 [K] R1
|
||||
|
||||
The behavior of ``J`` is to accept a (non-empty) tree node and arrive at
|
||||
the desired outcome.
|
||||
|
||||
::
|
||||
|
||||
[node tree*] J
|
||||
------------------------------
|
||||
node N [tree*] [K] map C
|
||||
|
||||
So ``J`` will have some form like:
|
||||
|
||||
::
|
||||
|
||||
J == ... [N] ... [K] ... [C] ...
|
||||
|
||||
Let’s dive in. First, unquote the node and ``dip`` ``N``.
|
||||
|
||||
::
|
||||
|
||||
[node tree*] uncons [N] dip
|
||||
node [tree*] [N] dip
|
||||
node N [tree*]
|
||||
|
||||
Next, ``map`` ``K`` over the child trees and combine with ``C``.
|
||||
|
||||
::
|
||||
|
||||
node N [tree*] [K] map C
|
||||
node N [tree*] [K] map C
|
||||
node N [K.tree*] C
|
||||
|
||||
So:
|
||||
|
||||
::
|
||||
|
||||
J == uncons [N] dip [K] map C
|
||||
|
||||
Plug it in and convert to ``genrec``:
|
||||
|
||||
::
|
||||
|
||||
K == [not] [B] [J ] ifte
|
||||
== [not] [B] [uncons [N] dip [K] map C] ifte
|
||||
== [not] [B] [uncons [N] dip] [map C] genrec
|
||||
|
||||
Extract the givens to parameterize the program.
|
||||
-----------------------------------------------
|
||||
|
||||
Working backwards:
|
||||
|
||||
::
|
||||
|
||||
[not] [B] [uncons [N] dip] [map C] genrec
|
||||
[B] [not] swap [uncons [N] dip] [map C] genrec
|
||||
[B] [uncons [N] dip] [[not] swap] dip [map C] genrec
|
||||
^^^^^^^^^^^^^^^^
|
||||
[B] [[N] dip] [uncons] swoncat [[not] swap] dip [map C] genrec
|
||||
[B] [N] [dip] cons [uncons] swoncat [[not] swap] dip [map C] genrec
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Extract a couple of auxiliary definitions:
|
||||
|
||||
::
|
||||
|
||||
TS.0 == [[not] swap] dip
|
||||
TS.1 == [dip] cons [uncons] swoncat
|
||||
|
||||
::
|
||||
|
||||
[B] [N] TS.1 TS.0 [map C] genrec
|
||||
[B] [N] [map C] [TS.1 TS.0] dip genrec
|
||||
[B] [N] [C] [map] swoncat [TS.1 TS.0] dip genrec
|
||||
|
||||
The givens are all to the left so we have our definition.
|
||||
|
||||
(alternate) Extract the givens to parameterize the program.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Working backwards:
|
||||
|
||||
::
|
||||
|
||||
[not] [B] [uncons [N] dip] [map C] genrec
|
||||
[not] [B] [N] [dip] cons [uncons] swoncat [map C] genrec
|
||||
[B] [N] [not] roll> [dip] cons [uncons] swoncat [map C] genrec
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Define ``treestep``
|
||||
-------------------
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import D, J, V, define, DefinitionWrapper
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
DefinitionWrapper.add_definitions('''
|
||||
|
||||
_treestep_0 == [[not] swap] dip
|
||||
_treestep_1 == [dip] cons [uncons] swoncat
|
||||
treegrind == [_treestep_1 _treestep_0] dip genrec
|
||||
treestep == [map] swoncat treegrind
|
||||
|
||||
''', D)
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
Consider trees, the nodes of which are integers. We can find the sum of
|
||||
all nodes in a tree with this function:
|
||||
|
||||
::
|
||||
|
||||
sumtree == [pop 0] [] [sum +] treestep
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('sumtree == [pop 0] [] [sum +] treestep')
|
||||
|
||||
Running this function on an empty tree value gives zero:
|
||||
|
||||
::
|
||||
|
||||
[] [pop 0] [] [sum +] treestep
|
||||
------------------------------------
|
||||
0
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[] sumtree') # Empty tree.
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
0
|
||||
|
||||
|
||||
Running it on a non-empty node:
|
||||
|
||||
::
|
||||
|
||||
[n tree*] [pop 0] [] [sum +] treestep
|
||||
n [tree*] [[pop 0] [] [sum +] treestep] map sum +
|
||||
n [ ... ] sum +
|
||||
n m +
|
||||
n+m
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[23] sumtree') # No child trees.
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
23
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[23 []] sumtree') # Child tree, empty.
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
23
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[23 [2 [4]] [3]] sumtree') # Non-empty child trees.
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
32
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[23 [2 [8] [9]] [3] [4 []]] sumtree') # Etc...
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
49
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep') # Alternate "spelling".
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
49
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep') # Replace each node.
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[23 [23 [23] [23]] [23] [23 []]]
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1 [1 [1] [1]] [1] [1 []]]
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
6
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
6
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
3
|
||||
|
||||
|
||||
Redefining the Ordered Binary Tree in terms of ``treestep``.
|
||||
------------------------------------------------------------
|
||||
|
||||
::
|
||||
|
||||
Tree = [] | [[key value] left right]
|
||||
|
||||
What kind of functions can we write for this with our ``treestep``?
|
||||
|
||||
The pattern for processing a non-empty node is:
|
||||
|
||||
::
|
||||
|
||||
node N [tree*] [K] map C
|
||||
|
||||
Plugging in our BTree structure:
|
||||
|
||||
::
|
||||
|
||||
[key value] N [left right] [K] map C
|
||||
|
||||
Traversal
|
||||
~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
[key value] first [left right] [K] map i
|
||||
key [value] [left right] [K] map i
|
||||
key [left right] [K] map i
|
||||
key [lkey rkey ] i
|
||||
key lkey rkey
|
||||
|
||||
This doesn’t quite work:
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
3 'B' 'B'
|
||||
|
||||
|
||||
Doesn’t work because ``map`` extracts the ``first`` item of whatever its
|
||||
mapped function produces. We have to return a list, rather than
|
||||
depositing our results directly on the stack.
|
||||
|
||||
::
|
||||
|
||||
[key value] N [left right] [K] map C
|
||||
|
||||
[key value] first [left right] [K] map flatten cons
|
||||
key [left right] [K] map flatten cons
|
||||
key [[lk] [rk] ] flatten cons
|
||||
key [ lk rk ] cons
|
||||
[key lk rk ]
|
||||
|
||||
So:
|
||||
|
||||
::
|
||||
|
||||
[] [first] [flatten cons] treestep
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [first] [flatten cons] treestep')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[3 2 9 5 4 8 6 7]
|
||||
|
||||
|
||||
There we go.
|
||||
|
||||
In-order traversal
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
From here:
|
||||
|
||||
::
|
||||
|
||||
key [[lk] [rk]] C
|
||||
key [[lk] [rk]] i
|
||||
key [lk] [rk] roll<
|
||||
[lk] [rk] key swons concat
|
||||
[lk] [key rk] concat
|
||||
[lk key rk]
|
||||
|
||||
So:
|
||||
|
||||
::
|
||||
|
||||
[] [i roll< swons concat] [first] treestep
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [uncons pop] [i roll< swons concat] treestep')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[2 3 4 5 6 7 8 9]
|
||||
|
||||
|
||||
With ``treegrind``?
|
||||
-------------------
|
||||
|
||||
The ``treegrind`` function doesn’t include the ``map`` combinator, so
|
||||
the ``[C]`` function must arrange to use some combinator on the quoted
|
||||
recursive copy ``[K]``. With this function, the pattern for processing a
|
||||
non-empty node is:
|
||||
|
||||
::
|
||||
|
||||
node N [tree*] [K] C
|
||||
|
||||
Plugging in our BTree structure:
|
||||
|
||||
::
|
||||
|
||||
[key value] N [left right] [K] C
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
['key' 'value'] 'N' [['left'] ['right']] [[not] ['B'] [uncons ['N'] dip] ['C'] genrec] 'C'
|
||||
|
||||
|
||||
``treegrind`` with ``step``
|
||||
---------------------------
|
||||
|
||||
Iteration through the nodes
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] ["N"] [step] treegrind')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[3 0] 'N' [2 0] 'N' [9 0] 'N' [5 0] 'N' [4 0] 'N' [8 0] 'N' [6 0] 'N' [7 0] 'N'
|
||||
|
||||
|
||||
Sum the nodes’ keys.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] [first +] [step] treegrind')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
44
|
||||
|
||||
|
||||
Rebuild the tree using ``map`` (imitating ``treestep``.)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [[100 +] infra] [map cons] treegrind')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[[103 0] [[102 0] [] []] [[109 0] [[105 0] [[104 0] [] []] [[108 0] [[106 0] [] [[107 0] [] []]] []]] []]]
|
||||
|
||||
|
||||
Do we have the flexibility to reimplement ``Tree-get``?
|
||||
-------------------------------------------------------
|
||||
|
||||
I think we do:
|
||||
|
||||
::
|
||||
|
||||
[B] [N] [C] treegrind
|
||||
|
||||
We’ll start by saying that the base-case (the key is not in the tree) is
|
||||
user defined, and the per-node function is just the query key literal:
|
||||
|
||||
::
|
||||
|
||||
[B] [query_key] [C] treegrind
|
||||
|
||||
This means we just have to define ``C`` from:
|
||||
|
||||
::
|
||||
|
||||
[key value] query_key [left right] [K] C
|
||||
|
||||
Let’s try ``cmp``:
|
||||
|
||||
::
|
||||
|
||||
C == P [T>] [E] [T<] cmp
|
||||
|
||||
[key value] query_key [left right] [K] P [T>] [E] [T<] cmp
|
||||
|
||||
The predicate ``P``
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Seems pretty easy (we must preserve the value in case the keys are
|
||||
equal):
|
||||
|
||||
::
|
||||
|
||||
[key value] query_key [left right] [K] P
|
||||
[key value] query_key [left right] [K] roll<
|
||||
[key value] [left right] [K] query_key [roll< uncons swap] dip
|
||||
|
||||
[key value] [left right] [K] roll< uncons swap query_key
|
||||
[left right] [K] [key value] uncons swap query_key
|
||||
[left right] [K] key [value] swap query_key
|
||||
[left right] [K] [value] key query_key
|
||||
|
||||
P == roll< [roll< uncons swap] dip
|
||||
|
||||
(Possibly with a swap at the end? Or just swap ``T<`` and ``T>``.)
|
||||
|
||||
So now:
|
||||
|
||||
::
|
||||
|
||||
[left right] [K] [value] key query_key [T>] [E] [T<] cmp
|
||||
|
||||
Becomes one of these three:
|
||||
|
||||
::
|
||||
|
||||
[left right] [K] [value] T>
|
||||
[left right] [K] [value] E
|
||||
[left right] [K] [value] T<
|
||||
|
||||
``E``
|
||||
~~~~~
|
||||
|
||||
Easy.
|
||||
|
||||
::
|
||||
|
||||
E == roll> popop first
|
||||
|
||||
``T<`` and ``T>``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
T< == pop [first] dip i
|
||||
T> == pop [second] dip i
|
||||
|
||||
Putting it together
|
||||
-------------------
|
||||
|
||||
::
|
||||
|
||||
T> == pop [first] dip i
|
||||
T< == pop [second] dip i
|
||||
E == roll> popop first
|
||||
P == roll< [roll< uncons swap] dip
|
||||
|
||||
Tree-get == [P [T>] [E] [T<] cmp] treegrind
|
||||
|
||||
To me, that seems simpler than the ``genrec`` version.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
DefinitionWrapper.add_definitions('''
|
||||
|
||||
T> == pop [first] dip i
|
||||
T< == pop [second] dip i
|
||||
E == roll> popop first
|
||||
P == roll< [roll< uncons swap] dip
|
||||
|
||||
Tree-get == [P [T>] [E] [T<] cmp] treegrind
|
||||
|
||||
''', D)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('''\
|
||||
|
||||
[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
|
||||
|
||||
[] [5] Tree-get
|
||||
|
||||
''')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
15
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('''\
|
||||
|
||||
[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
|
||||
|
||||
[pop "nope"] [25] Tree-get
|
||||
|
||||
''')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
'nope'
|
||||
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
Type Checking
|
||||
=============
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
import logging, sys
|
||||
|
||||
logging.basicConfig(
|
||||
format='%(message)s',
|
||||
stream=sys.stdout,
|
||||
level=logging.INFO,
|
||||
)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from joy.utils.types import (
|
||||
doc_from_stack_effect,
|
||||
infer,
|
||||
reify,
|
||||
unify,
|
||||
FUNCTIONS,
|
||||
JoyTypeError,
|
||||
)
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
D = FUNCTIONS.copy()
|
||||
del D['product']
|
||||
globals().update(D)
|
||||
|
||||
An Example
|
||||
----------
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0]
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
25 (--) ∘ pop swap rolldown rrest ccons
|
||||
28 (a1 --) ∘ swap rolldown rrest ccons
|
||||
31 (a3 a2 a1 -- a2 a3) ∘ rolldown rrest ccons
|
||||
34 (a4 a3 a2 a1 -- a2 a3 a4) ∘ rrest ccons
|
||||
37 ([a4 a5 ...1] a3 a2 a1 -- a2 a3 [...1]) ∘ ccons
|
||||
40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
print doc_from_stack_effect(fi, fo)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from joy.parser import text_to_expression
|
||||
from joy.utils.stack import stack_to_string
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
e = text_to_expression('0 1 2 [3 4]') # reverse order
|
||||
print stack_to_string(e)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[3 4] 2 1 0
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
u = unify(e, fi)[0]
|
||||
u
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
{a1: 0, a2: 1, a3: 2, a4: 3, a5: 4, s2: (), s1: ()}
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
g = reify(u, (fi, fo))
|
||||
print doc_from_stack_effect(*g)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
(... [3 4 ] 2 1 0 -- ... [1 2 ])
|
||||
|
||||
|
||||
Unification Works “in Reverse”
|
||||
------------------------------
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
e = text_to_expression('[2 3]')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
u = unify(e, fo)[0] # output side, not input side
|
||||
u
|
||||
|
||||
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
{a2: 2, a3: 3, s2: (), s1: ()}
|
||||
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
g = reify(u, (fi, fo))
|
||||
print doc_from_stack_effect(*g)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
(... [a4 a5 ] 3 2 a1 -- ... [2 3 ])
|
||||
|
||||
|
||||
Failing a Check
|
||||
---------------
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
fi, fo = infer(dup, mul)[0]
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
25 (--) ∘ dup mul
|
||||
28 (a1 -- a1 a1) ∘ mul
|
||||
31 (f1 -- f2) ∘
|
||||
31 (i1 -- i2) ∘
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
e = text_to_expression('"two"')
|
||||
print stack_to_string(e)
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
'two'
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
try:
|
||||
unify(e, fi)
|
||||
except JoyTypeError, err:
|
||||
print err
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
Cannot unify 'two' and f1.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,352 +0,0 @@
|
|||
Traversing Datastructures with Zippers
|
||||
======================================
|
||||
|
||||
This notebook is about using the “zipper” with joy datastructures. See
|
||||
the `Zipper wikipedia
|
||||
entry <https://en.wikipedia.org/wiki/Zipper_%28data_structure%29>`__ or
|
||||
the original paper: `“FUNCTIONAL PEARL The Zipper” by Gérard
|
||||
Huet <https://www.st.cs.uni-saarland.de/edu/seminare/2005/advanced-fp/docs/huet-zipper.pdf>`__
|
||||
|
||||
Given a datastructure on the stack we can navigate through it, modify
|
||||
it, and rebuild it using the “zipper” technique.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
from notebook_preamble import J, V, define
|
||||
|
||||
Trees
|
||||
-----
|
||||
|
||||
In Joypy there aren’t any complex datastructures, just ints, floats,
|
||||
strings, Symbols (strings that are names of functions) and sequences
|
||||
(aka lists, aka quoted literals, aka aggregates, etc…), but we can build
|
||||
`trees <https://en.wikipedia.org/wiki/Tree_%28data_structure%29>`__ out
|
||||
of sequences.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1 [2 [3 4 25 6] 7] 8]')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1 [2 [3 4 25 6] 7] 8]
|
||||
|
||||
|
||||
Zipper in Joy
|
||||
-------------
|
||||
|
||||
Zippers work by keeping track of the current item, the already-seen
|
||||
items, and the yet-to-be seen items as you traverse a datastructure (the
|
||||
datastructure used to keep track of these items is the zipper.)
|
||||
|
||||
In Joy we can do this with the following words:
|
||||
|
||||
::
|
||||
|
||||
z-down == [] swap uncons swap
|
||||
z-up == swons swap shunt
|
||||
z-right == [swons] cons dip uncons swap
|
||||
z-left == swons [uncons swap] dip swap
|
||||
|
||||
Let’s use them to change 25 into 625. The first time a word is used I
|
||||
show the trace so you can see how it works. If we were going to use
|
||||
these a lot it would make sense to write Python versions for efficiency,
|
||||
but see below.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('z-down == [] swap uncons swap')
|
||||
define('z-up == swons swap shunt')
|
||||
define('z-right == [swons] cons dip uncons swap')
|
||||
define('z-left == swons [uncons swap] dip swap')
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('[1 [2 [3 4 25 6] 7] 8] z-down')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. [1 [2 [3 4 25 6] 7] 8] z-down
|
||||
[1 [2 [3 4 25 6] 7] 8] . z-down
|
||||
[1 [2 [3 4 25 6] 7] 8] . [] swap uncons swap
|
||||
[1 [2 [3 4 25 6] 7] 8] [] . swap uncons swap
|
||||
[] [1 [2 [3 4 25 6] 7] 8] . uncons swap
|
||||
[] 1 [[2 [3 4 25 6] 7] 8] . swap
|
||||
[] [[2 [3 4 25 6] 7] 8] 1 .
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('[] [[2 [3 4 25 6] 7] 8] 1 z-right')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. [] [[2 [3 4 25 6] 7] 8] 1 z-right
|
||||
[] . [[2 [3 4 25 6] 7] 8] 1 z-right
|
||||
[] [[2 [3 4 25 6] 7] 8] . 1 z-right
|
||||
[] [[2 [3 4 25 6] 7] 8] 1 . z-right
|
||||
[] [[2 [3 4 25 6] 7] 8] 1 . [swons] cons dip uncons swap
|
||||
[] [[2 [3 4 25 6] 7] 8] 1 [swons] . cons dip uncons swap
|
||||
[] [[2 [3 4 25 6] 7] 8] [1 swons] . dip uncons swap
|
||||
[] . 1 swons [[2 [3 4 25 6] 7] 8] uncons swap
|
||||
[] 1 . swons [[2 [3 4 25 6] 7] 8] uncons swap
|
||||
[] 1 . swap cons [[2 [3 4 25 6] 7] 8] uncons swap
|
||||
1 [] . cons [[2 [3 4 25 6] 7] 8] uncons swap
|
||||
[1] . [[2 [3 4 25 6] 7] 8] uncons swap
|
||||
[1] [[2 [3 4 25 6] 7] 8] . uncons swap
|
||||
[1] [2 [3 4 25 6] 7] [8] . swap
|
||||
[1] [8] [2 [3 4 25 6] 7] .
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1] [8] [2 [3 4 25 6] 7] z-down')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1] [8] [] [[3 4 25 6] 7] 2
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1] [8] [] [[3 4 25 6] 7] 2 z-right')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1] [8] [2] [7] [3 4 25 6]
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1] [8] [2] [7] [3 4 25 6] z-down')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1] [8] [2] [7] [] [4 25 6] 3
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1] [8] [2] [7] [] [4 25 6] 3 z-right')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1] [8] [2] [7] [3] [25 6] 4
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1] [8] [2] [7] [3] [25 6] 4 z-right')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1] [8] [2] [7] [4 3] [6] 25
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1] [8] [2] [7] [4 3] [6] 25 sqr')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1] [8] [2] [7] [4 3] [6] 625
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('[1] [8] [2] [7] [4 3] [6] 625 z-up')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. [1] [8] [2] [7] [4 3] [6] 625 z-up
|
||||
[1] . [8] [2] [7] [4 3] [6] 625 z-up
|
||||
[1] [8] . [2] [7] [4 3] [6] 625 z-up
|
||||
[1] [8] [2] . [7] [4 3] [6] 625 z-up
|
||||
[1] [8] [2] [7] . [4 3] [6] 625 z-up
|
||||
[1] [8] [2] [7] [4 3] . [6] 625 z-up
|
||||
[1] [8] [2] [7] [4 3] [6] . 625 z-up
|
||||
[1] [8] [2] [7] [4 3] [6] 625 . z-up
|
||||
[1] [8] [2] [7] [4 3] [6] 625 . swons swap shunt
|
||||
[1] [8] [2] [7] [4 3] [6] 625 . swap cons swap shunt
|
||||
[1] [8] [2] [7] [4 3] 625 [6] . cons swap shunt
|
||||
[1] [8] [2] [7] [4 3] [625 6] . swap shunt
|
||||
[1] [8] [2] [7] [625 6] [4 3] . shunt
|
||||
[1] [8] [2] [7] [3 4 625 6] .
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1] [8] [2] [7] [3 4 625 6] z-up')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1] [8] [2 [3 4 625 6] 7]
|
||||
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1] [8] [2 [3 4 625 6] 7] z-up')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1 [2 [3 4 625 6] 7] 8]
|
||||
|
||||
|
||||
``dip`` and ``infra``
|
||||
---------------------
|
||||
|
||||
In Joy we have the ``dip`` and ``infra`` combinators which can “target”
|
||||
or “address” any particular item in a Joy tree structure.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('[1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. [1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] infra
|
||||
[1 [2 [3 4 25 6] 7] 8] . [[[[[[sqr] dipd] infra] dip] infra] dip] infra
|
||||
[1 [2 [3 4 25 6] 7] 8] [[[[[[sqr] dipd] infra] dip] infra] dip] . infra
|
||||
8 [2 [3 4 25 6] 7] 1 . [[[[[sqr] dipd] infra] dip] infra] dip [] swaack
|
||||
8 [2 [3 4 25 6] 7] 1 [[[[[sqr] dipd] infra] dip] infra] . dip [] swaack
|
||||
8 [2 [3 4 25 6] 7] . [[[[sqr] dipd] infra] dip] infra 1 [] swaack
|
||||
8 [2 [3 4 25 6] 7] [[[[sqr] dipd] infra] dip] . infra 1 [] swaack
|
||||
7 [3 4 25 6] 2 . [[[sqr] dipd] infra] dip [8] swaack 1 [] swaack
|
||||
7 [3 4 25 6] 2 [[[sqr] dipd] infra] . dip [8] swaack 1 [] swaack
|
||||
7 [3 4 25 6] . [[sqr] dipd] infra 2 [8] swaack 1 [] swaack
|
||||
7 [3 4 25 6] [[sqr] dipd] . infra 2 [8] swaack 1 [] swaack
|
||||
6 25 4 3 . [sqr] dipd [7] swaack 2 [8] swaack 1 [] swaack
|
||||
6 25 4 3 [sqr] . dipd [7] swaack 2 [8] swaack 1 [] swaack
|
||||
6 25 . sqr 4 3 [7] swaack 2 [8] swaack 1 [] swaack
|
||||
6 25 . dup mul 4 3 [7] swaack 2 [8] swaack 1 [] swaack
|
||||
6 25 25 . mul 4 3 [7] swaack 2 [8] swaack 1 [] swaack
|
||||
6 625 . 4 3 [7] swaack 2 [8] swaack 1 [] swaack
|
||||
6 625 4 . 3 [7] swaack 2 [8] swaack 1 [] swaack
|
||||
6 625 4 3 . [7] swaack 2 [8] swaack 1 [] swaack
|
||||
6 625 4 3 [7] . swaack 2 [8] swaack 1 [] swaack
|
||||
7 [3 4 625 6] . 2 [8] swaack 1 [] swaack
|
||||
7 [3 4 625 6] 2 . [8] swaack 1 [] swaack
|
||||
7 [3 4 625 6] 2 [8] . swaack 1 [] swaack
|
||||
8 [2 [3 4 625 6] 7] . 1 [] swaack
|
||||
8 [2 [3 4 625 6] 7] 1 . [] swaack
|
||||
8 [2 [3 4 625 6] 7] 1 [] . swaack
|
||||
[1 [2 [3 4 625 6] 7] 8] .
|
||||
|
||||
|
||||
If you read the trace carefully you’ll see that about half of it is the
|
||||
``dip`` and ``infra`` combinators de-quoting programs and “digging” into
|
||||
the subject datastructure. Instead of maintaining temporary results on
|
||||
the stack they are pushed into the pending expression (continuation).
|
||||
When ``sqr`` has run the rest of the pending expression rebuilds the
|
||||
datastructure.
|
||||
|
||||
``Z``
|
||||
-----
|
||||
|
||||
Imagine a function ``Z`` that accepts a sequence of ``dip`` and
|
||||
``infra`` combinators, a quoted program ``[Q]``, and a datastructure to
|
||||
work on. It would effectively execute the quoted program as if it had
|
||||
been embedded in a nested series of quoted programs, e.g.:
|
||||
|
||||
::
|
||||
|
||||
[...] [Q] [dip dip infra dip infra dip infra] Z
|
||||
-------------------------------------------------------------
|
||||
[...] [[[[[[[Q] dip] dip] infra] dip] infra] dip] infra
|
||||
|
||||
|
||||
The ``Z`` function isn’t hard to make.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
define('Z == [[] cons cons] step i')
|
||||
|
||||
Here it is in action in a simplified scenario.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
V('1 [2 3 4] Z')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
. 1 [2 3 4] Z
|
||||
1 . [2 3 4] Z
|
||||
1 [2 3 4] . Z
|
||||
1 [2 3 4] . [[] cons cons] step i
|
||||
1 [2 3 4] [[] cons cons] . step i
|
||||
1 2 [[] cons cons] . i [3 4] [[] cons cons] step i
|
||||
1 2 . [] cons cons [3 4] [[] cons cons] step i
|
||||
1 2 [] . cons cons [3 4] [[] cons cons] step i
|
||||
1 [2] . cons [3 4] [[] cons cons] step i
|
||||
[1 2] . [3 4] [[] cons cons] step i
|
||||
[1 2] [3 4] . [[] cons cons] step i
|
||||
[1 2] [3 4] [[] cons cons] . step i
|
||||
[1 2] 3 [[] cons cons] . i [4] [[] cons cons] step i
|
||||
[1 2] 3 . [] cons cons [4] [[] cons cons] step i
|
||||
[1 2] 3 [] . cons cons [4] [[] cons cons] step i
|
||||
[1 2] [3] . cons [4] [[] cons cons] step i
|
||||
[[1 2] 3] . [4] [[] cons cons] step i
|
||||
[[1 2] 3] [4] . [[] cons cons] step i
|
||||
[[1 2] 3] [4] [[] cons cons] . step i
|
||||
[[1 2] 3] 4 [[] cons cons] . i i
|
||||
[[1 2] 3] 4 . [] cons cons i
|
||||
[[1 2] 3] 4 [] . cons cons i
|
||||
[[1 2] 3] [4] . cons i
|
||||
[[[1 2] 3] 4] . i
|
||||
. [[1 2] 3] 4
|
||||
[[1 2] 3] . 4
|
||||
[[1 2] 3] 4 .
|
||||
|
||||
|
||||
And here it is doing the main thing.
|
||||
|
||||
.. code:: ipython2
|
||||
|
||||
J('[1 [2 [3 4 25 6] 7] 8] [sqr] [dip dip infra dip infra dip infra] Z')
|
||||
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
[1 [2 [3 4 625 6] 7] 8]
|
||||
|
||||
|
||||
Addressing
|
||||
----------
|
||||
|
||||
Because we are only using two combinators we could replace the list with
|
||||
a string made from only two characters.
|
||||
|
||||
::
|
||||
|
||||
[...] [Q] 'ddididi' Zstr
|
||||
-------------------------------------------------------------
|
||||
[...] [[[[[[[Q] dip] dip] infra] dip] infra] dip] infra
|
||||
|
||||
The string can be considered a name or address for an item in the
|
||||
subject datastructure.
|
||||
|
||||
Determining the right “path” for an item in a tree.
|
||||
---------------------------------------------------
|
||||
|
||||
It’s easy to read off (in reverse) the right sequence of “d” and “i”
|
||||
from the subject datastructure:
|
||||
|
||||
::
|
||||
|
||||
[ n [ n [ n n x ...
|
||||
i d i d i d d Bingo!
|
||||
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
|
||||
Essays about Programming in Joy
|
||||
===============================
|
||||
|
||||
These essays are adapted from Jupyter notebooks. I hope to have those hosted somewhere where people can view them "live" and interact with them, possibly on MS Azure. For now, Sphinx does such a great job rendering the HTML that I am copying over some notebooks in ReST format and hand-editing them into these documents.
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:maxdepth: 2
|
||||
|
||||
Developing
|
||||
Quadratic
|
||||
Replacing
|
||||
Recursion_Combinators
|
||||
Ordered_Binary_Trees
|
||||
Treestep
|
||||
Generator_Programs
|
||||
Newton-Raphson
|
||||
Square_Spiral
|
||||
Zipper
|
||||
Types
|
||||
TypeChecking
|
||||
NoUpdates
|
||||
Categorical
|
||||
The_Four_Operations
|
||||
Derivatives_of_Regular_Expressions
|
||||
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
|
||||
Parsing Text into Joy Expressions
|
||||
=================================
|
||||
|
||||
TODO: example...
|
||||
|
||||
|
||||
``joy.parser``
|
||||
---------------
|
||||
|
||||
|
||||
.. automodule:: joy.parser
|
||||
:members:
|
||||
|
||||
|
||||
Parser Internals
|
||||
----------------
|
||||
|
||||
TODO: Document things like the regular expressions used for tokenizing, and the re.Scanner, etc...
|
||||
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
Tracing Joy Execution
|
||||
=====================
|
||||
|
||||
|
||||
``joy.utils.pretty_print``
|
||||
--------------------------
|
||||
|
||||
|
||||
.. automodule:: joy.utils.pretty_print
|
||||
:members:
|
||||
|
||||
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
|
||||
Stack or Quote or Sequence or List...
|
||||
=====================================
|
||||
|
||||
|
||||
``joy.utils.stack``
|
||||
----------------------
|
||||
|
||||
|
||||
.. automodule:: joy.utils.stack
|
||||
:members:
|
||||
|
||||
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
|
||||
Type Inference of Joy Expressions
|
||||
=================================
|
||||
|
||||
UPDATE: May 2020 - I removed the type inference code in `joy.utils.types`
|
||||
but you can find it in the `v0.4.0` tag here:
|
||||
https://osdn.net/projects/joypy/scm/hg/Joypy/tags
|
||||
|
||||
|
||||
Two kinds of type inference are provided, a simple inferencer that can
|
||||
handle functions that have a single stack effect (aka "type signature")
|
||||
and that can generate Python code for a limited subset of those
|
||||
functions, and a more complex inferencer/interpreter hybrid that can
|
||||
infer the stack effects of most Joy expressions, including multiple stack
|
||||
effects, unbounded sequences of values, and combinators (if enough
|
||||
information is available.)
|
||||
|
||||
|
||||
``joy.utils.types``
|
||||
-------------------
|
||||
|
||||
|
||||
Curently (asterix after name indicates a function that can be
|
||||
auto-compiled to Python)::
|
||||
|
||||
_Tree_add_Ee = ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) *
|
||||
_Tree_delete_R0 = ([a2 ...1] a1 -- [a2 ...1] a2 a1 a1) *
|
||||
_Tree_delete_clear_stuff = (a3 a2 [a1 ...1] -- [...1]) *
|
||||
_Tree_get_E = ([a3 a4 ...1] a2 a1 -- a4) *
|
||||
add = (n1 n2 -- n3)
|
||||
and = (b1 b2 -- b3)
|
||||
bool = (a1 -- b1)
|
||||
ccons = (a2 a1 [...1] -- [a2 a1 ...1]) *
|
||||
cons = (a1 [...0] -- [a1 ...0]) *
|
||||
div = (n1 n2 -- n3)
|
||||
divmod = (n2 n1 -- n4 n3)
|
||||
dup = (a1 -- a1 a1) *
|
||||
dupd = (a2 a1 -- a2 a2 a1) *
|
||||
dupdd = (a3 a2 a1 -- a3 a3 a2 a1) *
|
||||
eq = (n1 n2 -- b1)
|
||||
first = ([a1 ...1] -- a1) *
|
||||
first_two = ([a1 a2 ...1] -- a1 a2) *
|
||||
floordiv = (n1 n2 -- n3)
|
||||
fourth = ([a1 a2 a3 a4 ...1] -- a4) *
|
||||
ge = (n1 n2 -- b1)
|
||||
gt = (n1 n2 -- b1)
|
||||
le = (n1 n2 -- b1)
|
||||
lshift = (n1 n2 -- n3)
|
||||
lt = (n1 n2 -- b1)
|
||||
modulus = (n1 n2 -- n3)
|
||||
mul = (n1 n2 -- n3)
|
||||
ne = (n1 n2 -- b1)
|
||||
neg = (n1 -- n2)
|
||||
not = (a1 -- b1)
|
||||
over = (a2 a1 -- a2 a1 a2) *
|
||||
pm = (n2 n1 -- n4 n3)
|
||||
pop = (a1 --) *
|
||||
popd = (a2 a1 -- a1) *
|
||||
popdd = (a3 a2 a1 -- a2 a1) *
|
||||
popop = (a2 a1 --) *
|
||||
popopd = (a3 a2 a1 -- a1) *
|
||||
popopdd = (a4 a3 a2 a1 -- a2 a1) *
|
||||
pow = (n1 n2 -- n3)
|
||||
pred = (n1 -- n2)
|
||||
rest = ([a1 ...0] -- [...0]) *
|
||||
rolldown = (a1 a2 a3 -- a2 a3 a1) *
|
||||
rollup = (a1 a2 a3 -- a3 a1 a2) *
|
||||
rrest = ([a1 a2 ...1] -- [...1]) *
|
||||
rshift = (n1 n2 -- n3)
|
||||
second = ([a1 a2 ...1] -- a2) *
|
||||
sqrt = (n1 -- n2)
|
||||
stack = (... -- ... [...]) *
|
||||
stuncons = (... a1 -- ... a1 a1 [...]) *
|
||||
stununcons = (... a2 a1 -- ... a2 a1 a1 a2 [...]) *
|
||||
sub = (n1 n2 -- n3)
|
||||
succ = (n1 -- n2)
|
||||
swaack = ([...1] -- [...0]) *
|
||||
swap = (a1 a2 -- a2 a1) *
|
||||
swons = ([...1] a1 -- [a1 ...1]) *
|
||||
third = ([a1 a2 a3 ...1] -- a3) *
|
||||
truediv = (n1 n2 -- n3)
|
||||
tuck = (a2 a1 -- a1 a2 a1) *
|
||||
uncons = ([a1 ...0] -- a1 [...0]) *
|
||||
unit = (a1 -- [a1 ]) *
|
||||
unswons = ([a1 ...1] -- [...1] a1) *
|
||||
|
||||
|
||||
Example output of the ``infer()`` function. The first number on each
|
||||
line is the depth of the Python stack. It goes down when the function
|
||||
backtracks. The next thing on each line is the currently-computed stack
|
||||
effect so far. It starts with the empty "identity function" and proceeds
|
||||
through the expression, which is the rest of each line. The function
|
||||
acts like an interpreter but instead of executing the terms of the
|
||||
expression it composes them, but for combinators it *does* execute them,
|
||||
using the output side of the stack effect as the stack. This seems to
|
||||
work fine. With proper definitions for the behavior of the combinators
|
||||
that can have more than one effect (like ``branch`` or ``loop``) the
|
||||
``infer()`` function seems to be able to handle anything I throw at it so
|
||||
far.
|
||||
|
||||
::
|
||||
|
||||
7 (--) ∘ pop swap rolldown rest rest cons cons
|
||||
10 (a1 --) ∘ swap rolldown rest rest cons cons
|
||||
13 (a3 a2 a1 -- a2 a3) ∘ rolldown rest rest cons cons
|
||||
16 (a4 a3 a2 a1 -- a2 a3 a4) ∘ rest rest cons cons
|
||||
19 ([a4 ...1] a3 a2 a1 -- a2 a3 [...1]) ∘ rest cons cons
|
||||
22 ([a4 a5 ...1] a3 a2 a1 -- a2 a3 [...1]) ∘ cons cons
|
||||
25 ([a4 a5 ...1] a3 a2 a1 -- a2 [a3 ...1]) ∘ cons
|
||||
28 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘
|
||||
----------------------------------------
|
||||
([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1])
|
||||
|
||||
|
||||
Here's another example (implementing ``ifte``) using some combinators::
|
||||
|
||||
7 (--) ∘ [pred] [mul] [div] [nullary bool] dipd branch
|
||||
8 (-- [pred ...2]) ∘ [mul] [div] [nullary bool] dipd branch
|
||||
9 (-- [pred ...2] [mul ...3]) ∘ [div] [nullary bool] dipd branch
|
||||
10 (-- [pred ...2] [mul ...3] [div ...4]) ∘ [nullary bool] dipd branch
|
||||
11 (-- [pred ...2] [mul ...3] [div ...4] [nullary bool ...5]) ∘ dipd branch
|
||||
15 (-- [pred ...5]) ∘ nullary bool [mul] [div] branch
|
||||
19 (-- [pred ...2]) ∘ [stack] dinfrirst bool [mul] [div] branch
|
||||
20 (-- [pred ...2] [stack ]) ∘ dinfrirst bool [mul] [div] branch
|
||||
22 (-- [pred ...2] [stack ]) ∘ dip infra first bool [mul] [div] branch
|
||||
26 (--) ∘ stack [pred] infra first bool [mul] [div] branch
|
||||
29 (... -- ... [...]) ∘ [pred] infra first bool [mul] [div] branch
|
||||
30 (... -- ... [...] [pred ...1]) ∘ infra first bool [mul] [div] branch
|
||||
34 (--) ∘ pred s1 swaack first bool [mul] [div] branch
|
||||
37 (n1 -- n2) ∘ [n1] swaack first bool [mul] [div] branch
|
||||
38 (... n1 -- ... n2 [n1 ...]) ∘ swaack first bool [mul] [div] branch
|
||||
41 (... n1 -- ... n1 [n2 ...]) ∘ first bool [mul] [div] branch
|
||||
44 (n1 -- n1 n2) ∘ bool [mul] [div] branch
|
||||
47 (n1 -- n1 b1) ∘ [mul] [div] branch
|
||||
48 (n1 -- n1 b1 [mul ...1]) ∘ [div] branch
|
||||
49 (n1 -- n1 b1 [mul ...1] [div ...2]) ∘ branch
|
||||
53 (n1 -- n1) ∘ div
|
||||
56 (f2 f1 -- f3) ∘
|
||||
56 (i1 f1 -- f2) ∘
|
||||
56 (f1 i1 -- f2) ∘
|
||||
56 (i2 i1 -- f1) ∘
|
||||
53 (n1 -- n1) ∘ mul
|
||||
56 (f2 f1 -- f3) ∘
|
||||
56 (i1 f1 -- f2) ∘
|
||||
56 (f1 i1 -- f2) ∘
|
||||
56 (i2 i1 -- i3) ∘
|
||||
----------------------------------------
|
||||
(f2 f1 -- f3)
|
||||
(i1 f1 -- f2)
|
||||
(f1 i1 -- f2)
|
||||
(i2 i1 -- f1)
|
||||
(i2 i1 -- i3)
|
||||
|
||||
|
|
@ -1,701 +0,0 @@
|
|||
@import url("basic.css");
|
||||
|
||||
/* -- page layout ----------------------------------------------------------- */
|
||||
|
||||
body {
|
||||
font-family: Georgia, serif;
|
||||
font-size: 17px;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
div.document {
|
||||
width: 940px;
|
||||
margin: 30px auto 0 auto;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: left;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0 0 0 220px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
width: 220px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 1px solid #B1B4B6;
|
||||
}
|
||||
|
||||
div.body {
|
||||
background-color: #fff;
|
||||
color: #3E4349;
|
||||
padding: 0 30px 0 30px;
|
||||
}
|
||||
|
||||
div.body > .section {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
width: 940px;
|
||||
margin: 20px auto 30px auto;
|
||||
font-size: 14px;
|
||||
color: #888;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.footer a {
|
||||
color: #888;
|
||||
}
|
||||
|
||||
p.caption {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
|
||||
div.relations {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #444;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted #999;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a:hover {
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 18px 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper p.logo {
|
||||
padding: 0;
|
||||
margin: -10px 0 0 0px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper h1.logo {
|
||||
margin-top: -10px;
|
||||
text-align: center;
|
||||
margin-bottom: 5px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper h1.logo-name {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
div.sphinxsidebarwrapper p.blurb {
|
||||
margin-top: 0;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3,
|
||||
div.sphinxsidebar h4 {
|
||||
font-family: Georgia, serif;
|
||||
color: #444;
|
||||
font-size: 24px;
|
||||
font-weight: normal;
|
||||
margin: 0 0 5px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h4 {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.logo a,
|
||||
div.sphinxsidebar h3 a,
|
||||
div.sphinxsidebar p.logo a:hover,
|
||||
div.sphinxsidebar h3 a:hover {
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p {
|
||||
color: #555;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
margin: 10px 0;
|
||||
padding: 0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul li.toctree-l1 > a {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul li.toctree-l2 > a {
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #CCC;
|
||||
font-family: Georgia, serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar hr {
|
||||
border: none;
|
||||
height: 1px;
|
||||
color: #AAA;
|
||||
background: #AAA;
|
||||
|
||||
text-align: left;
|
||||
margin-left: 0;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar .badge {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar .badge:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
/* To address an issue with donation coming after search */
|
||||
div.sphinxsidebar h3.donation {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- body styles ----------------------------------------------------------- */
|
||||
|
||||
a {
|
||||
color: #004B6B;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: #6D4100;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
div.body h1,
|
||||
div.body h2,
|
||||
div.body h3,
|
||||
div.body h4,
|
||||
div.body h5,
|
||||
div.body h6 {
|
||||
font-family: Georgia, serif;
|
||||
font-weight: normal;
|
||||
margin: 30px 0px 10px 0px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; }
|
||||
div.body h2 { font-size: 180%; }
|
||||
div.body h3 { font-size: 150%; }
|
||||
div.body h4 { font-size: 130%; }
|
||||
div.body h5 { font-size: 100%; }
|
||||
div.body h6 { font-size: 100%; }
|
||||
|
||||
a.headerlink {
|
||||
color: #DDD;
|
||||
padding: 0 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a.headerlink:hover {
|
||||
color: #444;
|
||||
background: #EAEAEA;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li {
|
||||
line-height: 1.4em;
|
||||
}
|
||||
|
||||
div.admonition {
|
||||
margin: 20px 0px;
|
||||
padding: 10px 30px;
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.admonition tt.xref, div.admonition code.xref, div.admonition a tt {
|
||||
background-color: #FBFBFB;
|
||||
border-bottom: 1px solid #fafafa;
|
||||
}
|
||||
|
||||
div.admonition p.admonition-title {
|
||||
font-family: Georgia, serif;
|
||||
font-weight: normal;
|
||||
font-size: 24px;
|
||||
margin: 0 0 10px 0;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
div.admonition p.last {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.highlight {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
dt:target, .highlight {
|
||||
background: #FAF3E8;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
}
|
||||
|
||||
div.danger {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
-moz-box-shadow: 2px 2px 4px #D52C2C;
|
||||
-webkit-box-shadow: 2px 2px 4px #D52C2C;
|
||||
box-shadow: 2px 2px 4px #D52C2C;
|
||||
}
|
||||
|
||||
div.error {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
-moz-box-shadow: 2px 2px 4px #D52C2C;
|
||||
-webkit-box-shadow: 2px 2px 4px #D52C2C;
|
||||
box-shadow: 2px 2px 4px #D52C2C;
|
||||
}
|
||||
|
||||
div.caution {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
}
|
||||
|
||||
div.attention {
|
||||
background-color: #FCC;
|
||||
border: 1px solid #FAA;
|
||||
}
|
||||
|
||||
div.important {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.note {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.tip {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.hint {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.seealso {
|
||||
background-color: #EEE;
|
||||
border: 1px solid #CCC;
|
||||
}
|
||||
|
||||
div.topic {
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p.admonition-title:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
pre, tt, code {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.hll {
|
||||
background-color: #FFC;
|
||||
margin: 0 -12px;
|
||||
padding: 0 12px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
}
|
||||
|
||||
tt.descname, tt.descclassname, code.descname, code.descclassname {
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
tt.descname, code.descname {
|
||||
padding-right: 0.08em;
|
||||
}
|
||||
|
||||
img.screenshot {
|
||||
-moz-box-shadow: 2px 2px 4px #EEE;
|
||||
-webkit-box-shadow: 2px 2px 4px #EEE;
|
||||
box-shadow: 2px 2px 4px #EEE;
|
||||
}
|
||||
|
||||
table.docutils {
|
||||
border: 1px solid #888;
|
||||
-moz-box-shadow: 2px 2px 4px #EEE;
|
||||
-webkit-box-shadow: 2px 2px 4px #EEE;
|
||||
box-shadow: 2px 2px 4px #EEE;
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
border: 1px solid #888;
|
||||
padding: 0.25em 0.7em;
|
||||
}
|
||||
|
||||
table.field-list, table.footnote {
|
||||
border: none;
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
table.footnote {
|
||||
margin: 15px 0;
|
||||
width: 100%;
|
||||
border: 1px solid #EEE;
|
||||
background: #FDFDFD;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
table.footnote + table.footnote {
|
||||
margin-top: -15px;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
table.field-list th {
|
||||
padding: 0 0.8em 0 0;
|
||||
}
|
||||
|
||||
table.field-list td {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.field-list p {
|
||||
margin-bottom: 0.8em;
|
||||
}
|
||||
|
||||
/* Cloned from
|
||||
* https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68
|
||||
*/
|
||||
.field-name {
|
||||
-moz-hyphens: manual;
|
||||
-ms-hyphens: manual;
|
||||
-webkit-hyphens: manual;
|
||||
hyphens: manual;
|
||||
}
|
||||
|
||||
table.footnote td.label {
|
||||
width: .1px;
|
||||
padding: 0.3em 0 0.3em 0.5em;
|
||||
}
|
||||
|
||||
table.footnote td {
|
||||
padding: 0.3em 0.5em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
dl dd {
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 0 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
/* Matches the 30px from the narrow-screen "li > ul" selector below */
|
||||
margin: 10px 0 10px 30px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: #EEE;
|
||||
padding: 7px 30px;
|
||||
margin: 15px 0px;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
background: #ffd;
|
||||
}
|
||||
|
||||
dl pre, blockquote pre, li pre {
|
||||
margin-left: 0;
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
tt, code {
|
||||
background-color: #ecf0f3;
|
||||
color: #222;
|
||||
/* padding: 1px 2px; */
|
||||
}
|
||||
|
||||
tt.xref, code.xref, a tt {
|
||||
background-color: #FBFBFB;
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
a.reference {
|
||||
text-decoration: none;
|
||||
border-bottom: 1px dotted #004B6B;
|
||||
}
|
||||
|
||||
/* Don't put an underline on images */
|
||||
a.image-reference, a.image-reference:hover {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
a.reference:hover {
|
||||
border-bottom: 1px solid #6D4100;
|
||||
}
|
||||
|
||||
a.footnote-reference {
|
||||
text-decoration: none;
|
||||
font-size: 0.7em;
|
||||
vertical-align: top;
|
||||
border-bottom: 1px dotted #004B6B;
|
||||
}
|
||||
|
||||
a.footnote-reference:hover {
|
||||
border-bottom: 1px solid #6D4100;
|
||||
}
|
||||
|
||||
a:hover tt, a:hover code {
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 870px) {
|
||||
|
||||
div.sphinxsidebar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: 100%;
|
||||
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
li > ul {
|
||||
/* Matches the 30px from the "ul, ol" selector above */
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
.document {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.bodywrapper {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.github {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 875px) {
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px 30px;
|
||||
}
|
||||
|
||||
div.documentwrapper {
|
||||
float: none;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
display: block;
|
||||
float: none;
|
||||
width: 102.5%;
|
||||
margin: 50px -30px -20px -30px;
|
||||
padding: 10px 20px;
|
||||
background: #333;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p,
|
||||
div.sphinxsidebar h3 a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
div.sphinxsidebar a {
|
||||
color: #AAA;
|
||||
}
|
||||
|
||||
div.sphinxsidebar p.logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.document {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.bodywrapper {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.body {
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.rtd_doc_footer {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.document {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.footer {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.github {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* misc. */
|
||||
|
||||
.revsys-inline {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
/* Make nested-list/multi-paragraph items look better in Releases changelog
|
||||
* pages. Without this, docutils' magical list fuckery causes inconsistent
|
||||
* formatting between different release sub-lists.
|
||||
*/
|
||||
div#changelog > div.section > ul > li > p:only-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Hide fugly table cell borders in ..bibliography:: directive output */
|
||||
table.docutils.citation, table.docutils.citation td, table.docutils.citation th {
|
||||
border: none;
|
||||
/* Below needed in some edge cases; if not applied, bottom shadows appear */
|
||||
-moz-box-shadow: none;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
|
||||
/* relbar */
|
||||
|
||||
.related {
|
||||
line-height: 30px;
|
||||
width: 100%;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.related.top {
|
||||
border-bottom: 1px solid #EEE;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.related.bottom {
|
||||
border-top: 1px solid #EEE;
|
||||
}
|
||||
|
||||
.related ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
nav#rellinks {
|
||||
float: right;
|
||||
}
|
||||
|
||||
nav#rellinks li+li:before {
|
||||
content: "|";
|
||||
}
|
||||
|
||||
nav#breadcrumbs li+li:before {
|
||||
content: "\00BB";
|
||||
}
|
||||
|
||||
/* Hide certain items when printing */
|
||||
@media print {
|
||||
div.related {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,909 +0,0 @@
|
|||
/*
|
||||
* basic.css
|
||||
* ~~~~~~~~~
|
||||
*
|
||||
* Sphinx stylesheet -- basic theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/* -- main layout ----------------------------------------------------------- */
|
||||
|
||||
div.clearer {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.section::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- relbar ---------------------------------------------------------------- */
|
||||
|
||||
div.related {
|
||||
width: 100%;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
div.related h3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.related ul {
|
||||
margin: 0;
|
||||
padding: 0 0 0 10px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.related li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
div.related li.right {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
/* -- sidebar --------------------------------------------------------------- */
|
||||
|
||||
div.sphinxsidebarwrapper {
|
||||
padding: 10px 5px 0 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar {
|
||||
float: left;
|
||||
width: 230px;
|
||||
margin-left: -100%;
|
||||
font-size: 90%;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap : break-word;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
div.sphinxsidebar li {
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul,
|
||||
div.sphinxsidebar ul.want-points {
|
||||
margin-left: 20px;
|
||||
list-style: square;
|
||||
}
|
||||
|
||||
div.sphinxsidebar ul ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sphinxsidebar form {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #98dbcc;
|
||||
font-family: sans-serif;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox form.search {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="text"] {
|
||||
float: left;
|
||||
width: 80%;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||
float: left;
|
||||
width: 20%;
|
||||
border-left: none;
|
||||
padding: 0.25em;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* -- search page ----------------------------------------------------------- */
|
||||
|
||||
ul.search {
|
||||
margin: 10px 0 0 20px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
ul.search li {
|
||||
padding: 5px 0 5px 20px;
|
||||
background-image: url(file.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0 7px;
|
||||
}
|
||||
|
||||
ul.search li a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul.search li p.context {
|
||||
color: #888;
|
||||
margin: 2px 0 0 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
ul.keywordmatches li.goodmatch a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* -- index page ------------------------------------------------------------ */
|
||||
|
||||
table.contentstable {
|
||||
width: 90%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.contentstable p.biglink {
|
||||
line-height: 150%;
|
||||
}
|
||||
|
||||
a.biglink {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
span.linkdescr {
|
||||
font-style: italic;
|
||||
padding-top: 5px;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
/* -- general index --------------------------------------------------------- */
|
||||
|
||||
table.indextable {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.indextable td {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.indextable ul {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
table.indextable > tbody > tr > td > ul {
|
||||
padding-left: 0em;
|
||||
}
|
||||
|
||||
table.indextable tr.pcap {
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
table.indextable tr.cap {
|
||||
margin-top: 10px;
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
|
||||
img.toggler {
|
||||
margin-right: 3px;
|
||||
margin-top: 3px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.modindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
div.genindex-jumpbox {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 1em 0 1em 0;
|
||||
padding: 0.4em;
|
||||
}
|
||||
|
||||
/* -- domain module index --------------------------------------------------- */
|
||||
|
||||
table.modindextable td {
|
||||
padding: 2px;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
/* -- general body styles --------------------------------------------------- */
|
||||
|
||||
div.body {
|
||||
min-width: 450px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
div.body p, div.body dd, div.body li, div.body blockquote {
|
||||
-moz-hyphens: auto;
|
||||
-ms-hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
a.headerlink {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
a.brackets:before,
|
||||
span.brackets > a:before{
|
||||
content: "[";
|
||||
}
|
||||
|
||||
a.brackets:after,
|
||||
span.brackets > a:after {
|
||||
content: "]";
|
||||
}
|
||||
|
||||
h1:hover > a.headerlink,
|
||||
h2:hover > a.headerlink,
|
||||
h3:hover > a.headerlink,
|
||||
h4:hover > a.headerlink,
|
||||
h5:hover > a.headerlink,
|
||||
h6:hover > a.headerlink,
|
||||
dt:hover > a.headerlink,
|
||||
caption:hover > a.headerlink,
|
||||
p.caption:hover > a.headerlink,
|
||||
div.code-block-caption:hover > a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
div.body p.caption {
|
||||
text-align: inherit;
|
||||
}
|
||||
|
||||
div.body td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.first {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
p.rubric {
|
||||
margin-top: 30px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
img.align-left, figure.align-left, .figure.align-left, object.align-left {
|
||||
clear: left;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
img.align-right, figure.align-right, .figure.align-right, object.align-right {
|
||||
clear: right;
|
||||
float: right;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
img.align-center, figure.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
img.align-default, figure.align-default, .figure.align-default {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-default {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* -- sidebars -------------------------------------------------------------- */
|
||||
|
||||
div.sidebar,
|
||||
aside.sidebar {
|
||||
margin: 0 0 0.5em 1em;
|
||||
border: 1px solid #ddb;
|
||||
padding: 7px;
|
||||
background-color: #ffe;
|
||||
width: 40%;
|
||||
float: right;
|
||||
clear: right;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
p.sidebar-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.admonition, div.topic, blockquote {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
/* -- topics ---------------------------------------------------------------- */
|
||||
|
||||
div.topic {
|
||||
border: 1px solid #ccc;
|
||||
padding: 7px;
|
||||
margin: 10px 0 10px 0;
|
||||
}
|
||||
|
||||
p.topic-title {
|
||||
font-size: 1.1em;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* -- admonitions ----------------------------------------------------------- */
|
||||
|
||||
div.admonition {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
div.admonition dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p.admonition-title {
|
||||
margin: 0px 10px 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.body p.centered {
|
||||
text-align: center;
|
||||
margin-top: 25px;
|
||||
}
|
||||
|
||||
/* -- content of sidebars/topics/admonitions -------------------------------- */
|
||||
|
||||
div.sidebar > :last-child,
|
||||
aside.sidebar > :last-child,
|
||||
div.topic > :last-child,
|
||||
div.admonition > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.sidebar::after,
|
||||
aside.sidebar::after,
|
||||
div.topic::after,
|
||||
div.admonition::after,
|
||||
blockquote::after {
|
||||
display: block;
|
||||
content: '';
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* -- tables ---------------------------------------------------------------- */
|
||||
|
||||
table.docutils {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
border: 0;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-default {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table caption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
table caption span.caption-text {
|
||||
}
|
||||
|
||||
table.docutils td, table.docutils th {
|
||||
padding: 1px 8px 1px 5px;
|
||||
border-top: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
|
||||
table.footnote td, table.footnote th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: left;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
table.citation td {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
th > :first-child,
|
||||
td > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
th > :last-child,
|
||||
td > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
/* -- figures --------------------------------------------------------------- */
|
||||
|
||||
div.figure, figure {
|
||||
margin: 0.5em;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
div.figure p.caption, figcaption {
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-number,
|
||||
figcaption span.caption-number {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.figure p.caption span.caption-text,
|
||||
figcaption span.caption-text {
|
||||
}
|
||||
|
||||
/* -- field list styles ----------------------------------------------------- */
|
||||
|
||||
table.field-list td, table.field-list th {
|
||||
border: 0 !important;
|
||||
}
|
||||
|
||||
.field-list ul {
|
||||
margin: 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.field-list p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.field-name {
|
||||
-moz-hyphens: manual;
|
||||
-ms-hyphens: manual;
|
||||
-webkit-hyphens: manual;
|
||||
hyphens: manual;
|
||||
}
|
||||
|
||||
/* -- hlist styles ---------------------------------------------------------- */
|
||||
|
||||
table.hlist {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
table.hlist td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* -- object description styles --------------------------------------------- */
|
||||
|
||||
.sig {
|
||||
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
|
||||
}
|
||||
|
||||
.sig-name, code.descname {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.sig-name {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
code.descname {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.sig-prename, code.descclassname {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.optional {
|
||||
font-size: 1.3em;
|
||||
}
|
||||
|
||||
.sig-paren {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.sig-param.n {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* C++ specific styling */
|
||||
|
||||
.sig-inline.c-texpr,
|
||||
.sig-inline.cpp-texpr {
|
||||
font-family: unset;
|
||||
}
|
||||
|
||||
.sig.c .k, .sig.c .kt,
|
||||
.sig.cpp .k, .sig.cpp .kt {
|
||||
color: #0033B3;
|
||||
}
|
||||
|
||||
.sig.c .m,
|
||||
.sig.cpp .m {
|
||||
color: #1750EB;
|
||||
}
|
||||
|
||||
.sig.c .s, .sig.c .sc,
|
||||
.sig.cpp .s, .sig.cpp .sc {
|
||||
color: #067D17;
|
||||
}
|
||||
|
||||
|
||||
/* -- other body styles ----------------------------------------------------- */
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha;
|
||||
}
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha;
|
||||
}
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman;
|
||||
}
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:first-child > :first-child,
|
||||
:not(li) > ul > li:first-child > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
:not(li) > ol > li:last-child > :last-child,
|
||||
:not(li) > ul > li:last-child > :last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
ol.simple ol p,
|
||||
ol.simple ul p,
|
||||
ul.simple ol p,
|
||||
ul.simple ul p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple > li:not(:first-child) > p,
|
||||
ul.simple > li:not(:first-child) > p {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
ol.simple p,
|
||||
ul.simple p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dl.footnote > dt,
|
||||
dl.citation > dt {
|
||||
float: left;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
dl.footnote > dd,
|
||||
dl.citation > dd {
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
dl.footnote > dd:after,
|
||||
dl.citation > dd:after {
|
||||
content: "";
|
||||
clear: both;
|
||||
}
|
||||
|
||||
dl.field-list {
|
||||
display: grid;
|
||||
grid-template-columns: fit-content(30%) auto;
|
||||
}
|
||||
|
||||
dl.field-list > dt {
|
||||
font-weight: bold;
|
||||
word-break: break-word;
|
||||
padding-left: 0.5em;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
dl.field-list > dt:after {
|
||||
content: ":";
|
||||
}
|
||||
|
||||
dl.field-list > dd {
|
||||
padding-left: 0.5em;
|
||||
margin-top: 0em;
|
||||
margin-left: 0em;
|
||||
margin-bottom: 0em;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
dd > :first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
dd ul, dd table {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-top: 3px;
|
||||
margin-bottom: 10px;
|
||||
margin-left: 30px;
|
||||
}
|
||||
|
||||
dl > dd:last-child,
|
||||
dl > dd:last-child > :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt:target, span.highlighted {
|
||||
background-color: #fbe54e;
|
||||
}
|
||||
|
||||
rect.highlighted {
|
||||
fill: #fbe54e;
|
||||
}
|
||||
|
||||
dl.glossary dt {
|
||||
font-weight: bold;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
.versionmodified {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.system-message {
|
||||
background-color: #fda;
|
||||
padding: 5px;
|
||||
border: 3px solid red;
|
||||
}
|
||||
|
||||
.footnote:target {
|
||||
background-color: #ffa;
|
||||
}
|
||||
|
||||
.line-block {
|
||||
display: block;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.line-block .line-block {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 1.5em;
|
||||
}
|
||||
|
||||
.guilabel, .menuselection {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.accelerator {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.classifier {
|
||||
font-style: oblique;
|
||||
}
|
||||
|
||||
.classifier:before {
|
||||
font-style: normal;
|
||||
margin: 0 0.5em;
|
||||
content: ":";
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
abbr, acronym {
|
||||
border-bottom: dotted 1px;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
/* -- code displays --------------------------------------------------------- */
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
||||
}
|
||||
|
||||
pre, div[class*="highlight-"] {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
span.pre {
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
-webkit-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
div[class*="highlight-"] {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
td.linenos pre {
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
table.highlighttable {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tbody {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.highlighttable tr {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
table.highlighttable td {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos {
|
||||
padding-right: 0.5em;
|
||||
}
|
||||
|
||||
table.highlighttable td.code {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.highlight .hll {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.highlight pre,
|
||||
table.highlighttable pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption + div {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.code-block-caption {
|
||||
margin-top: 1em;
|
||||
padding: 2px 5px;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
div.code-block-caption code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
table.highlighttable td.linenos,
|
||||
span.linenos,
|
||||
div.highlight span.gp { /* gp: Generic.Prompt */
|
||||
user-select: none;
|
||||
-webkit-user-select: text; /* Safari fallback only */
|
||||
-webkit-user-select: none; /* Chrome/Safari */
|
||||
-moz-user-select: none; /* Firefox */
|
||||
-ms-user-select: none; /* IE10+ */
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-number {
|
||||
padding: 0.1em 0.3em;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
div.code-block-caption span.caption-text {
|
||||
}
|
||||
|
||||
div.literal-block-wrapper {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
code.xref, a code {
|
||||
background-color: transparent;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.viewcode-link {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.viewcode-back {
|
||||
float: right;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
div.viewcode-block:target {
|
||||
margin: -1px -10px;
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* -- math display ---------------------------------------------------------- */
|
||||
|
||||
img.math {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.body div.math p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
span.eqno {
|
||||
float: right;
|
||||
}
|
||||
|
||||
span.eqno a.headerlink {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
div.math:hover a.headerlink {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/* -- printout stylesheet --------------------------------------------------- */
|
||||
|
||||
@media print {
|
||||
div.document,
|
||||
div.documentwrapper,
|
||||
div.bodywrapper {
|
||||
margin: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.sphinxsidebar,
|
||||
div.related,
|
||||
div.footer,
|
||||
#top-link {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
/* This file intentionally left blank. */
|
||||
|
|
@ -1,326 +0,0 @@
|
|||
/*
|
||||
* doctools.js
|
||||
* ~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx JavaScript utilities for all documentation.
|
||||
*
|
||||
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* select a different prefix for underscore
|
||||
*/
|
||||
$u = _.noConflict();
|
||||
|
||||
/**
|
||||
* make the code below compatible with browsers without
|
||||
* an installed firebug like debugger
|
||||
if (!window.console || !console.firebug) {
|
||||
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
||||
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
|
||||
"profile", "profileEnd"];
|
||||
window.console = {};
|
||||
for (var i = 0; i < names.length; ++i)
|
||||
window.console[names[i]] = function() {};
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* small helper function to urldecode strings
|
||||
*
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
|
||||
*/
|
||||
jQuery.urldecode = function(x) {
|
||||
if (!x) {
|
||||
return x
|
||||
}
|
||||
return decodeURIComponent(x.replace(/\+/g, ' '));
|
||||
};
|
||||
|
||||
/**
|
||||
* small helper function to urlencode strings
|
||||
*/
|
||||
jQuery.urlencode = encodeURIComponent;
|
||||
|
||||
/**
|
||||
* This function returns the parsed url parameters of the
|
||||
* current request. Multiple values per key are supported,
|
||||
* it will always return arrays of strings for the value parts.
|
||||
*/
|
||||
jQuery.getQueryParameters = function(s) {
|
||||
if (typeof s === 'undefined')
|
||||
s = document.location.search;
|
||||
var parts = s.substr(s.indexOf('?') + 1).split('&');
|
||||
var result = {};
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var tmp = parts[i].split('=', 2);
|
||||
var key = jQuery.urldecode(tmp[0]);
|
||||
var value = jQuery.urldecode(tmp[1]);
|
||||
if (key in result)
|
||||
result[key].push(value);
|
||||
else
|
||||
result[key] = [value];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* highlight a given string on a jquery object by wrapping it in
|
||||
* span elements with the given class name.
|
||||
*/
|
||||
jQuery.fn.highlightText = function(text, className) {
|
||||
function highlight(node, addItems) {
|
||||
if (node.nodeType === 3) {
|
||||
var val = node.nodeValue;
|
||||
var pos = val.toLowerCase().indexOf(text);
|
||||
if (pos >= 0 &&
|
||||
!jQuery(node.parentNode).hasClass(className) &&
|
||||
!jQuery(node.parentNode).hasClass("nohighlight")) {
|
||||
var span;
|
||||
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
|
||||
if (isInSVG) {
|
||||
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
|
||||
} else {
|
||||
span = document.createElement("span");
|
||||
span.className = className;
|
||||
}
|
||||
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
||||
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
|
||||
document.createTextNode(val.substr(pos + text.length)),
|
||||
node.nextSibling));
|
||||
node.nodeValue = val.substr(0, pos);
|
||||
if (isInSVG) {
|
||||
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
|
||||
var bbox = node.parentElement.getBBox();
|
||||
rect.x.baseVal.value = bbox.x;
|
||||
rect.y.baseVal.value = bbox.y;
|
||||
rect.width.baseVal.value = bbox.width;
|
||||
rect.height.baseVal.value = bbox.height;
|
||||
rect.setAttribute('class', className);
|
||||
addItems.push({
|
||||
"parent": node.parentNode,
|
||||
"target": rect});
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!jQuery(node).is("button, select, textarea")) {
|
||||
jQuery.each(node.childNodes, function() {
|
||||
highlight(this, addItems);
|
||||
});
|
||||
}
|
||||
}
|
||||
var addItems = [];
|
||||
var result = this.each(function() {
|
||||
highlight(this, addItems);
|
||||
});
|
||||
for (var i = 0; i < addItems.length; ++i) {
|
||||
jQuery(addItems[i].parent).before(addItems[i].target);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/*
|
||||
* backward compatibility for jQuery.browser
|
||||
* This will be supported until firefox bug is fixed.
|
||||
*/
|
||||
if (!jQuery.browser) {
|
||||
jQuery.uaMatch = function(ua) {
|
||||
ua = ua.toLowerCase();
|
||||
|
||||
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
|
||||
/(msie) ([\w.]+)/.exec(ua) ||
|
||||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
|
||||
[];
|
||||
|
||||
return {
|
||||
browser: match[ 1 ] || "",
|
||||
version: match[ 2 ] || "0"
|
||||
};
|
||||
};
|
||||
jQuery.browser = {};
|
||||
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Small JavaScript module for the documentation.
|
||||
*/
|
||||
var Documentation = {
|
||||
|
||||
init : function() {
|
||||
this.fixFirefoxAnchorBug();
|
||||
this.highlightSearchWords();
|
||||
this.initIndexTable();
|
||||
if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
|
||||
this.initOnKeyListeners();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* i18n support
|
||||
*/
|
||||
TRANSLATIONS : {},
|
||||
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
|
||||
LOCALE : 'unknown',
|
||||
|
||||
// gettext and ngettext don't access this so that the functions
|
||||
// can safely bound to a different name (_ = Documentation.gettext)
|
||||
gettext : function(string) {
|
||||
var translated = Documentation.TRANSLATIONS[string];
|
||||
if (typeof translated === 'undefined')
|
||||
return string;
|
||||
return (typeof translated === 'string') ? translated : translated[0];
|
||||
},
|
||||
|
||||
ngettext : function(singular, plural, n) {
|
||||
var translated = Documentation.TRANSLATIONS[singular];
|
||||
if (typeof translated === 'undefined')
|
||||
return (n == 1) ? singular : plural;
|
||||
return translated[Documentation.PLURALEXPR(n)];
|
||||
},
|
||||
|
||||
addTranslations : function(catalog) {
|
||||
for (var key in catalog.messages)
|
||||
this.TRANSLATIONS[key] = catalog.messages[key];
|
||||
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
|
||||
this.LOCALE = catalog.locale;
|
||||
},
|
||||
|
||||
/**
|
||||
* add context elements like header anchor links
|
||||
*/
|
||||
addContextElements : function() {
|
||||
$('div[id] > :header:first').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this headline')).
|
||||
appendTo(this);
|
||||
});
|
||||
$('dt[id]').each(function() {
|
||||
$('<a class="headerlink">\u00B6</a>').
|
||||
attr('href', '#' + this.id).
|
||||
attr('title', _('Permalink to this definition')).
|
||||
appendTo(this);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* workaround a firefox stupidity
|
||||
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
|
||||
*/
|
||||
fixFirefoxAnchorBug : function() {
|
||||
if (document.location.hash && $.browser.mozilla)
|
||||
window.setTimeout(function() {
|
||||
document.location.href += '';
|
||||
}, 10);
|
||||
},
|
||||
|
||||
/**
|
||||
* highlight the search words provided in the url in the text
|
||||
*/
|
||||
highlightSearchWords : function() {
|
||||
var params = $.getQueryParameters();
|
||||
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
||||
if (terms.length) {
|
||||
var body = $('div.body');
|
||||
if (!body.length) {
|
||||
body = $('body');
|
||||
}
|
||||
window.setTimeout(function() {
|
||||
$.each(terms, function() {
|
||||
body.highlightText(this.toLowerCase(), 'highlighted');
|
||||
});
|
||||
}, 10);
|
||||
$('<p class="highlight-link"><a href="javascript:Documentation.' +
|
||||
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
|
||||
.appendTo($('#searchbox'));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* init the domain index toggle buttons
|
||||
*/
|
||||
initIndexTable : function() {
|
||||
var togglers = $('img.toggler').click(function() {
|
||||
var src = $(this).attr('src');
|
||||
var idnum = $(this).attr('id').substr(7);
|
||||
$('tr.cg-' + idnum).toggle();
|
||||
if (src.substr(-9) === 'minus.png')
|
||||
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
|
||||
else
|
||||
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
|
||||
}).css('display', '');
|
||||
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
|
||||
togglers.click();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function to hide the search marks again
|
||||
*/
|
||||
hideSearchWords : function() {
|
||||
$('#searchbox .highlight-link').fadeOut(300);
|
||||
$('span.highlighted').removeClass('highlighted');
|
||||
var url = new URL(window.location);
|
||||
url.searchParams.delete('highlight');
|
||||
window.history.replaceState({}, '', url);
|
||||
},
|
||||
|
||||
/**
|
||||
* make the url absolute
|
||||
*/
|
||||
makeURL : function(relativeURL) {
|
||||
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
|
||||
},
|
||||
|
||||
/**
|
||||
* get the current relative url
|
||||
*/
|
||||
getCurrentURL : function() {
|
||||
var path = document.location.pathname;
|
||||
var parts = path.split(/\//);
|
||||
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
|
||||
if (this === '..')
|
||||
parts.pop();
|
||||
});
|
||||
var url = parts.join('/');
|
||||
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
|
||||
},
|
||||
|
||||
initOnKeyListeners: function() {
|
||||
$(document).keydown(function(event) {
|
||||
var activeElementType = document.activeElement.tagName;
|
||||
// don't navigate when in search box, textarea, dropdown or button
|
||||
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT'
|
||||
&& activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey
|
||||
&& !event.shiftKey) {
|
||||
switch (event.keyCode) {
|
||||
case 37: // left
|
||||
var prevHref = $('link[rel="prev"]').prop('href');
|
||||
if (prevHref) {
|
||||
window.location.href = prevHref;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 39: // right
|
||||
var nextHref = $('link[rel="next"]').prop('href');
|
||||
if (nextHref) {
|
||||
window.location.href = nextHref;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// quick alias for translations
|
||||
_ = Documentation.gettext;
|
||||
|
||||
$(document).ready(function() {
|
||||
Documentation.init();
|
||||
});
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
var DOCUMENTATION_OPTIONS = {
|
||||
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
|
||||
VERSION: '0.4.1',
|
||||
LANGUAGE: 'None',
|
||||
COLLAPSE_INDEX: false,
|
||||
BUILDER: 'html',
|
||||
FILE_SUFFIX: '.html',
|
||||
LINK_SUFFIX: '.html',
|
||||
HAS_SOURCE: true,
|
||||
SOURCELINK_SUFFIX: '.txt',
|
||||
NAVIGATION_WITH_KEYS: false
|
||||
};
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 286 B |
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -1,297 +0,0 @@
|
|||
/*
|
||||
* language_data.js
|
||||
* ~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* This script contains the language-specific data used by searchtools.js,
|
||||
* namely the list of stopwords, stemmer, scorer and splitter.
|
||||
*
|
||||
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
|
||||
|
||||
|
||||
/* Non-minified version is copied as a separate JS file, is available */
|
||||
|
||||
/**
|
||||
* Porter Stemmer
|
||||
*/
|
||||
var Stemmer = function() {
|
||||
|
||||
var step2list = {
|
||||
ational: 'ate',
|
||||
tional: 'tion',
|
||||
enci: 'ence',
|
||||
anci: 'ance',
|
||||
izer: 'ize',
|
||||
bli: 'ble',
|
||||
alli: 'al',
|
||||
entli: 'ent',
|
||||
eli: 'e',
|
||||
ousli: 'ous',
|
||||
ization: 'ize',
|
||||
ation: 'ate',
|
||||
ator: 'ate',
|
||||
alism: 'al',
|
||||
iveness: 'ive',
|
||||
fulness: 'ful',
|
||||
ousness: 'ous',
|
||||
aliti: 'al',
|
||||
iviti: 'ive',
|
||||
biliti: 'ble',
|
||||
logi: 'log'
|
||||
};
|
||||
|
||||
var step3list = {
|
||||
icate: 'ic',
|
||||
ative: '',
|
||||
alize: 'al',
|
||||
iciti: 'ic',
|
||||
ical: 'ic',
|
||||
ful: '',
|
||||
ness: ''
|
||||
};
|
||||
|
||||
var c = "[^aeiou]"; // consonant
|
||||
var v = "[aeiouy]"; // vowel
|
||||
var C = c + "[^aeiouy]*"; // consonant sequence
|
||||
var V = v + "[aeiou]*"; // vowel sequence
|
||||
|
||||
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
|
||||
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
|
||||
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
|
||||
var s_v = "^(" + C + ")?" + v; // vowel in stem
|
||||
|
||||
this.stemWord = function (w) {
|
||||
var stem;
|
||||
var suffix;
|
||||
var firstch;
|
||||
var origword = w;
|
||||
|
||||
if (w.length < 3)
|
||||
return w;
|
||||
|
||||
var re;
|
||||
var re2;
|
||||
var re3;
|
||||
var re4;
|
||||
|
||||
firstch = w.substr(0,1);
|
||||
if (firstch == "y")
|
||||
w = firstch.toUpperCase() + w.substr(1);
|
||||
|
||||
// Step 1a
|
||||
re = /^(.+?)(ss|i)es$/;
|
||||
re2 = /^(.+?)([^s])s$/;
|
||||
|
||||
if (re.test(w))
|
||||
w = w.replace(re,"$1$2");
|
||||
else if (re2.test(w))
|
||||
w = w.replace(re2,"$1$2");
|
||||
|
||||
// Step 1b
|
||||
re = /^(.+?)eed$/;
|
||||
re2 = /^(.+?)(ed|ing)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(fp[1])) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1];
|
||||
re2 = new RegExp(s_v);
|
||||
if (re2.test(stem)) {
|
||||
w = stem;
|
||||
re2 = /(at|bl|iz)$/;
|
||||
re3 = new RegExp("([^aeiouylsz])\\1$");
|
||||
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re2.test(w))
|
||||
w = w + "e";
|
||||
else if (re3.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
else if (re4.test(w))
|
||||
w = w + "e";
|
||||
}
|
||||
}
|
||||
|
||||
// Step 1c
|
||||
re = /^(.+?)y$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(s_v);
|
||||
if (re.test(stem))
|
||||
w = stem + "i";
|
||||
}
|
||||
|
||||
// Step 2
|
||||
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step2list[suffix];
|
||||
}
|
||||
|
||||
// Step 3
|
||||
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
suffix = fp[2];
|
||||
re = new RegExp(mgr0);
|
||||
if (re.test(stem))
|
||||
w = stem + step3list[suffix];
|
||||
}
|
||||
|
||||
// Step 4
|
||||
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
|
||||
re2 = /^(.+?)(s|t)(ion)$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
if (re.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
else if (re2.test(w)) {
|
||||
var fp = re2.exec(w);
|
||||
stem = fp[1] + fp[2];
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re2.test(stem))
|
||||
w = stem;
|
||||
}
|
||||
|
||||
// Step 5
|
||||
re = /^(.+?)e$/;
|
||||
if (re.test(w)) {
|
||||
var fp = re.exec(w);
|
||||
stem = fp[1];
|
||||
re = new RegExp(mgr1);
|
||||
re2 = new RegExp(meq1);
|
||||
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
||||
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
|
||||
w = stem;
|
||||
}
|
||||
re = /ll$/;
|
||||
re2 = new RegExp(mgr1);
|
||||
if (re.test(w) && re2.test(w)) {
|
||||
re = /.$/;
|
||||
w = w.replace(re,"");
|
||||
}
|
||||
|
||||
// and turn initial Y back to y
|
||||
if (firstch == "y")
|
||||
w = firstch.toLowerCase() + w.substr(1);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var splitChars = (function() {
|
||||
var result = {};
|
||||
var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
|
||||
1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
|
||||
2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
|
||||
2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
|
||||
3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
|
||||
3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
|
||||
4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
|
||||
8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
|
||||
11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
|
||||
43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
|
||||
var i, j, start, end;
|
||||
for (i = 0; i < singles.length; i++) {
|
||||
result[singles[i]] = true;
|
||||
}
|
||||
var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
|
||||
[722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
|
||||
[1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
|
||||
[1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
|
||||
[1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
|
||||
[2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
|
||||
[2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
|
||||
[2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
|
||||
[2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
|
||||
[2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
|
||||
[2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
|
||||
[2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
|
||||
[3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
|
||||
[3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
|
||||
[3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
|
||||
[3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
|
||||
[3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
|
||||
[3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
|
||||
[4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
|
||||
[4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
|
||||
[4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
|
||||
[4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
|
||||
[5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
|
||||
[6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
|
||||
[6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
|
||||
[6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
|
||||
[6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
|
||||
[7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
|
||||
[7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
|
||||
[8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
|
||||
[8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
|
||||
[8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
|
||||
[10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
|
||||
[11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
|
||||
[12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
|
||||
[12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
|
||||
[12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
|
||||
[19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
|
||||
[42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
|
||||
[42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
|
||||
[43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
|
||||
[43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
|
||||
[43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
|
||||
[43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
|
||||
[44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
|
||||
[57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
|
||||
[64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
|
||||
[65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
|
||||
[65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
|
||||
for (i = 0; i < ranges.length; i++) {
|
||||
start = ranges[i][0];
|
||||
end = ranges[i][1];
|
||||
for (j = start; j <= end; j++) {
|
||||
result[j] = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
})();
|
||||
|
||||
function splitQuery(query) {
|
||||
var result = [];
|
||||
var start = -1;
|
||||
for (var i = 0; i < query.length; i++) {
|
||||
if (splitChars[query.charCodeAt(i)]) {
|
||||
if (start !== -1) {
|
||||
result.push(query.slice(start, i));
|
||||
start = -1;
|
||||
}
|
||||
} else if (start === -1) {
|
||||
start = i;
|
||||
}
|
||||
}
|
||||
if (start !== -1) {
|
||||
result.push(query.slice(start));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 90 B |
Binary file not shown.
|
Before Width: | Height: | Size: 90 B |
|
|
@ -1,74 +0,0 @@
|
|||
pre { line-height: 125%; }
|
||||
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
|
||||
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight { background: #eeffcc; }
|
||||
.highlight .c { color: #408090; font-style: italic } /* Comment */
|
||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
||||
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #666666 } /* Operator */
|
||||
.highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
|
||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
||||
.highlight .go { color: #333333 } /* Generic.Output */
|
||||
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
||||
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #902000 } /* Keyword.Type */
|
||||
.highlight .m { color: #208050 } /* Literal.Number */
|
||||
.highlight .s { color: #4070a0 } /* Literal.String */
|
||||
.highlight .na { color: #4070a0 } /* Name.Attribute */
|
||||
.highlight .nb { color: #007020 } /* Name.Builtin */
|
||||
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #60add5 } /* Name.Constant */
|
||||
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
||||
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
||||
.highlight .ne { color: #007020 } /* Name.Exception */
|
||||
.highlight .nf { color: #06287e } /* Name.Function */
|
||||
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
|
||||
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
||||
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
|
||||
.highlight .nv { color: #bb60d5 } /* Name.Variable */
|
||||
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mb { color: #208050 } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #208050 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
|
||||
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
|
||||
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
||||
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
|
||||
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
||||
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #235388 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
||||
.highlight .fm { color: #06287e } /* Name.Function.Magic */
|
||||
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
||||
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
|
||||
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
|
||||
|
|
@ -1,529 +0,0 @@
|
|||
/*
|
||||
* searchtools.js
|
||||
* ~~~~~~~~~~~~~~~~
|
||||
*
|
||||
* Sphinx JavaScript utilities for the full-text search.
|
||||
*
|
||||
* :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
|
||||
if (!Scorer) {
|
||||
/**
|
||||
* Simple result scoring code.
|
||||
*/
|
||||
var Scorer = {
|
||||
// Implement the following function to further tweak the score for each result
|
||||
// The function takes a result array [filename, title, anchor, descr, score]
|
||||
// and returns the new score.
|
||||
/*
|
||||
score: function(result) {
|
||||
return result[4];
|
||||
},
|
||||
*/
|
||||
|
||||
// query matches the full name of an object
|
||||
objNameMatch: 11,
|
||||
// or matches in the last dotted part of the object name
|
||||
objPartialMatch: 6,
|
||||
// Additive scores depending on the priority of the object
|
||||
objPrio: {0: 15, // used to be importantResults
|
||||
1: 5, // used to be objectResults
|
||||
2: -5}, // used to be unimportantResults
|
||||
// Used when the priority is not in the mapping.
|
||||
objPrioDefault: 0,
|
||||
|
||||
// query found in title
|
||||
title: 15,
|
||||
partialTitle: 7,
|
||||
// query found in terms
|
||||
term: 5,
|
||||
partialTerm: 2
|
||||
};
|
||||
}
|
||||
|
||||
if (!splitQuery) {
|
||||
function splitQuery(query) {
|
||||
return query.split(/\s+/);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search Module
|
||||
*/
|
||||
var Search = {
|
||||
|
||||
_index : null,
|
||||
_queued_query : null,
|
||||
_pulse_status : -1,
|
||||
|
||||
htmlToText : function(htmlString) {
|
||||
var virtualDocument = document.implementation.createHTMLDocument('virtual');
|
||||
var htmlElement = $(htmlString, virtualDocument);
|
||||
htmlElement.find('.headerlink').remove();
|
||||
docContent = htmlElement.find('[role=main]')[0];
|
||||
if(docContent === undefined) {
|
||||
console.warn("Content block not found. Sphinx search tries to obtain it " +
|
||||
"via '[role=main]'. Could you check your theme or template.");
|
||||
return "";
|
||||
}
|
||||
return docContent.textContent || docContent.innerText;
|
||||
},
|
||||
|
||||
init : function() {
|
||||
var params = $.getQueryParameters();
|
||||
if (params.q) {
|
||||
var query = params.q[0];
|
||||
$('input[name="q"]')[0].value = query;
|
||||
this.performSearch(query);
|
||||
}
|
||||
},
|
||||
|
||||
loadIndex : function(url) {
|
||||
$.ajax({type: "GET", url: url, data: null,
|
||||
dataType: "script", cache: true,
|
||||
complete: function(jqxhr, textstatus) {
|
||||
if (textstatus != "success") {
|
||||
document.getElementById("searchindexloader").src = url;
|
||||
}
|
||||
}});
|
||||
},
|
||||
|
||||
setIndex : function(index) {
|
||||
var q;
|
||||
this._index = index;
|
||||
if ((q = this._queued_query) !== null) {
|
||||
this._queued_query = null;
|
||||
Search.query(q);
|
||||
}
|
||||
},
|
||||
|
||||
hasIndex : function() {
|
||||
return this._index !== null;
|
||||
},
|
||||
|
||||
deferQuery : function(query) {
|
||||
this._queued_query = query;
|
||||
},
|
||||
|
||||
stopPulse : function() {
|
||||
this._pulse_status = 0;
|
||||
},
|
||||
|
||||
startPulse : function() {
|
||||
if (this._pulse_status >= 0)
|
||||
return;
|
||||
function pulse() {
|
||||
var i;
|
||||
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
||||
var dotString = '';
|
||||
for (i = 0; i < Search._pulse_status; i++)
|
||||
dotString += '.';
|
||||
Search.dots.text(dotString);
|
||||
if (Search._pulse_status > -1)
|
||||
window.setTimeout(pulse, 500);
|
||||
}
|
||||
pulse();
|
||||
},
|
||||
|
||||
/**
|
||||
* perform a search for something (or wait until index is loaded)
|
||||
*/
|
||||
performSearch : function(query) {
|
||||
// create the required interface elements
|
||||
this.out = $('#search-results');
|
||||
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
|
||||
this.dots = $('<span></span>').appendTo(this.title);
|
||||
this.status = $('<p class="search-summary"> </p>').appendTo(this.out);
|
||||
this.output = $('<ul class="search"/>').appendTo(this.out);
|
||||
|
||||
$('#search-progress').text(_('Preparing search...'));
|
||||
this.startPulse();
|
||||
|
||||
// index already loaded, the browser was quick!
|
||||
if (this.hasIndex())
|
||||
this.query(query);
|
||||
else
|
||||
this.deferQuery(query);
|
||||
},
|
||||
|
||||
/**
|
||||
* execute search (requires search index to be loaded)
|
||||
*/
|
||||
query : function(query) {
|
||||
var i;
|
||||
|
||||
// stem the searchterms and add them to the correct list
|
||||
var stemmer = new Stemmer();
|
||||
var searchterms = [];
|
||||
var excluded = [];
|
||||
var hlterms = [];
|
||||
var tmp = splitQuery(query);
|
||||
var objectterms = [];
|
||||
for (i = 0; i < tmp.length; i++) {
|
||||
if (tmp[i] !== "") {
|
||||
objectterms.push(tmp[i].toLowerCase());
|
||||
}
|
||||
|
||||
if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i] === "") {
|
||||
// skip this "word"
|
||||
continue;
|
||||
}
|
||||
// stem the word
|
||||
var word = stemmer.stemWord(tmp[i].toLowerCase());
|
||||
// prevent stemmer from cutting word smaller than two chars
|
||||
if(word.length < 3 && tmp[i].length >= 3) {
|
||||
word = tmp[i];
|
||||
}
|
||||
var toAppend;
|
||||
// select the correct list
|
||||
if (word[0] == '-') {
|
||||
toAppend = excluded;
|
||||
word = word.substr(1);
|
||||
}
|
||||
else {
|
||||
toAppend = searchterms;
|
||||
hlterms.push(tmp[i].toLowerCase());
|
||||
}
|
||||
// only add if not already in the list
|
||||
if (!$u.contains(toAppend, word))
|
||||
toAppend.push(word);
|
||||
}
|
||||
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
||||
|
||||
// console.debug('SEARCH: searching for:');
|
||||
// console.info('required: ', searchterms);
|
||||
// console.info('excluded: ', excluded);
|
||||
|
||||
// prepare search
|
||||
var terms = this._index.terms;
|
||||
var titleterms = this._index.titleterms;
|
||||
|
||||
// array of [filename, title, anchor, descr, score]
|
||||
var results = [];
|
||||
$('#search-progress').empty();
|
||||
|
||||
// lookup as object
|
||||
for (i = 0; i < objectterms.length; i++) {
|
||||
var others = [].concat(objectterms.slice(0, i),
|
||||
objectterms.slice(i+1, objectterms.length));
|
||||
results = results.concat(this.performObjectSearch(objectterms[i], others));
|
||||
}
|
||||
|
||||
// lookup as search terms in fulltext
|
||||
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
|
||||
|
||||
// let the scorer override scores with a custom scoring function
|
||||
if (Scorer.score) {
|
||||
for (i = 0; i < results.length; i++)
|
||||
results[i][4] = Scorer.score(results[i]);
|
||||
}
|
||||
|
||||
// now sort the results by score (in opposite order of appearance, since the
|
||||
// display function below uses pop() to retrieve items) and then
|
||||
// alphabetically
|
||||
results.sort(function(a, b) {
|
||||
var left = a[4];
|
||||
var right = b[4];
|
||||
if (left > right) {
|
||||
return 1;
|
||||
} else if (left < right) {
|
||||
return -1;
|
||||
} else {
|
||||
// same score: sort alphabetically
|
||||
left = a[1].toLowerCase();
|
||||
right = b[1].toLowerCase();
|
||||
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
||||
}
|
||||
});
|
||||
|
||||
// for debugging
|
||||
//Search.lastresults = results.slice(); // a copy
|
||||
//console.info('search results:', Search.lastresults);
|
||||
|
||||
// print the results
|
||||
var resultCount = results.length;
|
||||
function displayNextItem() {
|
||||
// results left, load the summary and display it
|
||||
if (results.length) {
|
||||
var item = results.pop();
|
||||
var listItem = $('<li></li>');
|
||||
var requestUrl = "";
|
||||
var linkUrl = "";
|
||||
if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') {
|
||||
// dirhtml builder
|
||||
var dirname = item[0] + '/';
|
||||
if (dirname.match(/\/index\/$/)) {
|
||||
dirname = dirname.substring(0, dirname.length-6);
|
||||
} else if (dirname == 'index/') {
|
||||
dirname = '';
|
||||
}
|
||||
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + dirname;
|
||||
linkUrl = requestUrl;
|
||||
|
||||
} else {
|
||||
// normal html builders
|
||||
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX;
|
||||
linkUrl = item[0] + DOCUMENTATION_OPTIONS.LINK_SUFFIX;
|
||||
}
|
||||
listItem.append($('<a/>').attr('href',
|
||||
linkUrl +
|
||||
highlightstring + item[2]).html(item[1]));
|
||||
if (item[3]) {
|
||||
listItem.append($('<span> (' + item[3] + ')</span>'));
|
||||
Search.output.append(listItem);
|
||||
setTimeout(function() {
|
||||
displayNextItem();
|
||||
}, 5);
|
||||
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
||||
$.ajax({url: requestUrl,
|
||||
dataType: "text",
|
||||
complete: function(jqxhr, textstatus) {
|
||||
var data = jqxhr.responseText;
|
||||
if (data !== '' && data !== undefined) {
|
||||
var summary = Search.makeSearchSummary(data, searchterms, hlterms);
|
||||
if (summary) {
|
||||
listItem.append(summary);
|
||||
}
|
||||
}
|
||||
Search.output.append(listItem);
|
||||
setTimeout(function() {
|
||||
displayNextItem();
|
||||
}, 5);
|
||||
}});
|
||||
} else {
|
||||
// no source available, just display title
|
||||
Search.output.append(listItem);
|
||||
setTimeout(function() {
|
||||
displayNextItem();
|
||||
}, 5);
|
||||
}
|
||||
}
|
||||
// search finished, update title and status message
|
||||
else {
|
||||
Search.stopPulse();
|
||||
Search.title.text(_('Search Results'));
|
||||
if (!resultCount)
|
||||
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
|
||||
else
|
||||
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
|
||||
Search.status.fadeIn(500);
|
||||
}
|
||||
}
|
||||
displayNextItem();
|
||||
},
|
||||
|
||||
/**
|
||||
* search for object names
|
||||
*/
|
||||
performObjectSearch : function(object, otherterms) {
|
||||
var filenames = this._index.filenames;
|
||||
var docnames = this._index.docnames;
|
||||
var objects = this._index.objects;
|
||||
var objnames = this._index.objnames;
|
||||
var titles = this._index.titles;
|
||||
|
||||
var i;
|
||||
var results = [];
|
||||
|
||||
for (var prefix in objects) {
|
||||
for (var iMatch = 0; iMatch != objects[prefix].length; ++iMatch) {
|
||||
var match = objects[prefix][iMatch];
|
||||
var name = match[4];
|
||||
var fullname = (prefix ? prefix + '.' : '') + name;
|
||||
var fullnameLower = fullname.toLowerCase()
|
||||
if (fullnameLower.indexOf(object) > -1) {
|
||||
var score = 0;
|
||||
var parts = fullnameLower.split('.');
|
||||
// check for different match types: exact matches of full name or
|
||||
// "last name" (i.e. last dotted part)
|
||||
if (fullnameLower == object || parts[parts.length - 1] == object) {
|
||||
score += Scorer.objNameMatch;
|
||||
// matches in last name
|
||||
} else if (parts[parts.length - 1].indexOf(object) > -1) {
|
||||
score += Scorer.objPartialMatch;
|
||||
}
|
||||
var objname = objnames[match[1]][2];
|
||||
var title = titles[match[0]];
|
||||
// If more than one term searched for, we require other words to be
|
||||
// found in the name/title/description
|
||||
if (otherterms.length > 0) {
|
||||
var haystack = (prefix + ' ' + name + ' ' +
|
||||
objname + ' ' + title).toLowerCase();
|
||||
var allfound = true;
|
||||
for (i = 0; i < otherterms.length; i++) {
|
||||
if (haystack.indexOf(otherterms[i]) == -1) {
|
||||
allfound = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!allfound) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var descr = objname + _(', in ') + title;
|
||||
|
||||
var anchor = match[3];
|
||||
if (anchor === '')
|
||||
anchor = fullname;
|
||||
else if (anchor == '-')
|
||||
anchor = objnames[match[1]][1] + '-' + fullname;
|
||||
// add custom score for some objects according to scorer
|
||||
if (Scorer.objPrio.hasOwnProperty(match[2])) {
|
||||
score += Scorer.objPrio[match[2]];
|
||||
} else {
|
||||
score += Scorer.objPrioDefault;
|
||||
}
|
||||
results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
/**
|
||||
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
|
||||
*/
|
||||
escapeRegExp : function(string) {
|
||||
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
|
||||
},
|
||||
|
||||
/**
|
||||
* search for full-text terms in the index
|
||||
*/
|
||||
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
|
||||
var docnames = this._index.docnames;
|
||||
var filenames = this._index.filenames;
|
||||
var titles = this._index.titles;
|
||||
|
||||
var i, j, file;
|
||||
var fileMap = {};
|
||||
var scoreMap = {};
|
||||
var results = [];
|
||||
|
||||
// perform the search on the required terms
|
||||
for (i = 0; i < searchterms.length; i++) {
|
||||
var word = searchterms[i];
|
||||
var files = [];
|
||||
var _o = [
|
||||
{files: terms[word], score: Scorer.term},
|
||||
{files: titleterms[word], score: Scorer.title}
|
||||
];
|
||||
// add support for partial matches
|
||||
if (word.length > 2) {
|
||||
var word_regex = this.escapeRegExp(word);
|
||||
for (var w in terms) {
|
||||
if (w.match(word_regex) && !terms[word]) {
|
||||
_o.push({files: terms[w], score: Scorer.partialTerm})
|
||||
}
|
||||
}
|
||||
for (var w in titleterms) {
|
||||
if (w.match(word_regex) && !titleterms[word]) {
|
||||
_o.push({files: titleterms[w], score: Scorer.partialTitle})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no match but word was a required one
|
||||
if ($u.every(_o, function(o){return o.files === undefined;})) {
|
||||
break;
|
||||
}
|
||||
// found search word in contents
|
||||
$u.each(_o, function(o) {
|
||||
var _files = o.files;
|
||||
if (_files === undefined)
|
||||
return
|
||||
|
||||
if (_files.length === undefined)
|
||||
_files = [_files];
|
||||
files = files.concat(_files);
|
||||
|
||||
// set score for the word in each file to Scorer.term
|
||||
for (j = 0; j < _files.length; j++) {
|
||||
file = _files[j];
|
||||
if (!(file in scoreMap))
|
||||
scoreMap[file] = {};
|
||||
scoreMap[file][word] = o.score;
|
||||
}
|
||||
});
|
||||
|
||||
// create the mapping
|
||||
for (j = 0; j < files.length; j++) {
|
||||
file = files[j];
|
||||
if (file in fileMap && fileMap[file].indexOf(word) === -1)
|
||||
fileMap[file].push(word);
|
||||
else
|
||||
fileMap[file] = [word];
|
||||
}
|
||||
}
|
||||
|
||||
// now check if the files don't contain excluded terms
|
||||
for (file in fileMap) {
|
||||
var valid = true;
|
||||
|
||||
// check if all requirements are matched
|
||||
var filteredTermCount = // as search terms with length < 3 are discarded: ignore
|
||||
searchterms.filter(function(term){return term.length > 2}).length
|
||||
if (
|
||||
fileMap[file].length != searchterms.length &&
|
||||
fileMap[file].length != filteredTermCount
|
||||
) continue;
|
||||
|
||||
// ensure that none of the excluded terms is in the search result
|
||||
for (i = 0; i < excluded.length; i++) {
|
||||
if (terms[excluded[i]] == file ||
|
||||
titleterms[excluded[i]] == file ||
|
||||
$u.contains(terms[excluded[i]] || [], file) ||
|
||||
$u.contains(titleterms[excluded[i]] || [], file)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we have still a valid result we can add it to the result list
|
||||
if (valid) {
|
||||
// select one (max) score for the file.
|
||||
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
|
||||
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
|
||||
results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
},
|
||||
|
||||
/**
|
||||
* helper function to return a node containing the
|
||||
* search summary for a given text. keywords is a list
|
||||
* of stemmed words, hlwords is the list of normal, unstemmed
|
||||
* words. the first one is used to find the occurrence, the
|
||||
* latter for highlighting it.
|
||||
*/
|
||||
makeSearchSummary : function(htmlText, keywords, hlwords) {
|
||||
var text = Search.htmlToText(htmlText);
|
||||
if (text == "") {
|
||||
return null;
|
||||
}
|
||||
var textLower = text.toLowerCase();
|
||||
var start = 0;
|
||||
$.each(keywords, function() {
|
||||
var i = textLower.indexOf(this.toLowerCase());
|
||||
if (i > -1)
|
||||
start = i;
|
||||
});
|
||||
start = Math.max(start - 120, 0);
|
||||
var excerpt = ((start > 0) ? '...' : '') +
|
||||
$.trim(text.substr(start, 240)) +
|
||||
((start + 240 - text.length) ? '...' : '');
|
||||
var rv = $('<p class="context"></p>').text(excerpt);
|
||||
$.each(hlwords, function() {
|
||||
rv = rv.highlightText(this, 'highlighted');
|
||||
});
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
|
||||
$(document).ready(function() {
|
||||
Search.init();
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,999 +0,0 @@
|
|||
// Underscore.js 1.3.1
|
||||
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// Underscore is freely distributable under the MIT license.
|
||||
// Portions of Underscore are inspired or borrowed from Prototype,
|
||||
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||
// For all details and documentation:
|
||||
// http://documentcloud.github.com/underscore
|
||||
|
||||
(function() {
|
||||
|
||||
// Baseline setup
|
||||
// --------------
|
||||
|
||||
// Establish the root object, `window` in the browser, or `global` on the server.
|
||||
var root = this;
|
||||
|
||||
// Save the previous value of the `_` variable.
|
||||
var previousUnderscore = root._;
|
||||
|
||||
// Establish the object that gets returned to break out of a loop iteration.
|
||||
var breaker = {};
|
||||
|
||||
// Save bytes in the minified (but not gzipped) version:
|
||||
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
||||
|
||||
// Create quick reference variables for speed access to core prototypes.
|
||||
var slice = ArrayProto.slice,
|
||||
unshift = ArrayProto.unshift,
|
||||
toString = ObjProto.toString,
|
||||
hasOwnProperty = ObjProto.hasOwnProperty;
|
||||
|
||||
// All **ECMAScript 5** native function implementations that we hope to use
|
||||
// are declared here.
|
||||
var
|
||||
nativeForEach = ArrayProto.forEach,
|
||||
nativeMap = ArrayProto.map,
|
||||
nativeReduce = ArrayProto.reduce,
|
||||
nativeReduceRight = ArrayProto.reduceRight,
|
||||
nativeFilter = ArrayProto.filter,
|
||||
nativeEvery = ArrayProto.every,
|
||||
nativeSome = ArrayProto.some,
|
||||
nativeIndexOf = ArrayProto.indexOf,
|
||||
nativeLastIndexOf = ArrayProto.lastIndexOf,
|
||||
nativeIsArray = Array.isArray,
|
||||
nativeKeys = Object.keys,
|
||||
nativeBind = FuncProto.bind;
|
||||
|
||||
// Create a safe reference to the Underscore object for use below.
|
||||
var _ = function(obj) { return new wrapper(obj); };
|
||||
|
||||
// Export the Underscore object for **Node.js**, with
|
||||
// backwards-compatibility for the old `require()` API. If we're in
|
||||
// the browser, add `_` as a global object via a string identifier,
|
||||
// for Closure Compiler "advanced" mode.
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
exports = module.exports = _;
|
||||
}
|
||||
exports._ = _;
|
||||
} else {
|
||||
root['_'] = _;
|
||||
}
|
||||
|
||||
// Current version.
|
||||
_.VERSION = '1.3.1';
|
||||
|
||||
// Collection Functions
|
||||
// --------------------
|
||||
|
||||
// The cornerstone, an `each` implementation, aka `forEach`.
|
||||
// Handles objects with the built-in `forEach`, arrays, and raw objects.
|
||||
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
||||
var each = _.each = _.forEach = function(obj, iterator, context) {
|
||||
if (obj == null) return;
|
||||
if (nativeForEach && obj.forEach === nativeForEach) {
|
||||
obj.forEach(iterator, context);
|
||||
} else if (obj.length === +obj.length) {
|
||||
for (var i = 0, l = obj.length; i < l; i++) {
|
||||
if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
|
||||
}
|
||||
} else {
|
||||
for (var key in obj) {
|
||||
if (_.has(obj, key)) {
|
||||
if (iterator.call(context, obj[key], key, obj) === breaker) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Return the results of applying the iterator to each element.
|
||||
// Delegates to **ECMAScript 5**'s native `map` if available.
|
||||
_.map = _.collect = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
results[results.length] = iterator.call(context, value, index, list);
|
||||
});
|
||||
if (obj.length === +obj.length) results.length = obj.length;
|
||||
return results;
|
||||
};
|
||||
|
||||
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
||||
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
||||
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
||||
var initial = arguments.length > 2;
|
||||
if (obj == null) obj = [];
|
||||
if (nativeReduce && obj.reduce === nativeReduce) {
|
||||
if (context) iterator = _.bind(iterator, context);
|
||||
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
|
||||
}
|
||||
each(obj, function(value, index, list) {
|
||||
if (!initial) {
|
||||
memo = value;
|
||||
initial = true;
|
||||
} else {
|
||||
memo = iterator.call(context, memo, value, index, list);
|
||||
}
|
||||
});
|
||||
if (!initial) throw new TypeError('Reduce of empty array with no initial value');
|
||||
return memo;
|
||||
};
|
||||
|
||||
// The right-associative version of reduce, also known as `foldr`.
|
||||
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
|
||||
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
||||
var initial = arguments.length > 2;
|
||||
if (obj == null) obj = [];
|
||||
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
||||
if (context) iterator = _.bind(iterator, context);
|
||||
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||||
}
|
||||
var reversed = _.toArray(obj).reverse();
|
||||
if (context && !initial) iterator = _.bind(iterator, context);
|
||||
return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
|
||||
};
|
||||
|
||||
// Return the first value which passes a truth test. Aliased as `detect`.
|
||||
_.find = _.detect = function(obj, iterator, context) {
|
||||
var result;
|
||||
any(obj, function(value, index, list) {
|
||||
if (iterator.call(context, value, index, list)) {
|
||||
result = value;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
// Return all the elements that pass a truth test.
|
||||
// Delegates to **ECMAScript 5**'s native `filter` if available.
|
||||
// Aliased as `select`.
|
||||
_.filter = _.select = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (iterator.call(context, value, index, list)) results[results.length] = value;
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
// Return all the elements for which a truth test fails.
|
||||
_.reject = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
if (obj == null) return results;
|
||||
each(obj, function(value, index, list) {
|
||||
if (!iterator.call(context, value, index, list)) results[results.length] = value;
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
// Determine whether all of the elements match a truth test.
|
||||
// Delegates to **ECMAScript 5**'s native `every` if available.
|
||||
// Aliased as `all`.
|
||||
_.every = _.all = function(obj, iterator, context) {
|
||||
var result = true;
|
||||
if (obj == null) return result;
|
||||
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
// Determine if at least one element in the object matches a truth test.
|
||||
// Delegates to **ECMAScript 5**'s native `some` if available.
|
||||
// Aliased as `any`.
|
||||
var any = _.some = _.any = function(obj, iterator, context) {
|
||||
iterator || (iterator = _.identity);
|
||||
var result = false;
|
||||
if (obj == null) return result;
|
||||
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
|
||||
each(obj, function(value, index, list) {
|
||||
if (result || (result = iterator.call(context, value, index, list))) return breaker;
|
||||
});
|
||||
return !!result;
|
||||
};
|
||||
|
||||
// Determine if a given value is included in the array or object using `===`.
|
||||
// Aliased as `contains`.
|
||||
_.include = _.contains = function(obj, target) {
|
||||
var found = false;
|
||||
if (obj == null) return found;
|
||||
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||||
found = any(obj, function(value) {
|
||||
return value === target;
|
||||
});
|
||||
return found;
|
||||
};
|
||||
|
||||
// Invoke a method (with arguments) on every item in a collection.
|
||||
_.invoke = function(obj, method) {
|
||||
var args = slice.call(arguments, 2);
|
||||
return _.map(obj, function(value) {
|
||||
return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
|
||||
});
|
||||
};
|
||||
|
||||
// Convenience version of a common use case of `map`: fetching a property.
|
||||
_.pluck = function(obj, key) {
|
||||
return _.map(obj, function(value){ return value[key]; });
|
||||
};
|
||||
|
||||
// Return the maximum element or (element-based computation).
|
||||
_.max = function(obj, iterator, context) {
|
||||
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
||||
if (!iterator && _.isEmpty(obj)) return -Infinity;
|
||||
var result = {computed : -Infinity};
|
||||
each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed >= result.computed && (result = {value : value, computed : computed});
|
||||
});
|
||||
return result.value;
|
||||
};
|
||||
|
||||
// Return the minimum element (or element-based computation).
|
||||
_.min = function(obj, iterator, context) {
|
||||
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
||||
if (!iterator && _.isEmpty(obj)) return Infinity;
|
||||
var result = {computed : Infinity};
|
||||
each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed < result.computed && (result = {value : value, computed : computed});
|
||||
});
|
||||
return result.value;
|
||||
};
|
||||
|
||||
// Shuffle an array.
|
||||
_.shuffle = function(obj) {
|
||||
var shuffled = [], rand;
|
||||
each(obj, function(value, index, list) {
|
||||
if (index == 0) {
|
||||
shuffled[0] = value;
|
||||
} else {
|
||||
rand = Math.floor(Math.random() * (index + 1));
|
||||
shuffled[index] = shuffled[rand];
|
||||
shuffled[rand] = value;
|
||||
}
|
||||
});
|
||||
return shuffled;
|
||||
};
|
||||
|
||||
// Sort the object's values by a criterion produced by an iterator.
|
||||
_.sortBy = function(obj, iterator, context) {
|
||||
return _.pluck(_.map(obj, function(value, index, list) {
|
||||
return {
|
||||
value : value,
|
||||
criteria : iterator.call(context, value, index, list)
|
||||
};
|
||||
}).sort(function(left, right) {
|
||||
var a = left.criteria, b = right.criteria;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}), 'value');
|
||||
};
|
||||
|
||||
// Groups the object's values by a criterion. Pass either a string attribute
|
||||
// to group by, or a function that returns the criterion.
|
||||
_.groupBy = function(obj, val) {
|
||||
var result = {};
|
||||
var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
|
||||
each(obj, function(value, index) {
|
||||
var key = iterator(value, index);
|
||||
(result[key] || (result[key] = [])).push(value);
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
// Use a comparator function to figure out at what index an object should
|
||||
// be inserted so as to maintain order. Uses binary search.
|
||||
_.sortedIndex = function(array, obj, iterator) {
|
||||
iterator || (iterator = _.identity);
|
||||
var low = 0, high = array.length;
|
||||
while (low < high) {
|
||||
var mid = (low + high) >> 1;
|
||||
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
|
||||
}
|
||||
return low;
|
||||
};
|
||||
|
||||
// Safely convert anything iterable into a real, live array.
|
||||
_.toArray = function(iterable) {
|
||||
if (!iterable) return [];
|
||||
if (iterable.toArray) return iterable.toArray();
|
||||
if (_.isArray(iterable)) return slice.call(iterable);
|
||||
if (_.isArguments(iterable)) return slice.call(iterable);
|
||||
return _.values(iterable);
|
||||
};
|
||||
|
||||
// Return the number of elements in an object.
|
||||
_.size = function(obj) {
|
||||
return _.toArray(obj).length;
|
||||
};
|
||||
|
||||
// Array Functions
|
||||
// ---------------
|
||||
|
||||
// Get the first element of an array. Passing **n** will return the first N
|
||||
// values in the array. Aliased as `head`. The **guard** check allows it to work
|
||||
// with `_.map`.
|
||||
_.first = _.head = function(array, n, guard) {
|
||||
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
|
||||
};
|
||||
|
||||
// Returns everything but the last entry of the array. Especcialy useful on
|
||||
// the arguments object. Passing **n** will return all the values in
|
||||
// the array, excluding the last N. The **guard** check allows it to work with
|
||||
// `_.map`.
|
||||
_.initial = function(array, n, guard) {
|
||||
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n));
|
||||
};
|
||||
|
||||
// Get the last element of an array. Passing **n** will return the last N
|
||||
// values in the array. The **guard** check allows it to work with `_.map`.
|
||||
_.last = function(array, n, guard) {
|
||||
if ((n != null) && !guard) {
|
||||
return slice.call(array, Math.max(array.length - n, 0));
|
||||
} else {
|
||||
return array[array.length - 1];
|
||||
}
|
||||
};
|
||||
|
||||
// Returns everything but the first entry of the array. Aliased as `tail`.
|
||||
// Especially useful on the arguments object. Passing an **index** will return
|
||||
// the rest of the values in the array from that index onward. The **guard**
|
||||
// check allows it to work with `_.map`.
|
||||
_.rest = _.tail = function(array, index, guard) {
|
||||
return slice.call(array, (index == null) || guard ? 1 : index);
|
||||
};
|
||||
|
||||
// Trim out all falsy values from an array.
|
||||
_.compact = function(array) {
|
||||
return _.filter(array, function(value){ return !!value; });
|
||||
};
|
||||
|
||||
// Return a completely flattened version of an array.
|
||||
_.flatten = function(array, shallow) {
|
||||
return _.reduce(array, function(memo, value) {
|
||||
if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
|
||||
memo[memo.length] = value;
|
||||
return memo;
|
||||
}, []);
|
||||
};
|
||||
|
||||
// Return a version of the array that does not contain the specified value(s).
|
||||
_.without = function(array) {
|
||||
return _.difference(array, slice.call(arguments, 1));
|
||||
};
|
||||
|
||||
// Produce a duplicate-free version of the array. If the array has already
|
||||
// been sorted, you have the option of using a faster algorithm.
|
||||
// Aliased as `unique`.
|
||||
_.uniq = _.unique = function(array, isSorted, iterator) {
|
||||
var initial = iterator ? _.map(array, iterator) : array;
|
||||
var result = [];
|
||||
_.reduce(initial, function(memo, el, i) {
|
||||
if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
|
||||
memo[memo.length] = el;
|
||||
result[result.length] = array[i];
|
||||
}
|
||||
return memo;
|
||||
}, []);
|
||||
return result;
|
||||
};
|
||||
|
||||
// Produce an array that contains the union: each distinct element from all of
|
||||
// the passed-in arrays.
|
||||
_.union = function() {
|
||||
return _.uniq(_.flatten(arguments, true));
|
||||
};
|
||||
|
||||
// Produce an array that contains every item shared between all the
|
||||
// passed-in arrays. (Aliased as "intersect" for back-compat.)
|
||||
_.intersection = _.intersect = function(array) {
|
||||
var rest = slice.call(arguments, 1);
|
||||
return _.filter(_.uniq(array), function(item) {
|
||||
return _.every(rest, function(other) {
|
||||
return _.indexOf(other, item) >= 0;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Take the difference between one array and a number of other arrays.
|
||||
// Only the elements present in just the first array will remain.
|
||||
_.difference = function(array) {
|
||||
var rest = _.flatten(slice.call(arguments, 1));
|
||||
return _.filter(array, function(value){ return !_.include(rest, value); });
|
||||
};
|
||||
|
||||
// Zip together multiple lists into a single array -- elements that share
|
||||
// an index go together.
|
||||
_.zip = function() {
|
||||
var args = slice.call(arguments);
|
||||
var length = _.max(_.pluck(args, 'length'));
|
||||
var results = new Array(length);
|
||||
for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
|
||||
return results;
|
||||
};
|
||||
|
||||
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
|
||||
// we need this function. Return the position of the first occurrence of an
|
||||
// item in an array, or -1 if the item is not included in the array.
|
||||
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
|
||||
// If the array is large and already in sort order, pass `true`
|
||||
// for **isSorted** to use binary search.
|
||||
_.indexOf = function(array, item, isSorted) {
|
||||
if (array == null) return -1;
|
||||
var i, l;
|
||||
if (isSorted) {
|
||||
i = _.sortedIndex(array, item);
|
||||
return array[i] === item ? i : -1;
|
||||
}
|
||||
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
|
||||
for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
||||
_.lastIndexOf = function(array, item) {
|
||||
if (array == null) return -1;
|
||||
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
|
||||
var i = array.length;
|
||||
while (i--) if (i in array && array[i] === item) return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Generate an integer Array containing an arithmetic progression. A port of
|
||||
// the native Python `range()` function. See
|
||||
// [the Python documentation](http://docs.python.org/library/functions.html#range).
|
||||
_.range = function(start, stop, step) {
|
||||
if (arguments.length <= 1) {
|
||||
stop = start || 0;
|
||||
start = 0;
|
||||
}
|
||||
step = arguments[2] || 1;
|
||||
|
||||
var len = Math.max(Math.ceil((stop - start) / step), 0);
|
||||
var idx = 0;
|
||||
var range = new Array(len);
|
||||
|
||||
while(idx < len) {
|
||||
range[idx++] = start;
|
||||
start += step;
|
||||
}
|
||||
|
||||
return range;
|
||||
};
|
||||
|
||||
// Function (ahem) Functions
|
||||
// ------------------
|
||||
|
||||
// Reusable constructor function for prototype setting.
|
||||
var ctor = function(){};
|
||||
|
||||
// Create a function bound to a given object (assigning `this`, and arguments,
|
||||
// optionally). Binding with arguments is also known as `curry`.
|
||||
// Delegates to **ECMAScript 5**'s native `Function.bind` if available.
|
||||
// We check for `func.bind` first, to fail fast when `func` is undefined.
|
||||
_.bind = function bind(func, context) {
|
||||
var bound, args;
|
||||
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
||||
if (!_.isFunction(func)) throw new TypeError;
|
||||
args = slice.call(arguments, 2);
|
||||
return bound = function() {
|
||||
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
|
||||
ctor.prototype = func.prototype;
|
||||
var self = new ctor;
|
||||
var result = func.apply(self, args.concat(slice.call(arguments)));
|
||||
if (Object(result) === result) return result;
|
||||
return self;
|
||||
};
|
||||
};
|
||||
|
||||
// Bind all of an object's methods to that object. Useful for ensuring that
|
||||
// all callbacks defined on an object belong to it.
|
||||
_.bindAll = function(obj) {
|
||||
var funcs = slice.call(arguments, 1);
|
||||
if (funcs.length == 0) funcs = _.functions(obj);
|
||||
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Memoize an expensive function by storing its results.
|
||||
_.memoize = function(func, hasher) {
|
||||
var memo = {};
|
||||
hasher || (hasher = _.identity);
|
||||
return function() {
|
||||
var key = hasher.apply(this, arguments);
|
||||
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
|
||||
};
|
||||
};
|
||||
|
||||
// Delays a function for the given number of milliseconds, and then calls
|
||||
// it with the arguments supplied.
|
||||
_.delay = function(func, wait) {
|
||||
var args = slice.call(arguments, 2);
|
||||
return setTimeout(function(){ return func.apply(func, args); }, wait);
|
||||
};
|
||||
|
||||
// Defers a function, scheduling it to run after the current call stack has
|
||||
// cleared.
|
||||
_.defer = function(func) {
|
||||
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
|
||||
};
|
||||
|
||||
// Returns a function, that, when invoked, will only be triggered at most once
|
||||
// during a given window of time.
|
||||
_.throttle = function(func, wait) {
|
||||
var context, args, timeout, throttling, more;
|
||||
var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
|
||||
return function() {
|
||||
context = this; args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
if (more) func.apply(context, args);
|
||||
whenDone();
|
||||
};
|
||||
if (!timeout) timeout = setTimeout(later, wait);
|
||||
if (throttling) {
|
||||
more = true;
|
||||
} else {
|
||||
func.apply(context, args);
|
||||
}
|
||||
whenDone();
|
||||
throttling = true;
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a function, that, as long as it continues to be invoked, will not
|
||||
// be triggered. The function will be called after it stops being called for
|
||||
// N milliseconds.
|
||||
_.debounce = function(func, wait) {
|
||||
var timeout;
|
||||
return function() {
|
||||
var context = this, args = arguments;
|
||||
var later = function() {
|
||||
timeout = null;
|
||||
func.apply(context, args);
|
||||
};
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a function that will be executed at most one time, no matter how
|
||||
// often you call it. Useful for lazy initialization.
|
||||
_.once = function(func) {
|
||||
var ran = false, memo;
|
||||
return function() {
|
||||
if (ran) return memo;
|
||||
ran = true;
|
||||
return memo = func.apply(this, arguments);
|
||||
};
|
||||
};
|
||||
|
||||
// Returns the first function passed as an argument to the second,
|
||||
// allowing you to adjust arguments, run code before and after, and
|
||||
// conditionally execute the original function.
|
||||
_.wrap = function(func, wrapper) {
|
||||
return function() {
|
||||
var args = [func].concat(slice.call(arguments, 0));
|
||||
return wrapper.apply(this, args);
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a function that is the composition of a list of functions, each
|
||||
// consuming the return value of the function that follows.
|
||||
_.compose = function() {
|
||||
var funcs = arguments;
|
||||
return function() {
|
||||
var args = arguments;
|
||||
for (var i = funcs.length - 1; i >= 0; i--) {
|
||||
args = [funcs[i].apply(this, args)];
|
||||
}
|
||||
return args[0];
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a function that will only be executed after being called N times.
|
||||
_.after = function(times, func) {
|
||||
if (times <= 0) return func();
|
||||
return function() {
|
||||
if (--times < 1) { return func.apply(this, arguments); }
|
||||
};
|
||||
};
|
||||
|
||||
// Object Functions
|
||||
// ----------------
|
||||
|
||||
// Retrieve the names of an object's properties.
|
||||
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
||||
_.keys = nativeKeys || function(obj) {
|
||||
if (obj !== Object(obj)) throw new TypeError('Invalid object');
|
||||
var keys = [];
|
||||
for (var key in obj) if (_.has(obj, key)) keys[keys.length] = key;
|
||||
return keys;
|
||||
};
|
||||
|
||||
// Retrieve the values of an object's properties.
|
||||
_.values = function(obj) {
|
||||
return _.map(obj, _.identity);
|
||||
};
|
||||
|
||||
// Return a sorted list of the function names available on the object.
|
||||
// Aliased as `methods`
|
||||
_.functions = _.methods = function(obj) {
|
||||
var names = [];
|
||||
for (var key in obj) {
|
||||
if (_.isFunction(obj[key])) names.push(key);
|
||||
}
|
||||
return names.sort();
|
||||
};
|
||||
|
||||
// Extend a given object with all the properties in passed-in object(s).
|
||||
_.extend = function(obj) {
|
||||
each(slice.call(arguments, 1), function(source) {
|
||||
for (var prop in source) {
|
||||
obj[prop] = source[prop];
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Fill in a given object with default properties.
|
||||
_.defaults = function(obj) {
|
||||
each(slice.call(arguments, 1), function(source) {
|
||||
for (var prop in source) {
|
||||
if (obj[prop] == null) obj[prop] = source[prop];
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Create a (shallow-cloned) duplicate of an object.
|
||||
_.clone = function(obj) {
|
||||
if (!_.isObject(obj)) return obj;
|
||||
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
|
||||
};
|
||||
|
||||
// Invokes interceptor with the obj, and then returns obj.
|
||||
// The primary purpose of this method is to "tap into" a method chain, in
|
||||
// order to perform operations on intermediate results within the chain.
|
||||
_.tap = function(obj, interceptor) {
|
||||
interceptor(obj);
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Internal recursive comparison function.
|
||||
function eq(a, b, stack) {
|
||||
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
||||
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
|
||||
if (a === b) return a !== 0 || 1 / a == 1 / b;
|
||||
// A strict comparison is necessary because `null == undefined`.
|
||||
if (a == null || b == null) return a === b;
|
||||
// Unwrap any wrapped objects.
|
||||
if (a._chain) a = a._wrapped;
|
||||
if (b._chain) b = b._wrapped;
|
||||
// Invoke a custom `isEqual` method if one is provided.
|
||||
if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
|
||||
if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
|
||||
// Compare `[[Class]]` names.
|
||||
var className = toString.call(a);
|
||||
if (className != toString.call(b)) return false;
|
||||
switch (className) {
|
||||
// Strings, numbers, dates, and booleans are compared by value.
|
||||
case '[object String]':
|
||||
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
||||
// equivalent to `new String("5")`.
|
||||
return a == String(b);
|
||||
case '[object Number]':
|
||||
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
|
||||
// other numeric values.
|
||||
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
|
||||
case '[object Date]':
|
||||
case '[object Boolean]':
|
||||
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
|
||||
// millisecond representations. Note that invalid dates with millisecond representations
|
||||
// of `NaN` are not equivalent.
|
||||
return +a == +b;
|
||||
// RegExps are compared by their source patterns and flags.
|
||||
case '[object RegExp]':
|
||||
return a.source == b.source &&
|
||||
a.global == b.global &&
|
||||
a.multiline == b.multiline &&
|
||||
a.ignoreCase == b.ignoreCase;
|
||||
}
|
||||
if (typeof a != 'object' || typeof b != 'object') return false;
|
||||
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
||||
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
||||
var length = stack.length;
|
||||
while (length--) {
|
||||
// Linear search. Performance is inversely proportional to the number of
|
||||
// unique nested structures.
|
||||
if (stack[length] == a) return true;
|
||||
}
|
||||
// Add the first object to the stack of traversed objects.
|
||||
stack.push(a);
|
||||
var size = 0, result = true;
|
||||
// Recursively compare objects and arrays.
|
||||
if (className == '[object Array]') {
|
||||
// Compare array lengths to determine if a deep comparison is necessary.
|
||||
size = a.length;
|
||||
result = size == b.length;
|
||||
if (result) {
|
||||
// Deep compare the contents, ignoring non-numeric properties.
|
||||
while (size--) {
|
||||
// Ensure commutative equality for sparse arrays.
|
||||
if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Objects with different constructors are not equivalent.
|
||||
if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
|
||||
// Deep compare objects.
|
||||
for (var key in a) {
|
||||
if (_.has(a, key)) {
|
||||
// Count the expected number of properties.
|
||||
size++;
|
||||
// Deep compare each member.
|
||||
if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
|
||||
}
|
||||
}
|
||||
// Ensure that both objects contain the same number of properties.
|
||||
if (result) {
|
||||
for (key in b) {
|
||||
if (_.has(b, key) && !(size--)) break;
|
||||
}
|
||||
result = !size;
|
||||
}
|
||||
}
|
||||
// Remove the first object from the stack of traversed objects.
|
||||
stack.pop();
|
||||
return result;
|
||||
}
|
||||
|
||||
// Perform a deep comparison to check if two objects are equal.
|
||||
_.isEqual = function(a, b) {
|
||||
return eq(a, b, []);
|
||||
};
|
||||
|
||||
// Is a given array, string, or object empty?
|
||||
// An "empty" object has no enumerable own-properties.
|
||||
_.isEmpty = function(obj) {
|
||||
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
|
||||
for (var key in obj) if (_.has(obj, key)) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
// Is a given value a DOM element?
|
||||
_.isElement = function(obj) {
|
||||
return !!(obj && obj.nodeType == 1);
|
||||
};
|
||||
|
||||
// Is a given value an array?
|
||||
// Delegates to ECMA5's native Array.isArray
|
||||
_.isArray = nativeIsArray || function(obj) {
|
||||
return toString.call(obj) == '[object Array]';
|
||||
};
|
||||
|
||||
// Is a given variable an object?
|
||||
_.isObject = function(obj) {
|
||||
return obj === Object(obj);
|
||||
};
|
||||
|
||||
// Is a given variable an arguments object?
|
||||
_.isArguments = function(obj) {
|
||||
return toString.call(obj) == '[object Arguments]';
|
||||
};
|
||||
if (!_.isArguments(arguments)) {
|
||||
_.isArguments = function(obj) {
|
||||
return !!(obj && _.has(obj, 'callee'));
|
||||
};
|
||||
}
|
||||
|
||||
// Is a given value a function?
|
||||
_.isFunction = function(obj) {
|
||||
return toString.call(obj) == '[object Function]';
|
||||
};
|
||||
|
||||
// Is a given value a string?
|
||||
_.isString = function(obj) {
|
||||
return toString.call(obj) == '[object String]';
|
||||
};
|
||||
|
||||
// Is a given value a number?
|
||||
_.isNumber = function(obj) {
|
||||
return toString.call(obj) == '[object Number]';
|
||||
};
|
||||
|
||||
// Is the given value `NaN`?
|
||||
_.isNaN = function(obj) {
|
||||
// `NaN` is the only value for which `===` is not reflexive.
|
||||
return obj !== obj;
|
||||
};
|
||||
|
||||
// Is a given value a boolean?
|
||||
_.isBoolean = function(obj) {
|
||||
return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
|
||||
};
|
||||
|
||||
// Is a given value a date?
|
||||
_.isDate = function(obj) {
|
||||
return toString.call(obj) == '[object Date]';
|
||||
};
|
||||
|
||||
// Is the given value a regular expression?
|
||||
_.isRegExp = function(obj) {
|
||||
return toString.call(obj) == '[object RegExp]';
|
||||
};
|
||||
|
||||
// Is a given value equal to null?
|
||||
_.isNull = function(obj) {
|
||||
return obj === null;
|
||||
};
|
||||
|
||||
// Is a given variable undefined?
|
||||
_.isUndefined = function(obj) {
|
||||
return obj === void 0;
|
||||
};
|
||||
|
||||
// Has own property?
|
||||
_.has = function(obj, key) {
|
||||
return hasOwnProperty.call(obj, key);
|
||||
};
|
||||
|
||||
// Utility Functions
|
||||
// -----------------
|
||||
|
||||
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
|
||||
// previous owner. Returns a reference to the Underscore object.
|
||||
_.noConflict = function() {
|
||||
root._ = previousUnderscore;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Keep the identity function around for default iterators.
|
||||
_.identity = function(value) {
|
||||
return value;
|
||||
};
|
||||
|
||||
// Run a function **n** times.
|
||||
_.times = function (n, iterator, context) {
|
||||
for (var i = 0; i < n; i++) iterator.call(context, i);
|
||||
};
|
||||
|
||||
// Escape a string for HTML interpolation.
|
||||
_.escape = function(string) {
|
||||
return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
|
||||
};
|
||||
|
||||
// Add your own custom functions to the Underscore object, ensuring that
|
||||
// they're correctly added to the OOP wrapper as well.
|
||||
_.mixin = function(obj) {
|
||||
each(_.functions(obj), function(name){
|
||||
addToWrapper(name, _[name] = obj[name]);
|
||||
});
|
||||
};
|
||||
|
||||
// Generate a unique integer id (unique within the entire client session).
|
||||
// Useful for temporary DOM ids.
|
||||
var idCounter = 0;
|
||||
_.uniqueId = function(prefix) {
|
||||
var id = idCounter++;
|
||||
return prefix ? prefix + id : id;
|
||||
};
|
||||
|
||||
// By default, Underscore uses ERB-style template delimiters, change the
|
||||
// following template settings to use alternative delimiters.
|
||||
_.templateSettings = {
|
||||
evaluate : /<%([\s\S]+?)%>/g,
|
||||
interpolate : /<%=([\s\S]+?)%>/g,
|
||||
escape : /<%-([\s\S]+?)%>/g
|
||||
};
|
||||
|
||||
// When customizing `templateSettings`, if you don't want to define an
|
||||
// interpolation, evaluation or escaping regex, we need one that is
|
||||
// guaranteed not to match.
|
||||
var noMatch = /.^/;
|
||||
|
||||
// Within an interpolation, evaluation, or escaping, remove HTML escaping
|
||||
// that had been previously added.
|
||||
var unescape = function(code) {
|
||||
return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
|
||||
};
|
||||
|
||||
// JavaScript micro-templating, similar to John Resig's implementation.
|
||||
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||||
// and correctly escapes quotes within interpolated code.
|
||||
_.template = function(str, data) {
|
||||
var c = _.templateSettings;
|
||||
var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
|
||||
'with(obj||{}){__p.push(\'' +
|
||||
str.replace(/\\/g, '\\\\')
|
||||
.replace(/'/g, "\\'")
|
||||
.replace(c.escape || noMatch, function(match, code) {
|
||||
return "',_.escape(" + unescape(code) + "),'";
|
||||
})
|
||||
.replace(c.interpolate || noMatch, function(match, code) {
|
||||
return "'," + unescape(code) + ",'";
|
||||
})
|
||||
.replace(c.evaluate || noMatch, function(match, code) {
|
||||
return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
|
||||
})
|
||||
.replace(/\r/g, '\\r')
|
||||
.replace(/\n/g, '\\n')
|
||||
.replace(/\t/g, '\\t')
|
||||
+ "');}return __p.join('');";
|
||||
var func = new Function('obj', '_', tmpl);
|
||||
if (data) return func(data, _);
|
||||
return function(data) {
|
||||
return func.call(this, data, _);
|
||||
};
|
||||
};
|
||||
|
||||
// Add a "chain" function, which will delegate to the wrapper.
|
||||
_.chain = function(obj) {
|
||||
return _(obj).chain();
|
||||
};
|
||||
|
||||
// The OOP Wrapper
|
||||
// ---------------
|
||||
|
||||
// If Underscore is called as a function, it returns a wrapped object that
|
||||
// can be used OO-style. This wrapper holds altered versions of all the
|
||||
// underscore functions. Wrapped objects may be chained.
|
||||
var wrapper = function(obj) { this._wrapped = obj; };
|
||||
|
||||
// Expose `wrapper.prototype` as `_.prototype`
|
||||
_.prototype = wrapper.prototype;
|
||||
|
||||
// Helper function to continue chaining intermediate results.
|
||||
var result = function(obj, chain) {
|
||||
return chain ? _(obj).chain() : obj;
|
||||
};
|
||||
|
||||
// A method to easily add functions to the OOP wrapper.
|
||||
var addToWrapper = function(name, func) {
|
||||
wrapper.prototype[name] = function() {
|
||||
var args = slice.call(arguments);
|
||||
unshift.call(args, this._wrapped);
|
||||
return result(func.apply(_, args), this._chain);
|
||||
};
|
||||
};
|
||||
|
||||
// Add all of the Underscore functions to the wrapper object.
|
||||
_.mixin(_);
|
||||
|
||||
// Add all mutator Array functions to the wrapper.
|
||||
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
||||
var method = ArrayProto[name];
|
||||
wrapper.prototype[name] = function() {
|
||||
var wrapped = this._wrapped;
|
||||
method.apply(wrapped, arguments);
|
||||
var length = wrapped.length;
|
||||
if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
|
||||
return result(wrapped, this._chain);
|
||||
};
|
||||
});
|
||||
|
||||
// Add all accessor Array functions to the wrapper.
|
||||
each(['concat', 'join', 'slice'], function(name) {
|
||||
var method = ArrayProto[name];
|
||||
wrapper.prototype[name] = function() {
|
||||
return result(method.apply(this._wrapped, arguments), this._chain);
|
||||
};
|
||||
});
|
||||
|
||||
// Start chaining a wrapped Underscore object.
|
||||
wrapper.prototype.chain = function() {
|
||||
this._chain = true;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Extracts the result from a wrapped and chained object.
|
||||
wrapper.prototype.value = function() {
|
||||
return this._wrapped;
|
||||
};
|
||||
|
||||
}).call(this);
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,577 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Index — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
<script src="_static/jquery.js"></script>
|
||||
<script src="_static/underscore.js"></script>
|
||||
<script src="_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="#" />
|
||||
<link rel="search" title="Search" href="search.html" />
|
||||
|
||||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
|
||||
<h1 id="index">Index</h1>
|
||||
|
||||
<div class="genindex-jumpbox">
|
||||
<a href="#A"><strong>A</strong></a>
|
||||
| <a href="#B"><strong>B</strong></a>
|
||||
| <a href="#C"><strong>C</strong></a>
|
||||
| <a href="#D"><strong>D</strong></a>
|
||||
| <a href="#E"><strong>E</strong></a>
|
||||
| <a href="#F"><strong>F</strong></a>
|
||||
| <a href="#G"><strong>G</strong></a>
|
||||
| <a href="#H"><strong>H</strong></a>
|
||||
| <a href="#I"><strong>I</strong></a>
|
||||
| <a href="#J"><strong>J</strong></a>
|
||||
| <a href="#L"><strong>L</strong></a>
|
||||
| <a href="#M"><strong>M</strong></a>
|
||||
| <a href="#O"><strong>O</strong></a>
|
||||
| <a href="#P"><strong>P</strong></a>
|
||||
| <a href="#R"><strong>R</strong></a>
|
||||
| <a href="#S"><strong>S</strong></a>
|
||||
| <a href="#T"><strong>T</strong></a>
|
||||
| <a href="#U"><strong>U</strong></a>
|
||||
| <a href="#V"><strong>V</strong></a>
|
||||
| <a href="#W"><strong>W</strong></a>
|
||||
| <a href="#X"><strong>X</strong></a>
|
||||
| <a href="#Z"><strong>Z</strong></a>
|
||||
|
||||
</div>
|
||||
<h2 id="A">A</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.add_aliases">add_aliases() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.app1">app1() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.app2">app2() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.app3">app3() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="B">B</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.b">b() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.BinaryLogicWrapper">BinaryLogicWrapper() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.BinaryMathWrapper">BinaryMathWrapper() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.branch">branch() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="C">C</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.utils.generated_library.ccons">ccons() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.choice">choice() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.clear">clear() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.cmp_">cmp_() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="stack.html#joy.utils.stack.concat">concat() (in module joy.utils.stack)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.concat_">concat_() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.cond">cond() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.cons">cons() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="D">D</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.Def">Def (class in joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.dip">dip() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.dipd">dipd() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.dipdd">dipdd() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.disenstacken">disenstacken() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.divmod_">divmod_() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="stack.html#joy.utils.stack.dnd">dnd() (in module joy.utils.stack)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.drop">drop() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.dup">dup() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.dupd">dupd() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.dupdd">dupdd() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.dupdip">dupdip() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="E">E</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="stack.html#joy.utils.stack.expression_to_string">expression_to_string() (in module joy.utils.stack)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="F">F</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.utils.generated_library.first">first() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.first_two">first_two() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.floor">floor() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.fourth">fourth() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.FunctionWrapper">FunctionWrapper() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="G">G</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.gcd2">gcd2() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.genrec">genrec() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.getitem">getitem() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="pretty.html#joy.utils.pretty_print.TracePrinter.go">go() (joy.utils.pretty_print.TracePrinter method)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="H">H</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.help_">help_() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="I">I</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.i">i() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.id_">id_() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.ifte">ifte() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.ii">ii() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.infra">infra() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.initialize">initialize() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.inscribe">inscribe() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.inscribe_">inscribe_() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="joy.html#joy.joy.interp">interp() (in module joy.joy)</a>
|
||||
</li>
|
||||
<li><a href="stack.html#joy.utils.stack.iter_stack">iter_stack() (in module joy.utils.stack)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="J">J</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="joy.html#joy.joy.joy">joy() (in module joy.joy)</a>
|
||||
</li>
|
||||
<li>
|
||||
joy.joy
|
||||
|
||||
<ul>
|
||||
<li><a href="joy.html#module-joy.joy">module</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
joy.library
|
||||
|
||||
<ul>
|
||||
<li><a href="library.html#module-joy.library">module</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
joy.parser
|
||||
|
||||
<ul>
|
||||
<li><a href="parser.html#module-joy.parser">module</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li>
|
||||
joy.utils.generated_library
|
||||
|
||||
<ul>
|
||||
<li><a href="library.html#module-joy.utils.generated_library">module</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
joy.utils.pretty_print
|
||||
|
||||
<ul>
|
||||
<li><a href="pretty.html#module-joy.utils.pretty_print">module</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
<li>
|
||||
joy.utils.stack
|
||||
|
||||
<ul>
|
||||
<li><a href="stack.html#module-joy.utils.stack">module</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="L">L</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="stack.html#joy.utils.stack.list_to_stack">list_to_stack() (in module joy.utils.stack)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.loop">loop() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="M">M</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.map_">map_() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.max_">max_() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.min_">min_() (in module joy.library)</a>
|
||||
</li>
|
||||
<li>
|
||||
module
|
||||
|
||||
<ul>
|
||||
<li><a href="joy.html#module-joy.joy">joy.joy</a>
|
||||
</li>
|
||||
<li><a href="library.html#module-joy.library">joy.library</a>
|
||||
</li>
|
||||
<li><a href="parser.html#module-joy.parser">joy.parser</a>
|
||||
</li>
|
||||
<li><a href="library.html#module-joy.utils.generated_library">joy.utils.generated_library</a>
|
||||
</li>
|
||||
<li><a href="pretty.html#module-joy.utils.pretty_print">joy.utils.pretty_print</a>
|
||||
</li>
|
||||
<li><a href="stack.html#module-joy.utils.stack">joy.utils.stack</a>
|
||||
</li>
|
||||
</ul></li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="O">O</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.utils.generated_library.over">over() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="P">P</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="parser.html#joy.parser.ParseError">ParseError</a>
|
||||
</li>
|
||||
<li><a href="stack.html#joy.utils.stack.pick">pick() (in module joy.utils.stack)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.pm">pm() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.pop">pop() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.popd">popd() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.utils.generated_library.popdd">popdd() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.popop">popop() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.popopd">popopd() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.popopdd">popopdd() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.pred">pred() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.primrec">primrec() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="R">R</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.remove">remove() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="joy.html#joy.joy.repl">repl() (in module joy.joy)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.rest">rest() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.reverse">reverse() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.utils.generated_library.rolldown">rolldown() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.rollup">rollup() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.rrest">rrest() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="joy.html#joy.joy.run">run() (in module joy.joy)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="S">S</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.utils.generated_library.second">second() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.select">select() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.sharing">sharing() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.shunt">shunt() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.SimpleFunctionWrapper">SimpleFunctionWrapper() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.sort_">sort_() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.sqrt">sqrt() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.stack">stack() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="stack.html#joy.utils.stack.stack_to_string">stack_to_string() (in module joy.utils.stack)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.step">step() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.stuncons">stuncons() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.stununcons">stununcons() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.succ">succ() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.sum_">sum_() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.swaack">swaack() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.swap">swap() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.swons">swons() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="parser.html#joy.parser.Symbol">Symbol (class in joy.parser)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="T">T</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.take">take() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="parser.html#joy.parser.text_to_expression">text_to_expression() (in module joy.parser)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.third">third() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.times">times() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="pretty.html#joy.utils.pretty_print.trace">trace() (in module joy.utils.pretty_print)</a>
|
||||
</li>
|
||||
<li><a href="pretty.html#joy.utils.pretty_print.TracePrinter">TracePrinter (class in joy.utils.pretty_print)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.tuck">tuck() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="U">U</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.UnaryBuiltinWrapper">UnaryBuiltinWrapper() (in module joy.library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.uncons">uncons() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.library.unique">unique() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.utils.generated_library.unit">unit() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
<li><a href="joy.html#joy.joy.UnknownSymbolError">UnknownSymbolError</a>
|
||||
</li>
|
||||
<li><a href="library.html#joy.utils.generated_library.unswons">unswons() (in module joy.utils.generated_library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="V">V</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="pretty.html#joy.utils.pretty_print.TracePrinter.viewer">viewer() (joy.utils.pretty_print.TracePrinter method)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.void">void() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="W">W</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.warranty">warranty() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.words">words() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="X">X</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.x">x() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
<h2 id="Z">Z</h2>
|
||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||
<td style="width: 33%; vertical-align: top;"><ul>
|
||||
<li><a href="library.html#joy.library.zip_">zip_() (in module joy.library)</a>
|
||||
</li>
|
||||
</ul></td>
|
||||
</tr></table>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="notebooks/Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="notebooks/index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="index.html">Documentation overview</a><ul>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,263 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Thun 0.4.1 Documentation — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
<script src="_static/jquery.js"></script>
|
||||
<script src="_static/underscore.js"></script>
|
||||
<script src="_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="genindex.html" />
|
||||
<link rel="search" title="Search" href="search.html" />
|
||||
<link rel="next" title="Thun: Joy in Python" href="notebooks/Intro.html" />
|
||||
|
||||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="thun-release-documentation">
|
||||
<h1>Thun 0.4.1 Documentation<a class="headerlink" href="#thun-release-documentation" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Thun is dialect of Joy written in Python.</p>
|
||||
<p><a class="reference external" href="https://en.wikipedia.org/wiki/Joy_(programming_language)">Joy</a> is a programming language created by Manfred von Thun that is easy to
|
||||
use and understand and has many other nice properties. This Python
|
||||
package implements an interpreter for a dialect of Joy that attempts to
|
||||
stay very close to the spirit of Joy but does not precisely match the
|
||||
behaviour of the original version(s) written in C. The main difference
|
||||
between Thun and the originals, other than being written in Python, is
|
||||
that it works by the “Continuation-Passing Style”.</p>
|
||||
<p>Joy is:</p>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference external" href="https://en.wikipedia.org/wiki/Purely_functional_programming">Purely Functional</a></p></li>
|
||||
<li><p><a class="reference external" href="https://en.wikipedia.org/wiki/Stack-oriented_programming_language">Stack-based</a></p></li>
|
||||
<li><p><a class="reference external" href="https://en.wikipedia.org/wiki/Concatenative_programming_language">Concatinative</a> ( See also <a class="reference external" href="http://www.concatenative.org/wiki/view/Concatenative%20language">concatenative.org</a>)</p></li>
|
||||
<li><p><a class="reference internal" href="notebooks/Categorical.html"><span class="doc">Categorical</span></a></p></li>
|
||||
</ul>
|
||||
<p>I hope that this package is useful in the sense that it provides an
|
||||
additional joy interpreter (the binary in the archive from La Trobe seems
|
||||
to run just fine on my modern Linux machine!) But I also hope that you
|
||||
can read and understand the Python code and play with the implementation
|
||||
itself.</p>
|
||||
<section id="example-code">
|
||||
<h2>Example Code<a class="headerlink" href="#example-code" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Here is an example of Joy code:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>[[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>It might seem unreadable but with a little familiarity it becomes just as
|
||||
legible as any other notation. Some layout helps:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>[ [[abs] ii <=]
|
||||
[
|
||||
[<>] [pop !-] ||
|
||||
] &&
|
||||
]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This function accepts two integers on the stack and increments or
|
||||
decrements one of them such that the new pair of numbers is the next
|
||||
coordinate pair in a square spiral (like the kind used to construct an
|
||||
<a class="reference external" href="https://en.wikipedia.org/wiki/Ulam_spiral">Ulam Spiral</a>). For more information see <a class="reference internal" href="notebooks/Square_Spiral.html"><span class="doc">Square Spiral Example Joy Code</span></a></p>
|
||||
</section>
|
||||
<section id="quick-start">
|
||||
<h2>Quick Start<a class="headerlink" href="#quick-start" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Install from <a class="reference external" href="https://pypi.org/project/Thun/">PyPI</a> in the usual way:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ pip install Thun
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>To start the REPL:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ python -m joy
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Continue with <a class="reference internal" href="notebooks/Intro.html"><span class="doc">the introduction</span></a>.</p>
|
||||
</section>
|
||||
<section id="project-hosted-on-osdn">
|
||||
<h2>Project Hosted on <a class="reference external" href="https://osdn.net/projects/joypy/">OSDN</a><a class="headerlink" href="#project-hosted-on-osdn" title="Permalink to this headline">¶</a></h2>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference external" href="https://osdn.net/projects/joypy/scm/git/Thun/">Source Repository</a> (<a class="reference external" href="https://github.com/calroc/Thun">mirror</a>)</p></li>
|
||||
<li><p><a class="reference external" href="https://todo.sr.ht/~sforman/thun-der">Bug tracker</a> (<a class="reference external" href="https://osdn.net/projects/joypy/ticket/">old tracker</a>)</p></li>
|
||||
<li><p><a class="reference external" href="https://osdn.net/projects/joypy/forums/">Forums</a></p></li>
|
||||
<li><p><a class="reference external" href="https://osdn.net/projects/joypy/lists/">Mailing list</a></p></li>
|
||||
</ul>
|
||||
</section>
|
||||
<section id="information-on-the-joy-language">
|
||||
<h2>Information on the Joy language<a class="headerlink" href="#information-on-the-joy-language" title="Permalink to this headline">¶</a></h2>
|
||||
<p>See <a class="reference external" href="https://en.wikipedia.org/wiki/Joy_(programming_language)">the Wikipedia article</a> and <a class="reference external" href="http://www.kevinalbrecht.com/code/joy-mirror/index.html">Kevin Albrecht’s mirror of Manfred von Thun’s original website for the Joy Programming Language</a> for more information on the Joy language.</p>
|
||||
<p>The best source (no pun intended) for learning about Joy is the
|
||||
information made available at the website of La Trobe University (see the
|
||||
mirror link above) which contains source code for the
|
||||
original C interpreter, Joy language source code for various functions,
|
||||
and a great deal of fascinating material mostly written by Von Thun on
|
||||
Joy and its deeper facets as well as how to program in it and several
|
||||
interesting aspects. It’s quite a treasure trove.</p>
|
||||
</section>
|
||||
<section id="documentation-on-thun-dialect">
|
||||
<h2>Documentation on Thun Dialect<a class="headerlink" href="#documentation-on-thun-dialect" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The following is specific information for this dialect of Joy.</p>
|
||||
<div class="toctree-wrapper compound">
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="notebooks/Intro.html">Thun: Joy in Python</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Intro.html#read-eval-print-loop-repl">Read-Eval-Print Loop (REPL)</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Intro.html#the-stack">The Stack</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Intro.html#purely-functional-datastructures">Purely Functional Datastructures</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Intro.html#the-joy-function">The <code class="docutils literal notranslate"><span class="pre">joy()</span></code> function</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Intro.html#parser">Parser</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Intro.html#library">Library</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="joy.html">Joy Interpreter</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="joy.html#module-joy.joy"><code class="docutils literal notranslate"><span class="pre">joy.joy</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="stack.html">Stack or Quote or Sequence or List…</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="stack.html#module-joy.utils.stack"><code class="docutils literal notranslate"><span class="pre">joy.utils.stack</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="parser.html">Parsing Text into Joy Expressions</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="parser.html#module-joy.parser"><code class="docutils literal notranslate"><span class="pre">joy.parser</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="parser.html#parser-internals">Parser Internals</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="pretty.html">Tracing Joy Execution</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="pretty.html#module-joy.utils.pretty_print"><code class="docutils literal notranslate"><span class="pre">joy.utils.pretty_print</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="library.html">Function Reference</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="library.html#module-joy.library"><code class="docutils literal notranslate"><span class="pre">joy.library</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="library.html#module-joy.utils.generated_library">Auto-generated Functions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="lib.html">Functions Grouped by, er, Function with Examples</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="lib.html#stack-chatter">Stack Chatter</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="lib.html#list-words">List words</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="lib.html#math-words">Math words</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="lib.html#logic-and-comparison">Logic and Comparison</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="lib.html#miscellaneous">Miscellaneous</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="lib.html#combinators">Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="lib.html#void"><code class="docutils literal notranslate"><span class="pre">void</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="types.html">Type Inference of Joy Expressions</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="types.html#joy-utils-types"><code class="docutils literal notranslate"><span class="pre">joy.utils.types</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="notebooks/index.html">Essays about Programming in Joy</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="notebooks/Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="indices-and-tables">
|
||||
<h1>Indices and tables<a class="headerlink" href="#indices-and-tables" title="Permalink to this headline">¶</a></h1>
|
||||
<ul class="simple">
|
||||
<li><p><a class="reference internal" href="genindex.html"><span class="std std-ref">Index</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="py-modindex.html"><span class="std std-ref">Module Index</span></a></p></li>
|
||||
<li><p><a class="reference internal" href="search.html"><span class="std std-ref">Search Page</span></a></p></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="#">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul>
|
||||
<li class="toctree-l1"><a class="reference internal" href="notebooks/Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="notebooks/index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="#">Documentation overview</a><ul>
|
||||
<li>Next: <a href="notebooks/Intro.html" title="next chapter">Thun: Joy in Python</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Joy Interpreter — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
|
||||
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
|
||||
<script src="_static/jquery.js"></script>
|
||||
<script src="_static/underscore.js"></script>
|
||||
<script src="_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="genindex.html" />
|
||||
<link rel="search" title="Search" href="search.html" />
|
||||
<link rel="next" title="Stack or Quote or Sequence or List…" href="stack.html" />
|
||||
<link rel="prev" title="Thun: Joy in Python" href="notebooks/Intro.html" />
|
||||
|
||||
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="joy-interpreter">
|
||||
<h1>Joy Interpreter<a class="headerlink" href="#joy-interpreter" title="Permalink to this headline">¶</a></h1>
|
||||
<section id="module-joy.joy">
|
||||
<span id="joy-joy"></span><h2><code class="docutils literal notranslate"><span class="pre">joy.joy</span></code><a class="headerlink" href="#module-joy.joy" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This module implements an interpreter for a dialect of Joy that
|
||||
attempts to stay very close to the spirit of Joy but does not precisely
|
||||
match the behaviour of the original version(s) written in C.</p>
|
||||
<dl class="py exception">
|
||||
<dt class="sig sig-object py" id="joy.joy.UnknownSymbolError">
|
||||
<em class="property"><span class="pre">exception</span><span class="w"> </span></em><span class="sig-prename descclassname"><span class="pre">joy.joy.</span></span><span class="sig-name descname"><span class="pre">UnknownSymbolError</span></span><a class="reference internal" href="_modules/joy/joy.html#UnknownSymbolError"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#joy.joy.UnknownSymbolError" title="Permalink to this definition">¶</a></dt>
|
||||
<dd></dd></dl>
|
||||
|
||||
<dl class="py function">
|
||||
<dt class="sig sig-object py" id="joy.joy.interp">
|
||||
<span class="sig-prename descclassname"><span class="pre">joy.joy.</span></span><span class="sig-name descname"><span class="pre">interp</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">stack</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">()</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dictionary</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/joy.html#interp"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#joy.joy.interp" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Simple REPL with no extra output, suitable for use in scripts.</p>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py function">
|
||||
<dt class="sig sig-object py" id="joy.joy.joy">
|
||||
<span class="sig-prename descclassname"><span class="pre">joy.joy.</span></span><span class="sig-name descname"><span class="pre">joy</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">stack</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">expression</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dictionary</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">viewer</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/joy.html#joy"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#joy.joy.joy" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Evaluate a Joy expression on a stack.</p>
|
||||
<p>This function iterates through a sequence of terms which are either
|
||||
literals (strings, numbers, sequences of terms) or function symbols.
|
||||
Literals are put onto the stack and functions are looked up in the
|
||||
dictionary and executed.</p>
|
||||
<p>The viewer is a function that is called with the stack and expression
|
||||
on every iteration, its return value is ignored.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Parameters</dt>
|
||||
<dd class="field-odd"><ul class="simple">
|
||||
<li><p><strong>stack</strong> (<em>stack</em>) – The stack.</p></li>
|
||||
<li><p><strong>expression</strong> (<em>stack</em>) – The expression to evaluate.</p></li>
|
||||
<li><p><strong>dictionary</strong> (<em>dict</em>) – A <code class="docutils literal notranslate"><span class="pre">dict</span></code> mapping names to Joy functions.</p></li>
|
||||
<li><p><strong>viewer</strong> (<em>function</em>) – Optional viewer function.</p></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="field-even">Return type</dt>
|
||||
<dd class="field-even"><p>(stack, (), dictionary)</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py function">
|
||||
<dt class="sig sig-object py" id="joy.joy.repl">
|
||||
<span class="sig-prename descclassname"><span class="pre">joy.joy.</span></span><span class="sig-name descname"><span class="pre">repl</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">stack</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">()</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dictionary</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/joy.html#repl"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#joy.joy.repl" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Read-Evaluate-Print Loop</p>
|
||||
<p>Accept input and run it on the stack, loop.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Parameters</dt>
|
||||
<dd class="field-odd"><ul class="simple">
|
||||
<li><p><strong>stack</strong> (<em>stack</em>) – The stack.</p></li>
|
||||
<li><p><strong>dictionary</strong> (<em>dict</em>) – A <code class="docutils literal notranslate"><span class="pre">dict</span></code> mapping names to Joy functions.</p></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="field-even">Return type</dt>
|
||||
<dd class="field-even"><p>stack</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
<dl class="py function">
|
||||
<dt class="sig sig-object py" id="joy.joy.run">
|
||||
<span class="sig-prename descclassname"><span class="pre">joy.joy.</span></span><span class="sig-name descname"><span class="pre">run</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">text</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">stack</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">dictionary</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">viewer</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="reference internal" href="_modules/joy/joy.html#run"><span class="viewcode-link"><span class="pre">[source]</span></span></a><a class="headerlink" href="#joy.joy.run" title="Permalink to this definition">¶</a></dt>
|
||||
<dd><p>Return the stack resulting from running the Joy code text on the stack.</p>
|
||||
<dl class="field-list simple">
|
||||
<dt class="field-odd">Parameters</dt>
|
||||
<dd class="field-odd"><ul class="simple">
|
||||
<li><p><strong>text</strong> (<em>str</em>) – Joy code.</p></li>
|
||||
<li><p><strong>stack</strong> (<em>stack</em>) – The stack.</p></li>
|
||||
<li><p><strong>dictionary</strong> (<em>dict</em>) – A <code class="docutils literal notranslate"><span class="pre">dict</span></code> mapping names to Joy functions.</p></li>
|
||||
<li><p><strong>viewer</strong> (<em>function</em>) – Optional viewer function.</p></li>
|
||||
</ul>
|
||||
</dd>
|
||||
<dt class="field-even">Return type</dt>
|
||||
<dd class="field-even"><p>(stack, (), dictionary)</p>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd></dl>
|
||||
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="notebooks/Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">Joy Interpreter</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#module-joy.joy"><code class="docutils literal notranslate"><span class="pre">joy.joy</span></code></a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="notebooks/index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="notebooks/Intro.html" title="previous chapter">Thun: Joy in Python</a></li>
|
||||
<li>Next: <a href="stack.html" title="next chapter">Stack or Quote or Sequence or List…</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -1,138 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Categorical Programming — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="The Four Fundamental Operations of Definite Action" href="The_Four_Operations.html" />
|
||||
<link rel="prev" title="No Updates" href="NoUpdates.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="categorical-programming">
|
||||
<h1>Categorical Programming<a class="headerlink" href="#categorical-programming" title="Permalink to this headline">¶</a></h1>
|
||||
<p>DRAFT</p>
|
||||
<p><a class="reference external" href="https://en.wikipedia.org/wiki/Category_theory">Categorical</a></p>
|
||||
<p>In Manfred von Thun’s article <a class="reference external" href="http://www.kevinalbrecht.com/code/joy-mirror/j08cnt.html">Joy compared with other functional languages</a> he asks, “Could the language of categories be used for writing programs? Any lambda expression can be translated into a categorical expression, so the language of categories is expressively complete. But this does not make it a suitable language for writing programs. As it stands it is a very low-level language.”</p>
|
||||
<p>In <a class="reference external" href="http://conal.net/papers/compiling-to-categories/">Compiling to categories</a> Conal Elliott give a taste of what this might mean.</p>
|
||||
<blockquote>
|
||||
<div><p>It is well-known that the simply typed lambda-calculus is modeled by any cartesian closed category (CCC). This correspondence suggests giving typed functional programs a variety of interpretations, each corresponding to a different category. A convenient way to realize this idea is as a collection of meaning-preserving transformations added to an existing compiler, such as GHC for Haskell. This paper describes such an implementation and demonstrates its use for a variety of interpretations including hardware circuits, automatic differentiation, incremental computation, and interval analysis. Each such interpretation is a category easily defined in Haskell (outside of the compiler). The general technique appears to provide a compelling alternative to deeply embedded domain-specific languages.</p>
|
||||
</div></blockquote>
|
||||
<p>What he’s doing is translating lambda forms into a kind of “point-free” style that is very close to Joy code (although more verbose) and then showing how to instantiate that code over different categories to get several different kinds of program out of the same code.</p>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="NoUpdates.html" title="previous chapter">No Updates</a></li>
|
||||
<li>Next: <a href="The_Four_Operations.html" title="next chapter">The Four Fundamental Operations of Definite Action</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,935 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>∂RE — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="prev" title="The Four Fundamental Operations of Definite Action" href="The_Four_Operations.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="re">
|
||||
<h1>∂RE<a class="headerlink" href="#re" title="Permalink to this headline">¶</a></h1>
|
||||
<section id="brzozowskis-derivatives-of-regular-expressions">
|
||||
<h2>Brzozowski’s Derivatives of Regular Expressions<a class="headerlink" href="#brzozowskis-derivatives-of-regular-expressions" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Legend:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>∧ intersection
|
||||
∨ union
|
||||
∘ concatenation (see below)
|
||||
¬ complement
|
||||
ϕ empty set (aka ∅)
|
||||
λ singleton set containing just the empty string
|
||||
I set of all letters in alphabet
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Derivative of a set <code class="docutils literal notranslate"><span class="pre">R</span></code> of strings and a string <code class="docutils literal notranslate"><span class="pre">a</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>∂a(R)
|
||||
|
||||
∂a(a) → λ
|
||||
∂a(λ) → ϕ
|
||||
∂a(ϕ) → ϕ
|
||||
∂a(¬a) → ϕ
|
||||
∂a(R*) → ∂a(R)∘R*
|
||||
∂a(¬R) → ¬∂a(R)
|
||||
∂a(R∘S) → ∂a(R)∘S ∨ δ(R)∘∂a(S)
|
||||
∂a(R ∧ S) → ∂a(R) ∧ ∂a(S)
|
||||
∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
|
||||
∂ab(R) = ∂b(∂a(R))
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Auxiliary predicate function <code class="docutils literal notranslate"><span class="pre">δ</span></code> (I call it <code class="docutils literal notranslate"><span class="pre">nully</span></code>) returns either
|
||||
<code class="docutils literal notranslate"><span class="pre">λ</span></code> if <code class="docutils literal notranslate"><span class="pre">λ</span> <span class="pre">⊆</span> <span class="pre">R</span></code> or <code class="docutils literal notranslate"><span class="pre">ϕ</span></code> otherwise:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>δ(a) → ϕ
|
||||
δ(λ) → λ
|
||||
δ(ϕ) → ϕ
|
||||
δ(R*) → λ
|
||||
δ(¬R) δ(R)≟ϕ → λ
|
||||
δ(¬R) δ(R)≟λ → ϕ
|
||||
δ(R∘S) → δ(R) ∧ δ(S)
|
||||
δ(R ∧ S) → δ(R) ∧ δ(S)
|
||||
δ(R ∨ S) → δ(R) ∨ δ(S)
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Some rules we will use later for “compaction”:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>R ∧ ϕ = ϕ ∧ R = ϕ
|
||||
|
||||
R ∧ I = I ∧ R = R
|
||||
|
||||
R ∨ ϕ = ϕ ∨ R = R
|
||||
|
||||
R ∨ I = I ∨ R = I
|
||||
|
||||
R∘ϕ = ϕ∘R = ϕ
|
||||
|
||||
R∘λ = λ∘R = R
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Concatination of sets: for two sets A and B the set A∘B is defined as:</p>
|
||||
<p>{a∘b for a in A for b in B}</p>
|
||||
<p>E.g.:</p>
|
||||
<p>{‘a’, ‘b’}∘{‘c’, ‘d’} → {‘ac’, ‘ad’, ‘bc’, ‘bd’}</p>
|
||||
</section>
|
||||
<section id="implementation">
|
||||
<h2>Implementation<a class="headerlink" href="#implementation" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>from functools import partial as curry
|
||||
from itertools import product
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="and">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">ϕ</span></code> and <code class="docutils literal notranslate"><span class="pre">λ</span></code><a class="headerlink" href="#and" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The empty set and the set of just the empty string.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>phi = frozenset() # ϕ
|
||||
y = frozenset({''}) # λ
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="two-letter-alphabet">
|
||||
<h3>Two-letter Alphabet<a class="headerlink" href="#two-letter-alphabet" title="Permalink to this headline">¶</a></h3>
|
||||
<p>I’m only going to use two symbols (at first) becaase this is enough to
|
||||
illustrate the algorithm and because you can represent any other
|
||||
alphabet with two symbols (if you had to.)</p>
|
||||
<p>I chose the names <code class="docutils literal notranslate"><span class="pre">O</span></code> and <code class="docutils literal notranslate"><span class="pre">l</span></code> (uppercase “o” and lowercase “L”) to
|
||||
look like <code class="docutils literal notranslate"><span class="pre">0</span></code> and <code class="docutils literal notranslate"><span class="pre">1</span></code> (zero and one) respectively.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>syms = O, l = frozenset({'0'}), frozenset({'1'})
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="representing-regular-expressions">
|
||||
<h3>Representing Regular Expressions<a class="headerlink" href="#representing-regular-expressions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>To represent REs in Python I’m going to use tagged tuples. A <em>regular
|
||||
expression</em> is one of:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">O</span>
|
||||
<span class="n">l</span>
|
||||
<span class="p">(</span><span class="n">KSTAR</span><span class="p">,</span> <span class="n">R</span><span class="p">)</span>
|
||||
<span class="p">(</span><span class="n">NOT</span><span class="p">,</span> <span class="n">R</span><span class="p">)</span>
|
||||
<span class="p">(</span><span class="n">AND</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">S</span><span class="p">)</span>
|
||||
<span class="p">(</span><span class="n">CONS</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">S</span><span class="p">)</span>
|
||||
<span class="p">(</span><span class="n">OR</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">S</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Where <code class="docutils literal notranslate"><span class="pre">R</span></code> and <code class="docutils literal notranslate"><span class="pre">S</span></code> stand for <em>regular expressions</em>.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>AND, CONS, KSTAR, NOT, OR = 'and cons * not or'.split() # Tags are just strings.
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Because they are formed of <code class="docutils literal notranslate"><span class="pre">frozenset</span></code>, <code class="docutils literal notranslate"><span class="pre">tuple</span></code> and <code class="docutils literal notranslate"><span class="pre">str</span></code> objects
|
||||
only, these datastructures are immutable.</p>
|
||||
</section>
|
||||
<section id="string-representation-of-re-datastructures">
|
||||
<h3>String Representation of RE Datastructures<a class="headerlink" href="#string-representation-of-re-datastructures" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>def stringy(re):
|
||||
'''
|
||||
Return a nice string repr for a regular expression datastructure.
|
||||
'''
|
||||
if re == I: return '.'
|
||||
if re in syms: return next(iter(re))
|
||||
if re == y: return '^'
|
||||
if re == phi: return 'X'
|
||||
|
||||
assert isinstance(re, tuple), repr(re)
|
||||
tag = re[0]
|
||||
|
||||
if tag == KSTAR:
|
||||
body = stringy(re[1])
|
||||
if not body: return body
|
||||
if len(body) > 1: return '(' + body + ")*"
|
||||
return body + '*'
|
||||
|
||||
if tag == NOT:
|
||||
body = stringy(re[1])
|
||||
if not body: return body
|
||||
if len(body) > 1: return '(' + body + ")'"
|
||||
return body + "'"
|
||||
|
||||
r, s = stringy(re[1]), stringy(re[2])
|
||||
if tag == CONS: return r + s
|
||||
if tag == OR: return '%s | %s' % (r, s)
|
||||
if tag == AND: return '(%s) & (%s)' % (r, s)
|
||||
|
||||
raise ValueError
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="i">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">I</span></code><a class="headerlink" href="#i" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Match anything. Often spelled “.”</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">I</span> <span class="o">=</span> <span class="p">(</span><span class="mi">0</span><span class="o">|</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>I = (KSTAR, (OR, O, l))
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>print stringy(I)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="id1">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">(.111.)</span> <span class="pre">&</span> <span class="pre">(.01</span> <span class="pre">+</span> <span class="pre">11*)'</span></code><a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The example expression from Brzozowski:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mf">.111</span><span class="o">.</span><span class="p">)</span> <span class="o">&</span> <span class="p">(</span><span class="mf">.01</span> <span class="o">+</span> <span class="mi">11</span><span class="o">*</span><span class="p">)</span><span class="s1">'</span>
|
||||
<span class="n">a</span> <span class="o">&</span> <span class="p">(</span><span class="n">b</span> <span class="o">+</span> <span class="n">c</span><span class="p">)</span><span class="s1">'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Note that it contains one of everything.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>a = (CONS, I, (CONS, l, (CONS, l, (CONS, l, I))))
|
||||
b = (CONS, I, (CONS, O, l))
|
||||
c = (CONS, l, (KSTAR, l))
|
||||
it = (AND, a, (NOT, (OR, b, c)))
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>print stringy(it)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mf">.111</span><span class="o">.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">11</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="nully">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">nully()</span></code><a class="headerlink" href="#nully" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Let’s get that auxiliary predicate function <code class="docutils literal notranslate"><span class="pre">δ</span></code> out of the way.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>def nully(R):
|
||||
'''
|
||||
δ - Return λ if λ ⊆ R otherwise ϕ.
|
||||
'''
|
||||
|
||||
# δ(a) → ϕ
|
||||
# δ(ϕ) → ϕ
|
||||
if R in syms or R == phi:
|
||||
return phi
|
||||
|
||||
# δ(λ) → λ
|
||||
if R == y:
|
||||
return y
|
||||
|
||||
tag = R[0]
|
||||
|
||||
# δ(R*) → λ
|
||||
if tag == KSTAR:
|
||||
return y
|
||||
|
||||
# δ(¬R) δ(R)≟ϕ → λ
|
||||
# δ(¬R) δ(R)≟λ → ϕ
|
||||
if tag == NOT:
|
||||
return phi if nully(R[1]) else y
|
||||
|
||||
# δ(R∘S) → δ(R) ∧ δ(S)
|
||||
# δ(R ∧ S) → δ(R) ∧ δ(S)
|
||||
# δ(R ∨ S) → δ(R) ∨ δ(S)
|
||||
r, s = nully(R[1]), nully(R[2])
|
||||
return r & s if tag in {AND, CONS} else r | s
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="no-compaction">
|
||||
<h3>No “Compaction”<a class="headerlink" href="#no-compaction" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This is the straightforward version with no “compaction”. It works fine,
|
||||
but does waaaay too much work because the expressions grow each
|
||||
derivation.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>def D(symbol):
|
||||
|
||||
def derv(R):
|
||||
|
||||
# ∂a(a) → λ
|
||||
if R == {symbol}:
|
||||
return y
|
||||
|
||||
# ∂a(λ) → ϕ
|
||||
# ∂a(ϕ) → ϕ
|
||||
# ∂a(¬a) → ϕ
|
||||
if R == y or R == phi or R in syms:
|
||||
return phi
|
||||
|
||||
tag = R[0]
|
||||
|
||||
# ∂a(R*) → ∂a(R)∘R*
|
||||
if tag == KSTAR:
|
||||
return (CONS, derv(R[1]), R)
|
||||
|
||||
# ∂a(¬R) → ¬∂a(R)
|
||||
if tag == NOT:
|
||||
return (NOT, derv(R[1]))
|
||||
|
||||
r, s = R[1:]
|
||||
|
||||
# ∂a(R∘S) → ∂a(R)∘S ∨ δ(R)∘∂a(S)
|
||||
if tag == CONS:
|
||||
A = (CONS, derv(r), s) # A = ∂a(R)∘S
|
||||
# A ∨ δ(R) ∘ ∂a(S)
|
||||
# A ∨ λ ∘ ∂a(S) → A ∨ ∂a(S)
|
||||
# A ∨ ϕ ∘ ∂a(S) → A ∨ ϕ → A
|
||||
return (OR, A, derv(s)) if nully(r) else A
|
||||
|
||||
# ∂a(R ∧ S) → ∂a(R) ∧ ∂a(S)
|
||||
# ∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
return (tag, derv(r), derv(s))
|
||||
|
||||
return derv
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="compaction-rules">
|
||||
<h3>Compaction Rules<a class="headerlink" href="#compaction-rules" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>def _compaction_rule(relation, one, zero, a, b):
|
||||
return (
|
||||
b if a == one else # R*1 = 1*R = R
|
||||
a if b == one else
|
||||
zero if a == zero or b == zero else # R*0 = 0*R = 0
|
||||
(relation, a, b)
|
||||
)
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>An elegant symmetry.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span># R ∧ I = I ∧ R = R
|
||||
# R ∧ ϕ = ϕ ∧ R = ϕ
|
||||
_and = curry(_compaction_rule, AND, I, phi)
|
||||
|
||||
# R ∨ ϕ = ϕ ∨ R = R
|
||||
# R ∨ I = I ∨ R = I
|
||||
_or = curry(_compaction_rule, OR, phi, I)
|
||||
|
||||
# R∘λ = λ∘R = R
|
||||
# R∘ϕ = ϕ∘R = ϕ
|
||||
_cons = curry(_compaction_rule, CONS, y, phi)
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="memoizing">
|
||||
<h3>Memoizing<a class="headerlink" href="#memoizing" title="Permalink to this headline">¶</a></h3>
|
||||
<p>We can save re-processing by remembering results we have already
|
||||
computed. RE datastructures are immutable and the <code class="docutils literal notranslate"><span class="pre">derv()</span></code> functions
|
||||
are <em>pure</em> so this is fine.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>class Memo(object):
|
||||
|
||||
def __init__(self, f):
|
||||
self.f = f
|
||||
self.calls = self.hits = 0
|
||||
self.mem = {}
|
||||
|
||||
def __call__(self, key):
|
||||
self.calls += 1
|
||||
try:
|
||||
result = self.mem[key]
|
||||
self.hits += 1
|
||||
except KeyError:
|
||||
result = self.mem[key] = self.f(key)
|
||||
return result
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="with-compaction">
|
||||
<h3>With “Compaction”<a class="headerlink" href="#with-compaction" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This version uses the rules above to perform compaction. It keeps the
|
||||
expressions from growing too large.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>def D_compaction(symbol):
|
||||
|
||||
@Memo
|
||||
def derv(R):
|
||||
|
||||
# ∂a(a) → λ
|
||||
if R == {symbol}:
|
||||
return y
|
||||
|
||||
# ∂a(λ) → ϕ
|
||||
# ∂a(ϕ) → ϕ
|
||||
# ∂a(¬a) → ϕ
|
||||
if R == y or R == phi or R in syms:
|
||||
return phi
|
||||
|
||||
tag = R[0]
|
||||
|
||||
# ∂a(R*) → ∂a(R)∘R*
|
||||
if tag == KSTAR:
|
||||
return _cons(derv(R[1]), R)
|
||||
|
||||
# ∂a(¬R) → ¬∂a(R)
|
||||
if tag == NOT:
|
||||
return (NOT, derv(R[1]))
|
||||
|
||||
r, s = R[1:]
|
||||
|
||||
# ∂a(R∘S) → ∂a(R)∘S ∨ δ(R)∘∂a(S)
|
||||
if tag == CONS:
|
||||
A = _cons(derv(r), s) # A = ∂a(r)∘s
|
||||
# A ∨ δ(R) ∘ ∂a(S)
|
||||
# A ∨ λ ∘ ∂a(S) → A ∨ ∂a(S)
|
||||
# A ∨ ϕ ∘ ∂a(S) → A ∨ ϕ → A
|
||||
return _or(A, derv(s)) if nully(r) else A
|
||||
|
||||
# ∂a(R ∧ S) → ∂a(R) ∧ ∂a(S)
|
||||
# ∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
dr, ds = derv(r), derv(s)
|
||||
return _and(dr, ds) if tag == AND else _or(dr, ds)
|
||||
|
||||
return derv
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="lets-try-it-out">
|
||||
<h2>Let’s try it out…<a class="headerlink" href="#lets-try-it-out" title="Permalink to this headline">¶</a></h2>
|
||||
<p>(FIXME: redo.)</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>o, z = D_compaction('0'), D_compaction('1')
|
||||
REs = set()
|
||||
N = 5
|
||||
names = list(product(*(N * [(0, 1)])))
|
||||
dervs = list(product(*(N * [(o, z)])))
|
||||
for name, ds in zip(names, dervs):
|
||||
R = it
|
||||
ds = list(ds)
|
||||
while ds:
|
||||
R = ds.pop()(R)
|
||||
if R == phi or R == I:
|
||||
break
|
||||
REs.add(R)
|
||||
|
||||
print stringy(it) ; print
|
||||
print o.hits, '/', o.calls
|
||||
print z.hits, '/', z.calls
|
||||
print
|
||||
for s in sorted(map(stringy, REs), key=lambda n: (len(n), n)):
|
||||
print s
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mf">.111</span><span class="o">.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">11</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
|
||||
<span class="mi">92</span> <span class="o">/</span> <span class="mi">122</span>
|
||||
<span class="mi">92</span> <span class="o">/</span> <span class="mi">122</span>
|
||||
|
||||
<span class="p">(</span><span class="mf">.01</span><span class="p">)</span><span class="s1">'</span>
|
||||
<span class="p">(</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="p">)</span><span class="s1">'</span>
|
||||
<span class="p">(</span><span class="mf">.01</span> <span class="o">|</span> <span class="o">^</span><span class="p">)</span><span class="s1">'</span>
|
||||
<span class="p">(</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="o">*</span><span class="p">)</span><span class="s1">'</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="o">^</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span> <span class="o">|</span> <span class="mf">1.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span> <span class="o">|</span> <span class="mf">1.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Should match:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mf">.111</span><span class="o">.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">11</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
|
||||
<span class="mi">92</span> <span class="o">/</span> <span class="mi">122</span>
|
||||
<span class="mi">92</span> <span class="o">/</span> <span class="mi">122</span>
|
||||
|
||||
<span class="p">(</span><span class="mf">.01</span> <span class="p">)</span><span class="s1">'</span>
|
||||
<span class="p">(</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span> <span class="p">)</span><span class="s1">'</span>
|
||||
<span class="p">(</span><span class="mf">.01</span> <span class="o">|</span> <span class="o">^</span> <span class="p">)</span><span class="s1">'</span>
|
||||
<span class="p">(</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="o">*</span><span class="p">)</span><span class="s1">'</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span> <span class="p">)</span><span class="s1">')</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="o">^</span> <span class="p">)</span><span class="s1">')</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span> <span class="o">|</span> <span class="mf">1.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="p">)</span><span class="s1">')</span>
|
||||
<span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span> <span class="o">|</span> <span class="mf">1.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="larger-alphabets">
|
||||
<h2>Larger Alphabets<a class="headerlink" href="#larger-alphabets" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We could parse larger alphabets by defining patterns for e.g. each byte
|
||||
of the ASCII code. Or we can generalize this code. If you study the code
|
||||
above you’ll see that we never use the “set-ness” of the symbols <code class="docutils literal notranslate"><span class="pre">O</span></code>
|
||||
and <code class="docutils literal notranslate"><span class="pre">l</span></code>. The only time Python set operators (<code class="docutils literal notranslate"><span class="pre">&</span></code> and <code class="docutils literal notranslate"><span class="pre">|</span></code>) appear
|
||||
is in the <code class="docutils literal notranslate"><span class="pre">nully()</span></code> function, and there they operate on (recursively
|
||||
computed) outputs of that function, never <code class="docutils literal notranslate"><span class="pre">O</span></code> and <code class="docutils literal notranslate"><span class="pre">l</span></code>.</p>
|
||||
<p>What if we try:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>(OR, O, l)
|
||||
|
||||
∂1((OR, O, l))
|
||||
∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
∂1(O) ∨ ∂1(l)
|
||||
∂a(¬a) → ϕ
|
||||
ϕ ∨ ∂1(l)
|
||||
∂a(a) → λ
|
||||
ϕ ∨ λ
|
||||
ϕ ∨ R = R
|
||||
λ
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>And compare it to:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>{'0', '1')
|
||||
|
||||
∂1({'0', '1'))
|
||||
∂a(R ∨ S) → ∂a(R) ∨ ∂a(S)
|
||||
∂1({'0')) ∨ ∂1({'1'))
|
||||
∂a(¬a) → ϕ
|
||||
ϕ ∨ ∂1({'1'))
|
||||
∂a(a) → λ
|
||||
ϕ ∨ λ
|
||||
ϕ ∨ R = R
|
||||
λ
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This suggests that we should be able to alter the functions above to
|
||||
detect sets and deal with them appropriately. Exercise for the Reader
|
||||
for now.</p>
|
||||
</section>
|
||||
<section id="state-machine">
|
||||
<h2>State Machine<a class="headerlink" href="#state-machine" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We can drive the regular expressions to flesh out the underlying state
|
||||
machine transition table.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">.111</span><span class="o">.</span> <span class="o">&</span> <span class="p">(</span><span class="mf">.01</span> <span class="o">+</span> <span class="mi">11</span><span class="o">*</span><span class="p">)</span><span class="s1">'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Says, “Three or more 1’s and not ending in 01 nor composed of all 1’s.”</p>
|
||||
<figure class="align-default" id="id2">
|
||||
<img alt="State Machine Graph" src="../_images/omg.svg" /><figcaption>
|
||||
<p><span class="caption-text">State Machine Graph</span><a class="headerlink" href="#id2" title="Permalink to this image">¶</a></p>
|
||||
</figcaption>
|
||||
</figure>
|
||||
<p>Start at <code class="docutils literal notranslate"><span class="pre">a</span></code> and follow the transition arrows according to their
|
||||
labels. Accepting states have a double outline. (Graphic generated with
|
||||
<a class="reference external" href="http://www.graphviz.org/">Dot from Graphviz</a>.) You’ll see that only
|
||||
paths that lead to one of the accepting states will match the regular
|
||||
expression. All other paths will terminate at one of the non-accepting
|
||||
states.</p>
|
||||
<p>There’s a happy path to <code class="docutils literal notranslate"><span class="pre">g</span></code> along 111:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>a→c→e→g
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>After you reach <code class="docutils literal notranslate"><span class="pre">g</span></code> you’re stuck there eating 1’s until you see a 0,
|
||||
which takes you to the <code class="docutils literal notranslate"><span class="pre">i→j→i|i→j→h→i</span></code> “trap”. You can’t reach any
|
||||
other states from those two loops.</p>
|
||||
<p>If you see a 0 before you see 111 you will reach <code class="docutils literal notranslate"><span class="pre">b</span></code>, which forms
|
||||
another “trap” with <code class="docutils literal notranslate"><span class="pre">d</span></code> and <code class="docutils literal notranslate"><span class="pre">f</span></code>. The only way out is another happy
|
||||
path along 111 to <code class="docutils literal notranslate"><span class="pre">h</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>b→d→f→h
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Once you have reached <code class="docutils literal notranslate"><span class="pre">h</span></code> you can see as many 1’s or as many 0’ in a
|
||||
row and still be either still at <code class="docutils literal notranslate"><span class="pre">h</span></code> (for 1’s) or move to <code class="docutils literal notranslate"><span class="pre">i</span></code> (for
|
||||
0’s). If you find yourself at <code class="docutils literal notranslate"><span class="pre">i</span></code> you can see as many 0’s, or
|
||||
repetitions of 10, as there are, but if you see just a 1 you move to
|
||||
<code class="docutils literal notranslate"><span class="pre">j</span></code>.</p>
|
||||
<section id="re-to-fsm">
|
||||
<h3>RE to FSM<a class="headerlink" href="#re-to-fsm" title="Permalink to this headline">¶</a></h3>
|
||||
<p>So how do we get the state machine from the regular expression?</p>
|
||||
<p>It turns out that each RE is effectively a state, and each arrow points
|
||||
to the derivative RE in respect to the arrow’s symbol.</p>
|
||||
<p>If we label the initial RE <code class="docutils literal notranslate"><span class="pre">a</span></code>, we can say:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>a --0--> ∂0(a)
|
||||
a --1--> ∂1(a)
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>And so on, each new unique RE is a new state in the FSM table.</p>
|
||||
<p>Here are the derived REs at each state:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.111</span><span class="o">.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">11</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="n">b</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.111</span><span class="o">.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="n">c</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="n">d</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="o">^</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="n">e</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span> <span class="o">|</span> <span class="mf">1.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="o">*</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="n">f</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.111</span><span class="o">.</span> <span class="o">|</span> <span class="mf">11.</span> <span class="o">|</span> <span class="mf">1.</span><span class="p">)</span> <span class="o">&</span> <span class="p">((</span><span class="mf">.01</span><span class="p">)</span><span class="s1">')</span>
|
||||
<span class="n">g</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="o">*</span><span class="p">)</span><span class="s1">'</span>
|
||||
<span class="n">h</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.01</span><span class="p">)</span><span class="s1">'</span>
|
||||
<span class="n">i</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.01</span> <span class="o">|</span> <span class="mi">1</span><span class="p">)</span><span class="s1">'</span>
|
||||
<span class="n">j</span> <span class="o">=</span> <span class="p">(</span><span class="mf">.01</span> <span class="o">|</span> <span class="o">^</span><span class="p">)</span><span class="s1">'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>You can see the one-way nature of the <code class="docutils literal notranslate"><span class="pre">g</span></code> state and the <code class="docutils literal notranslate"><span class="pre">hij</span></code> “trap”
|
||||
in the way that the <code class="docutils literal notranslate"><span class="pre">.111.</span></code> on the left-hand side of the <code class="docutils literal notranslate"><span class="pre">&</span></code>
|
||||
disappears once it has been matched.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>from collections import defaultdict
|
||||
from pprint import pprint
|
||||
from string import ascii_lowercase
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>d0, d1 = D_compaction('0'), D_compaction('1')
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="explore">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">explore()</span></code><a class="headerlink" href="#explore" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>def explore(re):
|
||||
|
||||
# Don't have more than 26 states...
|
||||
names = defaultdict(iter(ascii_lowercase).next)
|
||||
|
||||
table, accepting = dict(), set()
|
||||
|
||||
to_check = {re}
|
||||
while to_check:
|
||||
|
||||
re = to_check.pop()
|
||||
state_name = names[re]
|
||||
|
||||
if (state_name, 0) in table:
|
||||
continue
|
||||
|
||||
if nully(re):
|
||||
accepting.add(state_name)
|
||||
|
||||
o, i = d0(re), d1(re)
|
||||
table[state_name, 0] = names[o] ; to_check.add(o)
|
||||
table[state_name, 1] = names[i] ; to_check.add(i)
|
||||
|
||||
return table, accepting
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>table, accepting = explore(it)
|
||||
table
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">{(</span><span class="s1">'a'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'b'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'a'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'c'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'b'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'b'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'b'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'d'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'c'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'b'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'c'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'e'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'d'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'b'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'d'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'f'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'e'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'b'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'e'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'g'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'f'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'b'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'f'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'h'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'g'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'i'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'g'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'g'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'h'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'i'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'h'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'h'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'i'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'i'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'i'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'j'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'j'</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="s1">'i'</span><span class="p">,</span>
|
||||
<span class="p">(</span><span class="s1">'j'</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="s1">'h'</span><span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>accepting
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="s1">'h'</span><span class="p">,</span> <span class="s1">'i'</span><span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="generate-diagram">
|
||||
<h3>Generate Diagram<a class="headerlink" href="#generate-diagram" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Once we have the FSM table and the set of accepting states we can
|
||||
generate the diagram above.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>_template = '''\
|
||||
digraph finite_state_machine {
|
||||
rankdir=LR;
|
||||
size="8,5"
|
||||
node [shape = doublecircle]; %s;
|
||||
node [shape = circle];
|
||||
%s
|
||||
}
|
||||
'''
|
||||
|
||||
def link(fr, nm, label):
|
||||
return ' %s -> %s [ label = "%s" ];' % (fr, nm, label)
|
||||
|
||||
|
||||
def make_graph(table, accepting):
|
||||
return _template % (
|
||||
' '.join(accepting),
|
||||
'\n'.join(
|
||||
link(from_, to, char)
|
||||
for (from_, char), (to) in sorted(table.iteritems())
|
||||
)
|
||||
)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>print make_graph(table, accepting)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">digraph</span> <span class="n">finite_state_machine</span> <span class="p">{</span>
|
||||
<span class="n">rankdir</span><span class="o">=</span><span class="n">LR</span><span class="p">;</span>
|
||||
<span class="n">size</span><span class="o">=</span><span class="s2">"8,5"</span>
|
||||
<span class="n">node</span> <span class="p">[</span><span class="n">shape</span> <span class="o">=</span> <span class="n">doublecircle</span><span class="p">];</span> <span class="n">i</span> <span class="n">h</span><span class="p">;</span>
|
||||
<span class="n">node</span> <span class="p">[</span><span class="n">shape</span> <span class="o">=</span> <span class="n">circle</span><span class="p">];</span>
|
||||
<span class="n">a</span> <span class="o">-></span> <span class="n">b</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">a</span> <span class="o">-></span> <span class="n">c</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="n">b</span> <span class="o">-></span> <span class="n">b</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">b</span> <span class="o">-></span> <span class="n">d</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="n">c</span> <span class="o">-></span> <span class="n">b</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">c</span> <span class="o">-></span> <span class="n">e</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="n">d</span> <span class="o">-></span> <span class="n">b</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">d</span> <span class="o">-></span> <span class="n">f</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="n">e</span> <span class="o">-></span> <span class="n">b</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">e</span> <span class="o">-></span> <span class="n">g</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="n">f</span> <span class="o">-></span> <span class="n">b</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">f</span> <span class="o">-></span> <span class="n">h</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="n">g</span> <span class="o">-></span> <span class="n">i</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">g</span> <span class="o">-></span> <span class="n">g</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="n">h</span> <span class="o">-></span> <span class="n">i</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">h</span> <span class="o">-></span> <span class="n">h</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="n">i</span> <span class="o">-></span> <span class="n">i</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">i</span> <span class="o">-></span> <span class="n">j</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="n">j</span> <span class="o">-></span> <span class="n">i</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"0"</span> <span class="p">];</span>
|
||||
<span class="n">j</span> <span class="o">-></span> <span class="n">h</span> <span class="p">[</span> <span class="n">label</span> <span class="o">=</span> <span class="s2">"1"</span> <span class="p">];</span>
|
||||
<span class="p">}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="drive-a-fsm">
|
||||
<h3>Drive a FSM<a class="headerlink" href="#drive-a-fsm" title="Permalink to this headline">¶</a></h3>
|
||||
<p>There are <em>lots</em> of FSM libraries already. Once you have the state
|
||||
transition table they should all be straightforward to use. State
|
||||
Machine code is very simple. Just for fun, here is an implementation in
|
||||
Python that imitates what “compiled” FSM code might look like in an
|
||||
“unrolled” form. Most FSM code uses a little driver loop and a table
|
||||
datastructure, the code below instead acts like JMP instructions
|
||||
(“jump”, or GOTO in higher-level-but-still-low-level languages) to
|
||||
hard-code the information in the table into a little patch of branches.</p>
|
||||
<section id="trampoline-function">
|
||||
<h4>Trampoline Function<a class="headerlink" href="#trampoline-function" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Python has no GOTO statement but we can fake it with a “trampoline”
|
||||
function.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>def trampoline(input_, jump_from, accepting):
|
||||
I = iter(input_)
|
||||
while True:
|
||||
try:
|
||||
bounce_to = jump_from(I)
|
||||
except StopIteration:
|
||||
return jump_from in accepting
|
||||
jump_from = bounce_to
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="stream-functions">
|
||||
<h4>Stream Functions<a class="headerlink" href="#stream-functions" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Little helpers to process the iterator of our data (a “stream” of “1”
|
||||
and “0” characters, not bits.)</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>getch = lambda I: int(next(I))
|
||||
|
||||
|
||||
def _1(I):
|
||||
'''Loop on ones.'''
|
||||
while getch(I): pass
|
||||
|
||||
|
||||
def _0(I):
|
||||
'''Loop on zeros.'''
|
||||
while not getch(I): pass
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="a-finite-state-machine">
|
||||
<h4>A Finite State Machine<a class="headerlink" href="#a-finite-state-machine" title="Permalink to this headline">¶</a></h4>
|
||||
<p>With those preliminaries out of the way, from the state table of
|
||||
<code class="docutils literal notranslate"><span class="pre">.111.</span> <span class="pre">&</span> <span class="pre">(.01</span> <span class="pre">+</span> <span class="pre">11*)'</span></code> we can immediately write down state machine
|
||||
code. (You have to imagine that these are GOTO statements in C or
|
||||
branches in assembly and that the state names are branch destination
|
||||
labels.)</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>a = lambda I: c if getch(I) else b
|
||||
b = lambda I: _0(I) or d
|
||||
c = lambda I: e if getch(I) else b
|
||||
d = lambda I: f if getch(I) else b
|
||||
e = lambda I: g if getch(I) else b
|
||||
f = lambda I: h if getch(I) else b
|
||||
g = lambda I: _1(I) or i
|
||||
h = lambda I: _1(I) or i
|
||||
i = lambda I: _0(I) or j
|
||||
j = lambda I: h if getch(I) else i
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Note that the implementations of <code class="docutils literal notranslate"><span class="pre">h</span></code> and <code class="docutils literal notranslate"><span class="pre">g</span></code> are identical ergo
|
||||
<code class="docutils literal notranslate"><span class="pre">h</span> <span class="pre">=</span> <span class="pre">g</span></code> and we could eliminate one in the code but <code class="docutils literal notranslate"><span class="pre">h</span></code> is an
|
||||
accepting state and <code class="docutils literal notranslate"><span class="pre">g</span></code> isn’t.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>def acceptable(input_):
|
||||
return trampoline(input_, a, {h, i})
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>for n in range(2**5):
|
||||
s = bin(n)[2:]
|
||||
print '%05s' % s, acceptable(s)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="mi">0</span> <span class="kc">False</span>
|
||||
<span class="mi">1</span> <span class="kc">False</span>
|
||||
<span class="mi">10</span> <span class="kc">False</span>
|
||||
<span class="mi">11</span> <span class="kc">False</span>
|
||||
<span class="mi">100</span> <span class="kc">False</span>
|
||||
<span class="mi">101</span> <span class="kc">False</span>
|
||||
<span class="mi">110</span> <span class="kc">False</span>
|
||||
<span class="mi">111</span> <span class="kc">False</span>
|
||||
<span class="mi">1000</span> <span class="kc">False</span>
|
||||
<span class="mi">1001</span> <span class="kc">False</span>
|
||||
<span class="mi">1010</span> <span class="kc">False</span>
|
||||
<span class="mi">1011</span> <span class="kc">False</span>
|
||||
<span class="mi">1100</span> <span class="kc">False</span>
|
||||
<span class="mi">1101</span> <span class="kc">False</span>
|
||||
<span class="mi">1110</span> <span class="kc">True</span>
|
||||
<span class="mi">1111</span> <span class="kc">False</span>
|
||||
<span class="mi">10000</span> <span class="kc">False</span>
|
||||
<span class="mi">10001</span> <span class="kc">False</span>
|
||||
<span class="mi">10010</span> <span class="kc">False</span>
|
||||
<span class="mi">10011</span> <span class="kc">False</span>
|
||||
<span class="mi">10100</span> <span class="kc">False</span>
|
||||
<span class="mi">10101</span> <span class="kc">False</span>
|
||||
<span class="mi">10110</span> <span class="kc">False</span>
|
||||
<span class="mi">10111</span> <span class="kc">True</span>
|
||||
<span class="mi">11000</span> <span class="kc">False</span>
|
||||
<span class="mi">11001</span> <span class="kc">False</span>
|
||||
<span class="mi">11010</span> <span class="kc">False</span>
|
||||
<span class="mi">11011</span> <span class="kc">False</span>
|
||||
<span class="mi">11100</span> <span class="kc">True</span>
|
||||
<span class="mi">11101</span> <span class="kc">False</span>
|
||||
<span class="mi">11110</span> <span class="kc">True</span>
|
||||
<span class="mi">11111</span> <span class="kc">False</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="reversing-the-derivatives-to-generate-matching-strings">
|
||||
<h2>Reversing the Derivatives to Generate Matching Strings<a class="headerlink" href="#reversing-the-derivatives-to-generate-matching-strings" title="Permalink to this headline">¶</a></h2>
|
||||
<p>(UNFINISHED) Brzozowski also shewed how to go from the state machine to
|
||||
strings and expressions…</p>
|
||||
<p>Each of these states is just a name for a Brzozowskian RE, and so, other
|
||||
than the initial state <code class="docutils literal notranslate"><span class="pre">a</span></code>, they can can be described in terms of the
|
||||
derivative-with-respect-to-N of some other state/RE:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">c</span> <span class="o">=</span> <span class="n">d1</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
|
||||
<span class="n">b</span> <span class="o">=</span> <span class="n">d0</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
|
||||
<span class="n">b</span> <span class="o">=</span> <span class="n">d0</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
|
||||
<span class="o">...</span>
|
||||
<span class="n">i</span> <span class="o">=</span> <span class="n">d0</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
|
||||
<span class="n">j</span> <span class="o">=</span> <span class="n">d1</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Consider:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">c</span> <span class="o">=</span> <span class="n">d1</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
|
||||
<span class="n">b</span> <span class="o">=</span> <span class="n">d0</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Substituting:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="o">=</span> <span class="n">d0</span><span class="p">(</span><span class="n">d1</span><span class="p">(</span><span class="n">a</span><span class="p">))</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Unwrapping:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="o">=</span> <span class="n">d10</span><span class="p">(</span><span class="n">a</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>’’’</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">j</span> <span class="o">=</span> <span class="n">d1</span><span class="p">(</span><span class="n">d0</span><span class="p">(</span><span class="n">j</span><span class="p">))</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Unwrapping:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">j</span> <span class="o">=</span> <span class="n">d1</span><span class="p">(</span><span class="n">d0</span><span class="p">(</span><span class="n">j</span><span class="p">))</span> <span class="o">=</span> <span class="n">d01</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We have a loop or “fixed point”.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">j</span> <span class="o">=</span> <span class="n">d01</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="o">=</span> <span class="n">d0101</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="o">=</span> <span class="n">d010101</span><span class="p">(</span><span class="n">j</span><span class="p">)</span> <span class="o">=</span> <span class="o">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>hmm…</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">j</span> <span class="o">=</span> <span class="p">(</span><span class="mi">01</span><span class="p">)</span><span class="o">*</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="The_Four_Operations.html" title="previous chapter">The Four Fundamental Operations of Definite Action</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,376 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Thun: Joy in Python — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Joy Interpreter" href="../joy.html" />
|
||||
<link rel="prev" title="Thun 0.4.1 Documentation" href="../index.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="thun-joy-in-python">
|
||||
<h1>Thun: Joy in Python<a class="headerlink" href="#thun-joy-in-python" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This implementation is meant as a tool for exploring the programming
|
||||
model and method of Joy. Python seems like a great implementation
|
||||
language for Joy for several reasons.</p>
|
||||
<ul class="simple">
|
||||
<li><p>We can lean on the Python immutable types for our basic semantics and types: ints, floats, strings, and tuples, which enforces functional purity.</p></li>
|
||||
<li><p>We get garbage collection for free.</p></li>
|
||||
<li><p>Compilation via Cython.</p></li>
|
||||
<li><p>Python is a “glue language” with loads of libraries which we can wrap in Joy functions.</p></li>
|
||||
</ul>
|
||||
<section id="read-eval-print-loop-repl">
|
||||
<h2><a class="reference external" href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop">Read-Eval-Print Loop (REPL)</a><a class="headerlink" href="#read-eval-print-loop-repl" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The main way to interact with the Joy interpreter is through a simple
|
||||
<a class="reference external" href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop">REPL</a>
|
||||
that you start by running the package:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>$ python3 -m joy
|
||||
Thun - Copyright © 2017 Simon Forman
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type "warranty".
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type "sharing" for details.
|
||||
Type "words" to see a list of all words, and "[<name>] help" to print the
|
||||
docs for a word.
|
||||
|
||||
|
||||
<-top
|
||||
|
||||
joy? _
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre"><-top</span></code> marker points to the top of the (initially empty) stack.
|
||||
You can enter Joy notation at the prompt and a <a class="reference internal" href="../pretty.html"><span class="doc">trace of evaluation</span></a> will
|
||||
be printed followed by the stack and prompt again:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>joy? 23 sqr 18 +
|
||||
|
||||
547 <-top
|
||||
|
||||
joy?
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>There is a <cite>trace</cite> combinator:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>joy? 23 [sqr 18 +] trace
|
||||
23 . sqr 18 +
|
||||
23 . dup mul 18 +
|
||||
23 23 . mul 18 +
|
||||
529 . 18 +
|
||||
529 18 . +
|
||||
547 .
|
||||
|
||||
547 <-top
|
||||
|
||||
joy?
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="the-stack">
|
||||
<h2>The Stack<a class="headerlink" href="#the-stack" title="Permalink to this headline">¶</a></h2>
|
||||
<p>In Joy, in addition to the types Boolean, integer, float, and string,
|
||||
there is a <a class="reference internal" href="../stack.html"><span class="doc">single sequence type</span></a> represented by enclosing a sequence of
|
||||
terms in brackets <code class="docutils literal notranslate"><span class="pre">[...]</span></code>. This sequence type is used to represent
|
||||
both the stack and the expression. It is a <a class="reference external" href="https://en.wikipedia.org/wiki/Cons#Lists">cons
|
||||
list</a> made from Python
|
||||
tuples.</p>
|
||||
</section>
|
||||
<section id="purely-functional-datastructures">
|
||||
<h2>Purely Functional Datastructures<a class="headerlink" href="#purely-functional-datastructures" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Because Joy stacks are made out of Python tuples they are immutable, as are the other Python types we “borrow” for Joy, so all Joy datastructures are <a class="reference external" href="https://en.wikipedia.org/wiki/Purely_functional_data_structure">purely functional</a>.</p>
|
||||
</section>
|
||||
<section id="the-joy-function">
|
||||
<h2>The <code class="docutils literal notranslate"><span class="pre">joy()</span></code> function<a class="headerlink" href="#the-joy-function" title="Permalink to this headline">¶</a></h2>
|
||||
<section id="an-interpreter">
|
||||
<h3>An Interpreter<a class="headerlink" href="#an-interpreter" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">joy()</span></code> interpreter function is extrememly simple. It accepts a stack, an
|
||||
expression, and a dictionary, and it iterates through the expression
|
||||
putting values onto the stack and delegating execution to functions which it
|
||||
looks up in the dictionary.</p>
|
||||
</section>
|
||||
<section id="continuation-passing-style">
|
||||
<h3><a class="reference external" href="https://en.wikipedia.org/wiki/Continuation-passing_style">Continuation-Passing Style</a><a class="headerlink" href="#continuation-passing-style" title="Permalink to this headline">¶</a></h3>
|
||||
<p>One day I thought, What happens if you rewrite Joy to use
|
||||
<a class="reference external" href="https://en.wikipedia.org/wiki/Continuation-passing_style">CPS</a>? I
|
||||
made all the functions accept and return the expression as well as the
|
||||
stack and found that all the combinators could be rewritten to work by
|
||||
modifying the expression rather than making recursive calls to the
|
||||
<code class="docutils literal notranslate"><span class="pre">joy()</span></code> function.</p>
|
||||
</section>
|
||||
<section id="view-function">
|
||||
<h3>View function<a class="headerlink" href="#view-function" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">joy()</span></code> function accepts an optional <code class="docutils literal notranslate"><span class="pre">viewer</span></code> argument that
|
||||
is a function which it calls on
|
||||
each iteration passing the current stack and expression just before
|
||||
evaluation. This can be used for tracing, breakpoints, retrying after
|
||||
exceptions, or interrupting an evaluation and saving to disk or sending
|
||||
over the network to resume later. The stack and expression together
|
||||
contain all the state of the computation at each step.</p>
|
||||
</section>
|
||||
<section id="the-traceprinter">
|
||||
<h3>The <code class="docutils literal notranslate"><span class="pre">TracePrinter</span></code>.<a class="headerlink" href="#the-traceprinter" title="Permalink to this headline">¶</a></h3>
|
||||
<p>A <code class="docutils literal notranslate"><span class="pre">viewer</span></code> records each step of the evaluation of a Joy program. The
|
||||
<code class="docutils literal notranslate"><span class="pre">TracePrinter</span></code> has a facility for printing out a trace of the
|
||||
evaluation, one line per step. Each step is aligned to the current
|
||||
interpreter position, signified by a period separating the stack on the
|
||||
left from the pending expression (“continuation”) on the right.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="parser">
|
||||
<h2>Parser<a class="headerlink" href="#parser" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The parser is extremely simple. The undocumented <code class="docutils literal notranslate"><span class="pre">re.Scanner</span></code> class
|
||||
does the tokenizing and then the parser builds the tuple
|
||||
structure out of the tokens. There’s no Abstract Syntax Tree or anything
|
||||
like that.</p>
|
||||
<section id="symbols">
|
||||
<h3>Symbols<a class="headerlink" href="#symbols" title="Permalink to this headline">¶</a></h3>
|
||||
<p>TODO: Symbols are just a string subclass; used by the parser to represent function names and by the interpreter to look up functions in the dictionary. N.B.: Symbols are not looked up at parse-time. You <em>could</em> define recursive functions, er, recusively, without <code class="docutils literal notranslate"><span class="pre">genrec</span></code> or other recursion combinators <code class="docutils literal notranslate"><span class="pre">foo</span> <span class="pre">==</span> <span class="pre">...</span> <span class="pre">foo</span> <span class="pre">...</span></code> but don’t do that.</p>
|
||||
</section>
|
||||
<section id="token-regular-expressions">
|
||||
<h3>Token Regular Expressions<a class="headerlink" href="#token-regular-expressions" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">123</span> <span class="mf">1.2</span> <span class="s1">'single quotes'</span> <span class="s2">"double quotes"</span> <span class="n">function</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>TBD (look in the :module: joy.parser module.)</p>
|
||||
</section>
|
||||
<section id="examples">
|
||||
<h3>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">joy</span><span class="o">.</span><span class="n">parser</span><span class="o">.</span><span class="n">text_to_expression</span><span class="p">(</span><span class="s1">'1 2 3 4 5'</span><span class="p">)</span> <span class="c1"># A simple sequence.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="p">())))))</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">joy</span><span class="o">.</span><span class="n">parser</span><span class="o">.</span><span class="n">text_to_expression</span><span class="p">(</span><span class="s1">'[1 2 3] 4 5'</span><span class="p">)</span> <span class="c1"># Three items, the first is a list with three items</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="p">()))),</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="p">())))</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">joy</span><span class="o">.</span><span class="n">parser</span><span class="o">.</span><span class="n">text_to_expression</span><span class="p">(</span><span class="s1">'1 23 ["four" [-5.0] cons] 8888'</span><span class="p">)</span> <span class="c1"># A mixed bag. cons is</span>
|
||||
<span class="c1"># a Symbol, no lookup at</span>
|
||||
<span class="c1"># parse-time. Haiku docs.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="p">(</span><span class="mi">23</span><span class="p">,</span> <span class="p">((</span><span class="s1">'four'</span><span class="p">,</span> <span class="p">((</span><span class="o">-</span><span class="mf">5.0</span><span class="p">,</span> <span class="p">()),</span> <span class="p">(</span><span class="n">cons</span><span class="p">,</span> <span class="p">()))),</span> <span class="p">(</span><span class="mi">8888</span><span class="p">,</span> <span class="p">()))))</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">joy</span><span class="o">.</span><span class="n">parser</span><span class="o">.</span><span class="n">text_to_expression</span><span class="p">(</span><span class="s1">'[][][][][]'</span><span class="p">)</span> <span class="c1"># Five empty lists.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">((),</span> <span class="p">((),</span> <span class="p">((),</span> <span class="p">((),</span> <span class="p">((),</span> <span class="p">())))))</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">joy</span><span class="o">.</span><span class="n">parser</span><span class="o">.</span><span class="n">text_to_expression</span><span class="p">(</span><span class="s1">'[[[[[]]]]]'</span><span class="p">)</span> <span class="c1"># Five nested lists.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">((((((),</span> <span class="p">()),</span> <span class="p">()),</span> <span class="p">()),</span> <span class="p">()),</span> <span class="p">())</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="library">
|
||||
<h2>Library<a class="headerlink" href="#library" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The Joy library of functions (aka commands, or “words” after Forth
|
||||
usage) encapsulates all the actual functionality (no pun intended) of
|
||||
the Joy system. There are simple functions such as addition <code class="docutils literal notranslate"><span class="pre">add</span></code> (or
|
||||
<code class="docutils literal notranslate"><span class="pre">+</span></code>, the library module supports aliases), and combinators which
|
||||
provide control-flow and higher-order operations.</p>
|
||||
<p>Many of the functions are defined in Python, like <code class="docutils literal notranslate"><span class="pre">dip</span></code>:</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="n">inspect</span><span class="o">.</span><span class="n">getsource</span><span class="p">(</span><span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">dip</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">dip</span><span class="p">(</span><span class="n">stack</span><span class="p">,</span> <span class="n">expression</span><span class="p">,</span> <span class="n">dictionary</span><span class="p">):</span>
|
||||
<span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">stack</span><span class="p">))</span> <span class="o">=</span> <span class="n">stack</span>
|
||||
<span class="n">expression</span> <span class="o">=</span> <span class="n">x</span><span class="p">,</span> <span class="n">expression</span>
|
||||
<span class="k">return</span> <span class="n">stack</span><span class="p">,</span> <span class="n">concat</span><span class="p">(</span><span class="n">quote</span><span class="p">,</span> <span class="n">expression</span><span class="p">),</span> <span class="n">dictionary</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Some functions are defined in equations in terms of other functions.
|
||||
When the interpreter executes a definition function that function just
|
||||
pushes its body expression onto the pending expression (the
|
||||
continuation) and returns control to the interpreter.</p>
|
||||
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="n">joy</span><span class="o">.</span><span class="n">library</span><span class="o">.</span><span class="n">definitions</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<pre class="literal-block">second == rest first
|
||||
third == rest rest first
|
||||
product == 1 swap [*] step
|
||||
swons == swap cons
|
||||
swoncat == swap concat
|
||||
flatten == [] swap [concat] step
|
||||
unit == [] cons
|
||||
quoted == [unit] dip
|
||||
unquoted == [i] dip
|
||||
enstacken == stack [clear] dip
|
||||
disenstacken == ? [uncons ?] loop pop
|
||||
? == dup truthy
|
||||
dinfrirst == dip infra first
|
||||
nullary == [stack] dinfrirst
|
||||
unary == [stack [pop] dip] dinfrirst
|
||||
binary == [stack [popop] dip] dinfrirst
|
||||
ternary == [stack [popop pop] dip] dinfrirst
|
||||
pam == [i] map
|
||||
run == [] swap infra
|
||||
sqr == dup mul
|
||||
size == 0 swap [pop ++] step
|
||||
cleave == [i] app2 [popd] dip
|
||||
average == [sum 1.0 <em>] [size] cleave /
|
||||
gcd == 1 [tuck modulus dup 0 >] loop pop
|
||||
least_fraction == dup [gcd] infra [div] concat map
|
||||
*fraction == [uncons] dip uncons [swap] dip concat [</em>] infra [*] dip cons
|
||||
<em>fraction0 == concat [[swap] dip * [</em>] dip] infra
|
||||
down_to_zero == [0 >] [dup --] while
|
||||
range_to_zero == unit [down_to_zero] infra
|
||||
anamorphism == [pop []] swap [dip swons] genrec
|
||||
range == [0 <=] [1 - dup] anamorphism
|
||||
while == swap [nullary] cons dup dipd concat loop
|
||||
dudipd == dup dipd
|
||||
primrec == [i] genrec</pre>
|
||||
<p>Currently, there’s no function to add new definitions to the dictionary
|
||||
from “within” Joy code itself. Adding new definitions remains a
|
||||
meta-interpreter action. You have to do it yourself, in Python, and wash
|
||||
your hands afterward.</p>
|
||||
<p>It would be simple enough to define one, but it would open the door to
|
||||
<em>name binding</em> and break the idea that all state is captured in the
|
||||
stack and expression. There’s an implicit <em>standard dictionary</em> that
|
||||
defines the actual semantics of the syntactic stack and expression
|
||||
datastructures (which only contain symbols, not the actual functions.
|
||||
Pickle some and see for yourself.)</p>
|
||||
<section id="there-should-be-only-one">
|
||||
<h3>“There should be only one.”<a class="headerlink" href="#there-should-be-only-one" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Which brings me to talking about one of my hopes and dreams for this
|
||||
notation: “There should be only one.” What I mean is that there should
|
||||
be one universal standard dictionary of commands, and all bespoke work
|
||||
done in a UI for purposes takes place by direct interaction and macros.
|
||||
There would be a <em>Grand Refactoring</em> biannually (two years, not six
|
||||
months, that’s semi-annually) where any new definitions factored out of
|
||||
the usage and macros of the previous time, along with new algorithms and
|
||||
such, were entered into the dictionary and posted to e.g. IPFS.</p>
|
||||
<p>Code should not burgeon wildly, as it does today. The variety of code
|
||||
should map more-or-less to the well-factored variety of human
|
||||
computably-solvable problems. There shouldn’t be dozens of chat apps, JS
|
||||
frameworks, programming languages. It’s a waste of time, a <a class="reference external" href="https://en.wikipedia.org/wiki/Thundering_herd_problem">fractal
|
||||
“thundering herd”
|
||||
attack</a> on
|
||||
human mentality.</p>
|
||||
</section>
|
||||
<section id="literary-code-library">
|
||||
<h3>Literary Code Library<a class="headerlink" href="#literary-code-library" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you read over the other notebooks you’ll see that developing code in
|
||||
Joy is a lot like doing simple mathematics, and the descriptions of the
|
||||
code resemble math papers. The code also works the first time, no bugs.
|
||||
If you have any experience programming at all, you are probably
|
||||
skeptical, as I was, but it seems to work: deriving code mathematically
|
||||
seems to lead to fewer errors.</p>
|
||||
<p>But my point now is that this great ratio of textual explanation to wind
|
||||
up with code that consists of a few equations and could fit on an index
|
||||
card is highly desirable. Less code has fewer errors. The structure of
|
||||
Joy engenders a kind of thinking that seems to be very effective for
|
||||
developing structured processes.</p>
|
||||
<p>There seems to be an elegance and power to the notation.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1 current"><a class="current reference internal" href="#">Thun: Joy in Python</a><ul>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#read-eval-print-loop-repl">Read-Eval-Print Loop (REPL)</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#the-stack">The Stack</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#purely-functional-datastructures">Purely Functional Datastructures</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#the-joy-function">The <code class="docutils literal notranslate"><span class="pre">joy()</span></code> function</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#parser">Parser</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="#library">Library</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="index.html">Essays about Programming in Joy</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li>Previous: <a href="../index.html" title="previous chapter">Thun 0.4.1 Documentation</a></li>
|
||||
<li>Next: <a href="../joy.html" title="next chapter">Joy Interpreter</a></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,323 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Newton’s method — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<script async="async" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Square Spiral Example Joy Code" href="Square_Spiral.html" />
|
||||
<link rel="prev" title="Using x to Generate Values" href="Generator_Programs.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="newton-s-method">
|
||||
<h1><a class="reference external" href="https://en.wikipedia.org/wiki/Newton%27s_method">Newton’s method</a><a class="headerlink" href="#newton-s-method" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Let’s use the Newton-Raphson method for finding the root of an equation
|
||||
to write a function that can compute the square root of a number.</p>
|
||||
<p>Cf. <a class="reference external" href="https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf">“Why Functional Programming Matters” by John
|
||||
Hughes</a></p>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>from notebook_preamble import J, V, define
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="a-generator-for-approximations">
|
||||
<h2>A Generator for Approximations<a class="headerlink" href="#a-generator-for-approximations" title="Permalink to this headline">¶</a></h2>
|
||||
<p>To make a generator that generates successive approximations let’s start
|
||||
by assuming an initial approximation and then derive the function that
|
||||
computes the next approximation:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">a</span> <span class="n">F</span>
|
||||
<span class="o">---------</span>
|
||||
<span class="n">a</span><span class="s1">'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="a-function-to-compute-the-next-approximation">
|
||||
<h3>A Function to Compute the Next Approximation<a class="headerlink" href="#a-function-to-compute-the-next-approximation" title="Permalink to this headline">¶</a></h3>
|
||||
<p>This is the equation for computing the next approximate value of the
|
||||
square root:</p>
|
||||
<p><span class="math notranslate nohighlight">\(a_{i+1} = \frac{(a_i+\frac{n}{a_i})}{2}\)</span></p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="n">n</span> <span class="n">over</span> <span class="o">/</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="n">a</span> <span class="n">n</span> <span class="n">a</span> <span class="o">/</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="n">a</span> <span class="n">n</span><span class="o">/</span><span class="n">a</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="n">a</span><span class="o">+</span><span class="n">n</span><span class="o">/</span><span class="n">a</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="p">(</span><span class="n">a</span><span class="o">+</span><span class="n">n</span><span class="o">/</span><span class="n">a</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The function we want has the argument <code class="docutils literal notranslate"><span class="pre">n</span></code> in it:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">F</span> <span class="o">==</span> <span class="n">n</span> <span class="n">over</span> <span class="o">/</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="make-it-into-a-generator">
|
||||
<h3>Make it into a Generator<a class="headerlink" href="#make-it-into-a-generator" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Our generator would be created by:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="p">[</span><span class="n">dup</span> <span class="n">F</span><span class="p">]</span> <span class="n">make_generator</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>With n as part of the function F, but n is the input to the sqrt
|
||||
function we’re writing. If we let 1 be the initial approximation:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">1</span> <span class="n">n</span> <span class="mi">1</span> <span class="o">/</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="mi">1</span> <span class="n">n</span><span class="o">/</span><span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="mi">1</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="n">n</span><span class="o">+</span><span class="mi">1</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="p">(</span><span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The generator can be written as:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">23</span> <span class="mi">1</span> <span class="n">swap</span> <span class="p">[</span><span class="n">over</span> <span class="o">/</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="p">[</span><span class="n">dup</span><span class="p">]</span> <span class="n">swoncat</span> <span class="n">make_generator</span>
|
||||
<span class="mi">1</span> <span class="mi">23</span> <span class="p">[</span><span class="n">over</span> <span class="o">/</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="p">[</span><span class="n">dup</span><span class="p">]</span> <span class="n">swoncat</span> <span class="n">make_generator</span>
|
||||
<span class="mi">1</span> <span class="p">[</span><span class="mi">23</span> <span class="n">over</span> <span class="o">/</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="p">[</span><span class="n">dup</span><span class="p">]</span> <span class="n">swoncat</span> <span class="n">make_generator</span>
|
||||
<span class="mi">1</span> <span class="p">[</span><span class="n">dup</span> <span class="mi">23</span> <span class="n">over</span> <span class="o">/</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">make_generator</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>define('gsra 1 swap [over / + 2 /] cons [dup] swoncat make_generator')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('23 gsra')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span> <span class="p">[</span><span class="n">dup</span> <span class="mi">23</span> <span class="n">over</span> <span class="o">/</span> <span class="o">+</span> <span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Let’s drive the generator a few time (with the <code class="docutils literal notranslate"><span class="pre">x</span></code> combinator) and
|
||||
square the approximation to see how well it works…</p>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('23 gsra 6 [x popd] times first sqr')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">23.0000000001585</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="finding-consecutive-approximations-within-a-tolerance">
|
||||
<h2>Finding Consecutive Approximations within a Tolerance<a class="headerlink" href="#finding-consecutive-approximations-within-a-tolerance" title="Permalink to this headline">¶</a></h2>
|
||||
<p>From <a class="reference external" href="https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf">“Why Functional Programming Matters” by John
|
||||
Hughes</a>:</p>
|
||||
<blockquote>
|
||||
<div><p>The remainder of a square root finder is a function <em>within</em>, which
|
||||
takes a tolerance and a list of approximations and looks down the
|
||||
list for two successive approximations that differ by no more than
|
||||
the given tolerance.</p>
|
||||
</div></blockquote>
|
||||
<p>(And note that by “list” he means a lazily-evaluated list.)</p>
|
||||
<p>Using the <em>output</em> <code class="docutils literal notranslate"><span class="pre">[a</span> <span class="pre">G]</span></code> of the above generator for square root
|
||||
approximations, and further assuming that the first term a has been
|
||||
generated already and epsilon ε is handy on the stack…</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="n">within</span>
|
||||
<span class="o">----------------------</span> <span class="n">a</span> <span class="n">b</span> <span class="o">-</span> <span class="nb">abs</span> <span class="n">ε</span> <span class="o"><=</span>
|
||||
<span class="n">b</span>
|
||||
|
||||
|
||||
<span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="n">within</span>
|
||||
<span class="o">----------------------</span> <span class="n">a</span> <span class="n">b</span> <span class="o">-</span> <span class="nb">abs</span> <span class="n">ε</span> <span class="o">></span>
|
||||
<span class="n">b</span> <span class="p">[</span><span class="n">c</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="n">within</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="predicate">
|
||||
<h3>Predicate<a class="headerlink" href="#predicate" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="p">[</span><span class="n">first</span> <span class="o">-</span> <span class="nb">abs</span><span class="p">]</span> <span class="n">dip</span> <span class="o"><=</span>
|
||||
<span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">first</span> <span class="o">-</span> <span class="nb">abs</span> <span class="n">ε</span> <span class="o"><=</span>
|
||||
<span class="n">a</span> <span class="n">b</span> <span class="o">-</span> <span class="nb">abs</span> <span class="n">ε</span> <span class="o"><=</span>
|
||||
<span class="n">a</span><span class="o">-</span><span class="n">b</span> <span class="nb">abs</span> <span class="n">ε</span> <span class="o"><=</span>
|
||||
<span class="nb">abs</span><span class="p">(</span><span class="n">a</span><span class="o">-</span><span class="n">b</span><span class="p">)</span> <span class="n">ε</span> <span class="o"><=</span>
|
||||
<span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">a</span><span class="o">-</span><span class="n">b</span><span class="p">)</span><span class="o"><=</span><span class="n">ε</span><span class="p">)</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>define('_within_P [first - abs] dip <=')
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="base-case">
|
||||
<h3>Base-Case<a class="headerlink" href="#base-case" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="n">roll</span><span class="o"><</span> <span class="n">popop</span> <span class="n">first</span>
|
||||
<span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="n">a</span> <span class="n">popop</span> <span class="n">first</span>
|
||||
<span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">first</span>
|
||||
<span class="n">b</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>define('_within_B roll< popop first')
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="recur">
|
||||
<h3>Recur<a class="headerlink" href="#recur" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="n">R0</span> <span class="p">[</span><span class="n">within</span><span class="p">]</span> <span class="n">R1</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Discard a.</p></li>
|
||||
<li><p>Use <code class="docutils literal notranslate"><span class="pre">x</span></code> combinator to generate next term from <code class="docutils literal notranslate"><span class="pre">G</span></code>.</p></li>
|
||||
<li><p>Run <code class="docutils literal notranslate"><span class="pre">within</span></code> with <code class="docutils literal notranslate"><span class="pre">i</span></code> (it is a “tail-recursive” function.)</p></li>
|
||||
</ol>
|
||||
<p>Pretty straightforward:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="n">R0</span> <span class="p">[</span><span class="n">within</span><span class="p">]</span> <span class="n">R1</span>
|
||||
<span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="p">[</span><span class="n">popd</span> <span class="n">x</span><span class="p">]</span> <span class="n">dip</span> <span class="p">[</span><span class="n">within</span><span class="p">]</span> <span class="n">i</span>
|
||||
<span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">popd</span> <span class="n">x</span> <span class="n">ε</span> <span class="p">[</span><span class="n">within</span><span class="p">]</span> <span class="n">i</span>
|
||||
<span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">x</span> <span class="n">ε</span> <span class="p">[</span><span class="n">within</span><span class="p">]</span> <span class="n">i</span>
|
||||
<span class="n">b</span> <span class="p">[</span><span class="n">c</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="p">[</span><span class="n">within</span><span class="p">]</span> <span class="n">i</span>
|
||||
<span class="n">b</span> <span class="p">[</span><span class="n">c</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="n">within</span>
|
||||
|
||||
<span class="n">b</span> <span class="p">[</span><span class="n">c</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="n">within</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>define('_within_R [popd x] dip')
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="setting-up">
|
||||
<h3>Setting up<a class="headerlink" href="#setting-up" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The recursive function we have defined so far needs a slight preamble:
|
||||
<code class="docutils literal notranslate"><span class="pre">x</span></code> to prime the generator and the epsilon value to use:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">a</span> <span class="n">G</span><span class="p">]</span> <span class="n">x</span> <span class="n">ε</span> <span class="o">...</span>
|
||||
<span class="n">a</span> <span class="p">[</span><span class="n">b</span> <span class="n">G</span><span class="p">]</span> <span class="n">ε</span> <span class="o">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>define('within x 0.000000001 [_within_P] [_within_B] [_within_R] tailrec')
|
||||
define('sqrt gsra within')
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Try it out…</p>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('36 sqrt')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">6.0</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('23 sqrt')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">4.795831523312719</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Check it.</p>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>4.795831523312719**2
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">22.999999999999996</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>from math import sqrt
|
||||
|
||||
sqrt(23)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mf">4.795831523312719</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Generator_Programs.html" title="previous chapter">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li>Next: <a href="Square_Spiral.html" title="next chapter">Square Spiral Example Joy Code</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,151 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>No Updates — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Categorical Programming" href="Categorical.html" />
|
||||
<link rel="prev" title="Type Checking" href="TypeChecking.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="no-updates">
|
||||
<h1>No Updates<a class="headerlink" href="#no-updates" title="Permalink to this headline">¶</a></h1>
|
||||
<p>DRAFT</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Joy doesn’t need to change.</p></li>
|
||||
</ol>
|
||||
<blockquote>
|
||||
<div><ol class="upperalpha simple">
|
||||
<li><p>The interpreter doesn’t need to change, <code class="docutils literal notranslate"><span class="pre">viewer</span></code> function can customize mainloop. Or use a sub-interpreter (Joy in Joy.) The base interpreter remains static.</p></li>
|
||||
<li><p>Once a function has been named and defined <em>never change that name</em>. It’s just not allowed. If you need to change a function <code class="docutils literal notranslate"><span class="pre">foo</span></code> you have to call it <code class="docutils literal notranslate"><span class="pre">foo_II</span></code> or something. Once a function (name mapped to behavior) is released to the public <em>that’s it</em>, it’s done.</p></li>
|
||||
<li><p>The language evolves by adding new definitions and refactoring, always choosing new names for new functions.</p></li>
|
||||
</ol>
|
||||
</div></blockquote>
|
||||
<ol class="arabic simple" start="2">
|
||||
<li><p>Following <a class="reference external" href="https://semver.org">Semantic Versioning</a> there will never be a version 2.0.</p></li>
|
||||
</ol>
|
||||
<blockquote>
|
||||
<div><ol class="upperalpha simple">
|
||||
<li><p><a class="reference external" href="https://semver.org/#spec-item-8">Major version must be incremented if any backwards incompatible changes are introduced to the public API.</a></p></li>
|
||||
<li><p>We never implement any backwards incompatible changes, so…</p></li>
|
||||
<li><p>We could see e.g. Thun version 1.273.3!</p></li>
|
||||
</ol>
|
||||
</div></blockquote>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="TypeChecking.html" title="previous chapter">Type Checking</a></li>
|
||||
<li>Next: <a href="Categorical.html" title="next chapter">Categorical Programming</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,260 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Quadratic formula — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<script async="async" src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Replacing Functions in the Dictionary" href="Replacing.html" />
|
||||
<link rel="prev" title="Developing a Program in Joy" href="Developing.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>from notebook_preamble import J, V, define
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="quadratic-formula">
|
||||
<h1><a class="reference external" href="https://en.wikipedia.org/wiki/Quadratic_formula">Quadratic formula</a><a class="headerlink" href="#quadratic-formula" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Cf.
|
||||
<a class="reference external" href="http://www.kevinalbrecht.com/code/joy-mirror/jp-quadratic.html">jp-quadratic.html</a></p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> -b ± sqrt(b^2 - 4 * a * c)
|
||||
--------------------------------
|
||||
2 * a
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><span class="math notranslate nohighlight">\(\frac{-b \pm \sqrt{b^2 - 4ac}}{2a}\)</span></p>
|
||||
<section id="write-a-straightforward-program-with-variable-names">
|
||||
<h2>Write a straightforward program with variable names.<a class="headerlink" href="#write-a-straightforward-program-with-variable-names" title="Permalink to this headline">¶</a></h2>
|
||||
<p>This math translates to Joy code in a straightforward manner. We are
|
||||
going to use named variables to keep track of the arguments, then write
|
||||
a definition without them.</p>
|
||||
<section id="b">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">-b</span></code><a class="headerlink" href="#b" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">neg</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="sqrt-b-2-4-a-c">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">sqrt(b^2</span> <span class="pre">-</span> <span class="pre">4</span> <span class="pre">*</span> <span class="pre">a</span> <span class="pre">*</span> <span class="pre">c)</span></code><a class="headerlink" href="#sqrt-b-2-4-a-c" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="a">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">/2a</span></code><a class="headerlink" href="#a" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="o">/</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="id1">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">±</span></code><a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h3>
|
||||
<p>There is a function <code class="docutils literal notranslate"><span class="pre">pm</span></code> that accepts two values on the stack and
|
||||
replaces them with their sum and difference.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pm</span> <span class="o">==</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="p">]</span> <span class="n">cleave</span> <span class="n">popdd</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="putting-them-together">
|
||||
<h3>Putting Them Together<a class="headerlink" href="#putting-them-together" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">neg</span> <span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We use <code class="docutils literal notranslate"><span class="pre">app2</span></code> to compute both roots by using a quoted program
|
||||
<code class="docutils literal notranslate"><span class="pre">[2a</span> <span class="pre">/]</span></code> built with <code class="docutils literal notranslate"><span class="pre">cons</span></code>.</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="derive-a-definition">
|
||||
<h2>Derive a definition.<a class="headerlink" href="#derive-a-definition" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Working backwards we use <code class="docutils literal notranslate"><span class="pre">dip</span></code> and <code class="docutils literal notranslate"><span class="pre">dipd</span></code> to extract the code from
|
||||
the variables:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">b</span> <span class="n">neg</span> <span class="n">b</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="n">b</span> <span class="p">[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="n">a</span> <span class="n">c</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="p">[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="n">a</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="n">a</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="n">b</span> <span class="n">a</span> <span class="n">c</span> <span class="n">over</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The three arguments are to the left, so we can “chop off” everything to
|
||||
the right and say it’s the definition of the <code class="docutils literal notranslate"><span class="pre">quadratic</span></code> function:</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('quadratic == over [[[neg] dupdip sqr 4] dipd * * - sqrt pm] dip 2 * [/] cons app2')
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Let’s try it out:</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('3 1 1 quadratic')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">-</span><span class="mf">0.3819660112501051</span> <span class="o">-</span><span class="mf">2.618033988749895</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If you look at the Joy evaluation trace you can see that the first few
|
||||
lines are the <code class="docutils literal notranslate"><span class="pre">dip</span></code> and <code class="docutils literal notranslate"><span class="pre">dipd</span></code> combinators building the main program
|
||||
by incorporating the values on the stack. Then that program runs and you
|
||||
get the results. This is pretty typical of Joy code.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>V('-5 1 4 quadratic')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">.</span> <span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="n">quadratic</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="mi">1</span> <span class="mi">4</span> <span class="n">quadratic</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="o">.</span> <span class="mi">4</span> <span class="n">quadratic</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">.</span> <span class="n">quadratic</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">.</span> <span class="n">over</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="mi">1</span> <span class="o">.</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="mi">1</span> <span class="p">[[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span><span class="p">]</span> <span class="o">.</span> <span class="n">dip</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">.</span> <span class="p">[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="mi">1</span> <span class="mi">4</span> <span class="p">[[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span><span class="p">]</span> <span class="o">.</span> <span class="n">dipd</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="p">[</span><span class="n">neg</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="p">[</span><span class="n">neg</span><span class="p">]</span> <span class="o">.</span> <span class="n">dupdip</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="n">neg</span> <span class="o">-</span><span class="mi">5</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="o">.</span> <span class="o">-</span><span class="mi">5</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="n">sqr</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="n">dup</span> <span class="n">mul</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="o">-</span><span class="mi">5</span> <span class="o">-</span><span class="mi">5</span> <span class="o">.</span> <span class="n">mul</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="o">.</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">4</span> <span class="o">.</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">4</span> <span class="mi">1</span> <span class="o">.</span> <span class="mi">4</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">4</span> <span class="mi">1</span> <span class="mi">4</span> <span class="o">.</span> <span class="o">*</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">4</span> <span class="mi">4</span> <span class="o">.</span> <span class="o">*</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">25</span> <span class="mi">16</span> <span class="o">.</span> <span class="o">-</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mi">9</span> <span class="o">.</span> <span class="n">sqrt</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mi">5</span> <span class="mf">3.0</span> <span class="o">.</span> <span class="n">pm</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="o">.</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="mi">1</span> <span class="o">.</span> <span class="mi">2</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="mi">1</span> <span class="mi">2</span> <span class="o">.</span> <span class="o">*</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="mi">2</span> <span class="p">[</span><span class="o">/</span><span class="p">]</span> <span class="o">.</span> <span class="n">cons</span> <span class="n">app2</span>
|
||||
<span class="mf">8.0</span> <span class="mf">2.0</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="o">.</span> <span class="n">app2</span>
|
||||
<span class="p">[</span><span class="mf">8.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">8.0</span> <span class="o">.</span> <span class="mi">2</span> <span class="o">/</span> <span class="p">[]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">8.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="o">/</span> <span class="p">[]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="o">.</span> <span class="p">[]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="p">[]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="o">.</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="p">[</span><span class="mf">2.0</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="o">/</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="mf">2.0</span> <span class="o">.</span> <span class="mi">2</span> <span class="o">/</span> <span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="mf">2.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="o">/</span> <span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="mf">1.0</span> <span class="o">.</span> <span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="mf">1.0</span> <span class="p">[</span><span class="mf">4.0</span><span class="p">]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="p">[</span><span class="mf">1.0</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span>
|
||||
<span class="mf">4.0</span> <span class="mf">1.0</span> <span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Developing.html" title="previous chapter">Developing a Program in Joy</a></li>
|
||||
<li>Next: <a href="Replacing.html" title="next chapter">Replacing Functions in the Dictionary</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,682 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Recursion Combinators — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Treating Trees I: Ordered Binary Trees" href="Ordered_Binary_Trees.html" />
|
||||
<link rel="prev" title="Replacing Functions in the Dictionary" href="Replacing.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>from notebook_preamble import D, DefinitionWrapper, J, V, define
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="recursion-combinators">
|
||||
<h1>Recursion Combinators<a class="headerlink" href="#recursion-combinators" title="Permalink to this headline">¶</a></h1>
|
||||
<p>This article describes the <code class="docutils literal notranslate"><span class="pre">genrec</span></code> combinator, how to use it, and
|
||||
several generic specializations.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="k">if</span><span class="p">]</span> <span class="p">[</span><span class="n">then</span><span class="p">]</span> <span class="p">[</span><span class="n">rec1</span><span class="p">]</span> <span class="p">[</span><span class="n">rec2</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="o">---------------------------------------------------------------------</span>
|
||||
<span class="p">[</span><span class="k">if</span><span class="p">]</span> <span class="p">[</span><span class="n">then</span><span class="p">]</span> <span class="p">[</span><span class="n">rec1</span> <span class="p">[[</span><span class="k">if</span><span class="p">]</span> <span class="p">[</span><span class="n">then</span><span class="p">]</span> <span class="p">[</span><span class="n">rec1</span><span class="p">]</span> <span class="p">[</span><span class="n">rec2</span><span class="p">]</span> <span class="n">genrec</span><span class="p">]</span> <span class="n">rec2</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>From “Recursion Theory and Joy” (j05cmp.html) by Manfred von Thun:</p>
|
||||
<blockquote>
|
||||
<div><p>“The genrec combinator takes four program parameters in addition to
|
||||
whatever data parameters it needs. Fourth from the top is an if-part,
|
||||
followed by a then-part. If the if-part yields true, then the
|
||||
then-part is executed and the combinator terminates. The other two
|
||||
parameters are the rec1-part and the rec2-part. If the if-part yields
|
||||
false, the rec1-part is executed. Following that the four program
|
||||
parameters and the combinator are again pushed onto the stack bundled
|
||||
up in a quoted form. Then the rec2-part is executed, where it will
|
||||
find the bundled form. Typically it will then execute the bundled
|
||||
form, either with i or with app2, or some other combinator.”</p>
|
||||
</div></blockquote>
|
||||
<section id="designing-recursive-functions">
|
||||
<h2>Designing Recursive Functions<a class="headerlink" href="#designing-recursive-functions" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The way to design one of these is to fix your base case and test and
|
||||
then treat <code class="docutils literal notranslate"><span class="pre">R1</span></code> and <code class="docutils literal notranslate"><span class="pre">R2</span></code> as an else-part “sandwiching” a quotation
|
||||
of the whole function.</p>
|
||||
<p>For example, given a (general recursive) function <code class="docutils literal notranslate"><span class="pre">F</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">F</span> <span class="o">==</span> <span class="p">[</span><span class="n">I</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="p">[</span><span class="n">R1</span><span class="p">]</span> <span class="p">[</span><span class="n">R2</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="o">==</span> <span class="p">[</span><span class="n">I</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="p">[</span><span class="n">R1</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">R2</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If the <code class="docutils literal notranslate"><span class="pre">[I]</span></code> predicate is false you must derive <code class="docutils literal notranslate"><span class="pre">R1</span></code> and <code class="docutils literal notranslate"><span class="pre">R2</span></code>
|
||||
from:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">...</span> <span class="n">R1</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">R2</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Set the stack arguments in front and figure out what <code class="docutils literal notranslate"><span class="pre">R1</span></code> and <code class="docutils literal notranslate"><span class="pre">R2</span></code>
|
||||
have to do to apply the quoted <code class="docutils literal notranslate"><span class="pre">[F]</span></code> in the proper way.</p>
|
||||
</section>
|
||||
<section id="primitive-recursive-functions">
|
||||
<h2>Primitive Recursive Functions<a class="headerlink" href="#primitive-recursive-functions" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Primitive recursive functions are those where <code class="docutils literal notranslate"><span class="pre">R2</span> <span class="pre">==</span> <span class="pre">i</span></code>.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">P</span> <span class="o">==</span> <span class="p">[</span><span class="n">I</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="p">[</span><span class="n">R</span><span class="p">]</span> <span class="n">primrec</span>
|
||||
<span class="o">==</span> <span class="p">[</span><span class="n">I</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="p">[</span><span class="n">R</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">i</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
<span class="o">==</span> <span class="p">[</span><span class="n">I</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="p">[</span><span class="n">R</span> <span class="n">P</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="hylomorphism">
|
||||
<h2><a class="reference external" href="https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29">Hylomorphism</a><a class="headerlink" href="#hylomorphism" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A
|
||||
<a class="reference external" href="https://en.wikipedia.org/wiki/Hylomorphism_%28computer_science%29">hylomorphism</a>
|
||||
is a recursive function <code class="docutils literal notranslate"><span class="pre">H</span> <span class="pre">::</span> <span class="pre">A</span> <span class="pre">-></span> <span class="pre">C</span></code> that converts a value of type
|
||||
<code class="docutils literal notranslate"><span class="pre">A</span></code> into a value of type <code class="docutils literal notranslate"><span class="pre">C</span></code> by means of:</p>
|
||||
<ul class="simple">
|
||||
<li><p>A generator <code class="docutils literal notranslate"><span class="pre">G</span> <span class="pre">::</span> <span class="pre">A</span> <span class="pre">-></span> <span class="pre">(B,</span> <span class="pre">A)</span></code></p></li>
|
||||
<li><p>A combiner <code class="docutils literal notranslate"><span class="pre">F</span> <span class="pre">::</span> <span class="pre">(B,</span> <span class="pre">C)</span> <span class="pre">-></span> <span class="pre">C</span></code></p></li>
|
||||
<li><p>A predicate <code class="docutils literal notranslate"><span class="pre">P</span> <span class="pre">::</span> <span class="pre">A</span> <span class="pre">-></span> <span class="pre">Bool</span></code> to detect the base case</p></li>
|
||||
<li><p>A base case value <code class="docutils literal notranslate"><span class="pre">c</span> <span class="pre">::</span> <span class="pre">C</span></code></p></li>
|
||||
<li><p>Recursive calls (zero or more); it has a “call stack in the form of a
|
||||
cons list”.</p></li>
|
||||
</ul>
|
||||
<p>It may be helpful to see this function implemented in imperative Python
|
||||
code.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>def hylomorphism(c, F, P, G):
|
||||
'''Return a hylomorphism function H.'''
|
||||
|
||||
def H(a):
|
||||
if P(a):
|
||||
result = c
|
||||
else:
|
||||
b, aa = G(a)
|
||||
result = F(b, H(aa)) # b is stored in the stack frame during recursive call to H().
|
||||
return result
|
||||
|
||||
return H
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Cf. <a class="reference external" href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125">“Bananas, Lenses, & Barbed
|
||||
Wire”</a></p>
|
||||
<p>Note that during evaluation of <code class="docutils literal notranslate"><span class="pre">H()</span></code> the intermediate <code class="docutils literal notranslate"><span class="pre">b</span></code> values are
|
||||
stored in the Python call stack. This is what is meant by “call stack in
|
||||
the form of a cons list”.</p>
|
||||
</section>
|
||||
<section id="hylomorphism-in-joy">
|
||||
<h2>Hylomorphism in Joy<a class="headerlink" href="#hylomorphism-in-joy" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We can define a combinator <code class="docutils literal notranslate"><span class="pre">hylomorphism</span></code> that will make a
|
||||
hylomorphism combinator <code class="docutils literal notranslate"><span class="pre">H</span></code> from constituent parts.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">c</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">hylomorphism</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The function <code class="docutils literal notranslate"><span class="pre">H</span></code> is recursive, so we start with <code class="docutils literal notranslate"><span class="pre">ifte</span></code> and set the
|
||||
else-part to some function <code class="docutils literal notranslate"><span class="pre">J</span></code> that will contain a quoted copy of
|
||||
<code class="docutils literal notranslate"><span class="pre">H</span></code>. (The then-part just discards the leftover <code class="docutils literal notranslate"><span class="pre">a</span></code> and replaces it
|
||||
with the base case value <code class="docutils literal notranslate"><span class="pre">c</span></code>.)</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">J</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The else-part <code class="docutils literal notranslate"><span class="pre">J</span></code> gets just the argument <code class="docutils literal notranslate"><span class="pre">a</span></code> on the stack.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">a</span> <span class="n">J</span>
|
||||
<span class="n">a</span> <span class="n">G</span> <span class="n">The</span> <span class="n">first</span> <span class="n">thing</span> <span class="n">to</span> <span class="n">do</span> <span class="ow">is</span> <span class="n">use</span> <span class="n">the</span> <span class="n">generator</span> <span class="n">G</span>
|
||||
<span class="n">aa</span> <span class="n">b</span> <span class="n">which</span> <span class="n">produces</span> <span class="n">b</span> <span class="ow">and</span> <span class="n">a</span> <span class="n">new</span> <span class="n">aa</span>
|
||||
<span class="n">aa</span> <span class="n">b</span> <span class="p">[</span><span class="n">H</span><span class="p">]</span> <span class="n">dip</span> <span class="n">we</span> <span class="n">recur</span> <span class="k">with</span> <span class="n">H</span> <span class="n">on</span> <span class="n">the</span> <span class="n">new</span> <span class="n">aa</span>
|
||||
<span class="n">aa</span> <span class="n">H</span> <span class="n">b</span> <span class="n">F</span> <span class="ow">and</span> <span class="n">run</span> <span class="n">F</span> <span class="n">on</span> <span class="n">the</span> <span class="n">result</span><span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This gives us a definition for <code class="docutils literal notranslate"><span class="pre">J</span></code>.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">J</span> <span class="o">==</span> <span class="n">G</span> <span class="p">[</span><span class="n">H</span><span class="p">]</span> <span class="n">dip</span> <span class="n">F</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Plug it in and convert to genrec.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span> <span class="p">[</span><span class="n">H</span><span class="p">]</span> <span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
<span class="n">H</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This is the form of a hylomorphism in Joy, which nicely illustrates that
|
||||
it is a simple specialization of the general recursion combinator.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">c</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">hylomorphism</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="derivation-of-hylomorphism-combinator">
|
||||
<h2>Derivation of <code class="docutils literal notranslate"><span class="pre">hylomorphism</span></code> combinator<a class="headerlink" href="#derivation-of-hylomorphism-combinator" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Now we just need to derive a definition that builds the <code class="docutils literal notranslate"><span class="pre">genrec</span></code>
|
||||
arguments out of the pieces given to the <code class="docutils literal notranslate"><span class="pre">hylomorphism</span></code> combinator.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">c</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">hylomorphism</span>
|
||||
<span class="o">------------------------------------------</span>
|
||||
<span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Working in reverse:</p>
|
||||
<ul class="simple">
|
||||
<li><p>Use <code class="docutils literal notranslate"><span class="pre">swoncat</span></code> twice to decouple <code class="docutils literal notranslate"><span class="pre">[c]</span></code> and <code class="docutils literal notranslate"><span class="pre">[F]</span></code>.</p></li>
|
||||
<li><p>Use <code class="docutils literal notranslate"><span class="pre">unit</span></code> to dequote <code class="docutils literal notranslate"><span class="pre">c</span></code>.</p></li>
|
||||
<li><p>Use <code class="docutils literal notranslate"><span class="pre">dipd</span></code> to untangle <code class="docutils literal notranslate"><span class="pre">[unit</span> <span class="pre">[pop]</span> <span class="pre">swoncat]</span></code> from the givens.</p></li>
|
||||
</ul>
|
||||
<p>So:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="n">swoncat</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span><span class="p">]</span> <span class="n">swoncat</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">c</span> <span class="n">unit</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="n">swoncat</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span><span class="p">]</span> <span class="n">swoncat</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">c</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">unit</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="n">swoncat</span><span class="p">]</span> <span class="n">dipd</span> <span class="p">[</span><span class="n">dip</span><span class="p">]</span> <span class="n">swoncat</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>At this point all of the arguments (givens) to the hylomorphism are to
|
||||
the left so we have a definition for <code class="docutils literal notranslate"><span class="pre">hylomorphism</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">hylomorphism</span> <span class="o">==</span> <span class="p">[</span><span class="n">unit</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="n">swoncat</span><span class="p">]</span> <span class="n">dipd</span> <span class="p">[</span><span class="n">dip</span><span class="p">]</span> <span class="n">swoncat</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('hylomorphism == [unit [pop] swoncat] dipd [dip] swoncat genrec')
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="example-finding-triangular-numbers">
|
||||
<h3>Example: Finding <a class="reference external" href="https://en.wikipedia.org/wiki/Triangular_number">Triangular Numbers</a><a class="headerlink" href="#example-finding-triangular-numbers" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Let’s write a function that, given a positive integer, returns the sum
|
||||
of all positive integers less than that one. (In this case the types
|
||||
<code class="docutils literal notranslate"><span class="pre">A</span></code>, <code class="docutils literal notranslate"><span class="pre">B</span></code> and <code class="docutils literal notranslate"><span class="pre">C</span></code> are all <code class="docutils literal notranslate"><span class="pre">int</span></code>.)</p>
|
||||
<p>To sum a range of integers from 0 to <em>n</em> - 1:</p>
|
||||
<ul class="simple">
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">[P]</span></code> is <code class="docutils literal notranslate"><span class="pre">[1</span> <span class="pre"><=]</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">c</span></code> is <code class="docutils literal notranslate"><span class="pre">0</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">[G]</span></code> is <code class="docutils literal notranslate"><span class="pre">[--</span> <span class="pre">dup]</span></code></p></li>
|
||||
<li><p><code class="docutils literal notranslate"><span class="pre">[F]</span></code> is <code class="docutils literal notranslate"><span class="pre">[+]</span></code></p></li>
|
||||
</ul>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('triangular_number == [1 <=] 0 [-- dup] [+] hylomorphism')
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Let’s try it:</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('5 triangular_number')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">10</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[0 1 2 3 4 5 6] [triangular_number] map')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">0</span> <span class="mi">0</span> <span class="mi">1</span> <span class="mi">3</span> <span class="mi">6</span> <span class="mi">10</span> <span class="mi">15</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="four-specializations">
|
||||
<h2>Four Specializations<a class="headerlink" href="#four-specializations" title="Permalink to this headline">¶</a></h2>
|
||||
<p>There are at least four kinds of recursive combinator, depending on two
|
||||
choices. The first choice is whether the combiner function <code class="docutils literal notranslate"><span class="pre">F</span></code> should
|
||||
be evaluated during the recursion or pushed into the pending expression
|
||||
to be “collapsed” at the end. The second choice is whether the combiner
|
||||
needs to operate on the current value of the datastructure or the
|
||||
generator’s output, in other words, whether <code class="docutils literal notranslate"><span class="pre">F</span></code> or <code class="docutils literal notranslate"><span class="pre">G</span></code> should run
|
||||
first in the recursive branch.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H1</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span> <span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="n">H2</span> <span class="o">==</span> <span class="n">c</span> <span class="n">swap</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">dip</span> <span class="p">]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="n">H3</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="n">dupdip</span> <span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="n">H4</span> <span class="o">==</span> <span class="n">c</span> <span class="n">swap</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="p">[</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The working of the generator function <code class="docutils literal notranslate"><span class="pre">G</span></code> differs slightly for each.
|
||||
Consider the recursive branches:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>... a G [H1] dip F w/ a G == a′ b
|
||||
|
||||
... c a G [F] dip H2 a G == b a′
|
||||
|
||||
... a [G] dupdip [H3] dip F a G == a′
|
||||
|
||||
... c a [F] dupdip G H4 a G == a′
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The following four sections illustrate how these work, omitting the
|
||||
predicate evaluation.</p>
|
||||
<section id="h1">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">H1</span></code><a class="headerlink" href="#h1" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H1</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Iterate n times.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>... a G [H1] dip F
|
||||
... a′ b [H1] dip F
|
||||
... a′ H1 b F
|
||||
... a′ G [H1] dip F b F
|
||||
... a″ b′ [H1] dip F b F
|
||||
... a″ H1 b′ F b F
|
||||
... a″ G [H1] dip F b′ F b F
|
||||
... a‴ b″ [H1] dip F b′ F b F
|
||||
... a‴ H1 b″ F b′ F b F
|
||||
... a‴ pop c b″ F b′ F b F
|
||||
... c b″ F b′ F b F
|
||||
... d b′ F b F
|
||||
... d′ b F
|
||||
... d″
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This form builds up a pending expression (continuation) that contains
|
||||
the intermediate results along with the pending combiner functions. When
|
||||
the base case is reached the last term is replaced by the identity value
|
||||
<code class="docutils literal notranslate"><span class="pre">c</span></code> and the continuation “collapses” into the final result using the
|
||||
combiner <code class="docutils literal notranslate"><span class="pre">F</span></code>.</p>
|
||||
</section>
|
||||
<section id="h2">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">H2</span></code><a class="headerlink" href="#h2" title="Permalink to this headline">¶</a></h3>
|
||||
<p>When you can start with the identity value <code class="docutils literal notranslate"><span class="pre">c</span></code> on the stack and the
|
||||
combiner <code class="docutils literal notranslate"><span class="pre">F</span></code> can operate as you go using the intermediate results
|
||||
immediately rather than queuing them up, use this form. An important
|
||||
difference is that the generator function must return its results in the
|
||||
reverse order.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>H2 == c swap [P] [pop] [G [F] dip] primrec
|
||||
|
||||
... c a G [F] dip H2
|
||||
... c b a′ [F] dip H2
|
||||
... c b F a′ H2
|
||||
... d a′ H2
|
||||
... d a′ G [F] dip H2
|
||||
... d b′ a″ [F] dip H2
|
||||
... d b′ F a″ H2
|
||||
... d′ a″ H2
|
||||
... d′ a″ G [F] dip H2
|
||||
... d′ b″ a‴ [F] dip H2
|
||||
... d′ b″ F a‴ H2
|
||||
... d″ a‴ H2
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="h3">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">H3</span></code><a class="headerlink" href="#h3" title="Permalink to this headline">¶</a></h3>
|
||||
<p>If you examine the traces above you’ll see that the combiner <code class="docutils literal notranslate"><span class="pre">F</span></code> only
|
||||
gets to operate on the results of <code class="docutils literal notranslate"><span class="pre">G</span></code>, it never “sees” the first value
|
||||
<code class="docutils literal notranslate"><span class="pre">a</span></code>. If the combiner and the generator both need to work on the
|
||||
current value then <code class="docutils literal notranslate"><span class="pre">dup</span></code> must be used, and the generator must produce
|
||||
one item instead of two (the b is instead the duplicate of a.)</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>H3 == [P] [pop c] [[G] dupdip] [dip F] genrec
|
||||
|
||||
... a [G] dupdip [H3] dip F
|
||||
... a G a [H3] dip F
|
||||
... a′ a [H3] dip F
|
||||
... a′ H3 a F
|
||||
... a′ [G] dupdip [H3] dip F a F
|
||||
... a′ G a′ [H3] dip F a F
|
||||
... a″ a′ [H3] dip F a F
|
||||
... a″ H3 a′ F a F
|
||||
... a″ [G] dupdip [H3] dip F a′ F a F
|
||||
... a″ G a″ [H3] dip F a′ F a F
|
||||
... a‴ a″ [H3] dip F a′ F a F
|
||||
... a‴ H3 a″ F a′ F a F
|
||||
... a‴ pop c a″ F a′ F a F
|
||||
... c a″ F a′ F a F
|
||||
... d a′ F a F
|
||||
... d′ a F
|
||||
... d″
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="h4">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">H4</span></code><a class="headerlink" href="#h4" title="Permalink to this headline">¶</a></h3>
|
||||
<p>And, last but not least, if you can combine as you go, starting with
|
||||
<code class="docutils literal notranslate"><span class="pre">c</span></code>, and the combiner <code class="docutils literal notranslate"><span class="pre">F</span></code> needs to work on the current item, this is
|
||||
the form:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>H4 == c swap [P] [pop] [[F] dupdip G] primrec
|
||||
|
||||
... c a [F] dupdip G H4
|
||||
... c a F a G H4
|
||||
... d a G H4
|
||||
... d a′ H4
|
||||
... d a′ [F] dupdip G H4
|
||||
... d a′ F a′ G H4
|
||||
... d′ a′ G H4
|
||||
... d′ a″ H4
|
||||
... d′ a″ [F] dupdip G H4
|
||||
... d′ a″ F a″ G H4
|
||||
... d″ a″ G H4
|
||||
... d″ a‴ H4
|
||||
... d″ a‴ pop
|
||||
... d″
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="anamorphism">
|
||||
<h2>Anamorphism<a class="headerlink" href="#anamorphism" title="Permalink to this headline">¶</a></h2>
|
||||
<p>An anamorphism can be defined as a hylomorphism that uses <code class="docutils literal notranslate"><span class="pre">[]</span></code> for
|
||||
<code class="docutils literal notranslate"><span class="pre">c</span></code> and <code class="docutils literal notranslate"><span class="pre">swons</span></code> for <code class="docutils literal notranslate"><span class="pre">F</span></code>. An anamorphic function builds a list of
|
||||
values.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">A</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[]</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">swons</span><span class="p">]</span> <span class="n">hylomorphism</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="range-et-al-an-example-of-an-anamorphism-is-the-range-function-which-generates-the-list-of-integers-from-0-to-n-1-given-n">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">range</span></code> et. al. An example of an anamorphism is the <code class="docutils literal notranslate"><span class="pre">range</span></code> function which generates the list of integers from 0 to <em>n</em> - 1 given <em>n</em>.<a class="headerlink" href="#range-et-al-an-example-of-an-anamorphism-is-the-range-function-which-generates-the-list-of-integers-from-0-to-n-1-given-n" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Each of the above variations can be used to make four slightly different
|
||||
<code class="docutils literal notranslate"><span class="pre">range</span></code> functions.</p>
|
||||
<section id="range-with-h1">
|
||||
<h4><code class="docutils literal notranslate"><span class="pre">range</span></code> with <code class="docutils literal notranslate"><span class="pre">H1</span></code><a class="headerlink" href="#range-with-h1" title="Permalink to this headline">¶</a></h4>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H1</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="o">==</span> <span class="p">[</span><span class="mi">0</span> <span class="o"><=</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="p">[]]</span> <span class="p">[</span><span class="o">--</span> <span class="n">dup</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">swons</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('range == [0 <=] [] [-- dup] [swons] hylomorphism')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('5 range')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">4</span> <span class="mi">3</span> <span class="mi">2</span> <span class="mi">1</span> <span class="mi">0</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="range-with-h2">
|
||||
<h4><code class="docutils literal notranslate"><span class="pre">range</span></code> with <code class="docutils literal notranslate"><span class="pre">H2</span></code><a class="headerlink" href="#range-with-h2" title="Permalink to this headline">¶</a></h4>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H2</span> <span class="o">==</span> <span class="n">c</span> <span class="n">swap</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="n">primrec</span>
|
||||
<span class="o">==</span> <span class="p">[]</span> <span class="n">swap</span> <span class="p">[</span><span class="mi">0</span> <span class="o"><=</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="p">[</span><span class="o">--</span> <span class="n">dup</span> <span class="p">[</span><span class="n">swons</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="n">primrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('range_reverse == [] swap [0 <=] [pop] [-- dup [swons] dip] primrec')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('5 range_reverse')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">0</span> <span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="range-with-h3">
|
||||
<h4><code class="docutils literal notranslate"><span class="pre">range</span></code> with <code class="docutils literal notranslate"><span class="pre">H3</span></code><a class="headerlink" href="#range-with-h3" title="Permalink to this headline">¶</a></h4>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H3</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span><span class="p">]</span> <span class="p">[[</span><span class="n">G</span><span class="p">]</span> <span class="n">dupdip</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="o">==</span> <span class="p">[</span><span class="mi">0</span> <span class="o"><=</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="p">[]]</span> <span class="p">[[</span><span class="o">--</span><span class="p">]</span> <span class="n">dupdip</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">swons</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('ranger == [0 <=] [pop []] [[--] dupdip] [dip swons] genrec')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('5 ranger')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">5</span> <span class="mi">4</span> <span class="mi">3</span> <span class="mi">2</span> <span class="mi">1</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="range-with-h4">
|
||||
<h4><code class="docutils literal notranslate"><span class="pre">range</span></code> with <code class="docutils literal notranslate"><span class="pre">H4</span></code><a class="headerlink" href="#range-with-h4" title="Permalink to this headline">¶</a></h4>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H4</span> <span class="o">==</span> <span class="n">c</span> <span class="n">swap</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="p">[[</span><span class="n">F</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">G</span> <span class="p">]</span> <span class="n">primrec</span>
|
||||
<span class="o">==</span> <span class="p">[]</span> <span class="n">swap</span> <span class="p">[</span><span class="mi">0</span> <span class="o"><=</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="p">[[</span><span class="n">swons</span><span class="p">]</span> <span class="n">dupdip</span> <span class="o">--</span><span class="p">]</span> <span class="n">primrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('ranger_reverse == [] swap [0 <=] [pop] [[swons] dupdip --] primrec')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('5 ranger_reverse')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span> <span class="mi">5</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Hopefully this illustrates the workings of the variations. For more
|
||||
insight you can run the cells using the <code class="docutils literal notranslate"><span class="pre">V()</span></code> function instead of the
|
||||
<code class="docutils literal notranslate"><span class="pre">J()</span></code> function to get a trace of the Joy evaluation.</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
<section id="catamorphism">
|
||||
<h2>Catamorphism<a class="headerlink" href="#catamorphism" title="Permalink to this headline">¶</a></h2>
|
||||
<p>A catamorphism can be defined as a hylomorphism that uses
|
||||
<code class="docutils literal notranslate"><span class="pre">[uncons</span> <span class="pre">swap]</span></code> for <code class="docutils literal notranslate"><span class="pre">[G]</span></code> and <code class="docutils literal notranslate"><span class="pre">[[]</span> <span class="pre">=]</span></code> (or just <code class="docutils literal notranslate"><span class="pre">[not]</span></code>) for the
|
||||
predicate <code class="docutils literal notranslate"><span class="pre">[P]</span></code>. A catamorphic function tears down a list term-by-term
|
||||
and makes some new value.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">C</span> <span class="o">==</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="n">c</span> <span class="p">[</span><span class="n">uncons</span> <span class="n">swap</span><span class="p">]</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">hylomorphism</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('swuncons == uncons swap') # Awkward name.
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>An example of a catamorphism is the sum function.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nb">sum</span> <span class="o">==</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="mi">0</span> <span class="p">[</span><span class="n">swuncons</span><span class="p">]</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">hylomorphism</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('sum == [not] 0 [swuncons] [+] hylomorphism')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[5 4 3 2 1] sum')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">15</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="the-step-combinator">
|
||||
<h3>The <code class="docutils literal notranslate"><span class="pre">step</span></code> combinator<a class="headerlink" href="#the-step-combinator" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">step</span></code> combinator will usually be better to use than
|
||||
<code class="docutils literal notranslate"><span class="pre">catamorphism</span></code>.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[step] help')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Run</span> <span class="n">a</span> <span class="n">quoted</span> <span class="n">program</span> <span class="n">on</span> <span class="n">each</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">a</span> <span class="n">sequence</span><span class="o">.</span>
|
||||
<span class="p">::</span>
|
||||
|
||||
<span class="o">...</span> <span class="p">[]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="o">.</span> <span class="n">step</span>
|
||||
<span class="o">-----------------------</span>
|
||||
<span class="o">...</span> <span class="o">.</span>
|
||||
|
||||
|
||||
<span class="o">...</span> <span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="o">.</span> <span class="n">step</span>
|
||||
<span class="o">------------------------</span>
|
||||
<span class="o">...</span> <span class="n">a</span> <span class="o">.</span> <span class="n">Q</span>
|
||||
|
||||
|
||||
<span class="o">...</span> <span class="p">[</span><span class="n">a</span> <span class="n">b</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="o">.</span> <span class="n">step</span>
|
||||
<span class="o">----------------------------------------</span>
|
||||
<span class="o">...</span> <span class="n">a</span> <span class="o">.</span> <span class="n">Q</span> <span class="p">[</span><span class="n">b</span> <span class="n">c</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">step</span>
|
||||
|
||||
<span class="n">The</span> <span class="n">step</span> <span class="n">combinator</span> <span class="n">executes</span> <span class="n">the</span> <span class="n">quotation</span> <span class="n">on</span> <span class="n">each</span> <span class="n">member</span> <span class="n">of</span> <span class="n">the</span> <span class="nb">list</span>
|
||||
<span class="n">on</span> <span class="n">top</span> <span class="n">of</span> <span class="n">the</span> <span class="n">stack</span><span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('sum == 0 swap [+] step')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[5 4 3 2 1] sum')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">15</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="example-factorial-function">
|
||||
<h2>Example: Factorial Function<a class="headerlink" href="#example-factorial-function" title="Permalink to this headline">¶</a></h2>
|
||||
<p>For the Factorial function:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H4</span> <span class="o">==</span> <span class="n">c</span> <span class="n">swap</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="p">[[</span><span class="n">F</span><span class="p">]</span> <span class="n">dupdip</span> <span class="n">G</span><span class="p">]</span> <span class="n">primrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>With:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">c</span> <span class="o">==</span> <span class="mi">1</span>
|
||||
<span class="n">F</span> <span class="o">==</span> <span class="o">*</span>
|
||||
<span class="n">G</span> <span class="o">==</span> <span class="o">--</span>
|
||||
<span class="n">P</span> <span class="o">==</span> <span class="mi">1</span> <span class="o"><=</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('factorial == 1 swap [1 <=] [pop] [[*] dupdip --] primrec')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('5 factorial')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">120</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="example-tails">
|
||||
<h2>Example: <code class="docutils literal notranslate"><span class="pre">tails</span></code><a class="headerlink" href="#example-tails" title="Permalink to this headline">¶</a></h2>
|
||||
<p>An example of a paramorphism for lists given in the <a class="reference external" href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125">“Bananas…”
|
||||
paper</a>
|
||||
is <code class="docutils literal notranslate"><span class="pre">tails</span></code> which returns the list of “tails” of a list.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="mi">1</span> <span class="mi">2</span> <span class="mi">3</span><span class="p">]</span> <span class="n">tails</span>
|
||||
<span class="o">--------------------</span>
|
||||
<span class="p">[[]</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="mi">3</span><span class="p">]]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We can build as we go, and we want <code class="docutils literal notranslate"><span class="pre">F</span></code> to run after <code class="docutils literal notranslate"><span class="pre">G</span></code>, so we use
|
||||
pattern <code class="docutils literal notranslate"><span class="pre">H2</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H2</span> <span class="o">==</span> <span class="n">c</span> <span class="n">swap</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span><span class="p">]</span> <span class="p">[</span><span class="n">G</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="n">primrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We would use:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">c</span> <span class="o">==</span> <span class="p">[]</span>
|
||||
<span class="n">F</span> <span class="o">==</span> <span class="n">swons</span>
|
||||
<span class="n">G</span> <span class="o">==</span> <span class="n">rest</span> <span class="n">dup</span>
|
||||
<span class="n">P</span> <span class="o">==</span> <span class="ow">not</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('tails == [] swap [not] [pop] [rest dup [swons] dip] primrec')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[1 2 3] tails')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[]</span> <span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="p">[</span><span class="mi">2</span> <span class="mi">3</span><span class="p">]]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="conclusion-patterns-of-recursion">
|
||||
<h2>Conclusion: Patterns of Recursion<a class="headerlink" href="#conclusion-patterns-of-recursion" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Our story so far…</p>
|
||||
<section id="hylo-ana-cata">
|
||||
<h3>Hylo-, Ana-, Cata-<a class="headerlink" href="#hylo-ana-cata" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">H</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span> <span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span> <span class="p">]</span> <span class="p">[</span><span class="n">G</span> <span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span> <span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="n">A</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span> <span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="p">[]]</span> <span class="p">[</span><span class="n">G</span> <span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">swap</span> <span class="n">cons</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="n">C</span> <span class="o">==</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="n">c</span> <span class="p">]</span> <span class="p">[</span><span class="n">uncons</span> <span class="n">swap</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span> <span class="n">F</span> <span class="p">]</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="para">
|
||||
<h3>Para-, ?-, ?-<a class="headerlink" href="#para" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>P == c swap [P ] [pop] [[F ] dupdip G ] primrec
|
||||
? == [] swap [P ] [pop] [[swap cons] dupdip G ] primrec
|
||||
? == c swap [not] [pop] [[F ] dupdip uncons swap] primrec
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="appendix-fun-with-symbols">
|
||||
<h2>Appendix: Fun with Symbols<a class="headerlink" href="#appendix-fun-with-symbols" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>|[ (c, F), (G, P) ]| == (|c, F|) • [(G, P)]
|
||||
</pre></div>
|
||||
</div>
|
||||
<p><a class="reference external" href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.41.125">“Bananas, Lenses, & Barbed
|
||||
Wire”</a></p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="o">|...|</span><span class="p">)</span> <span class="p">[(</span><span class="o">...</span><span class="p">)]</span> <span class="p">[</span><span class="o"><...></span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>I think they are having slightly too much fun with the symbols. However,
|
||||
“Too much is always better than not enough.”</p>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Replacing.html" title="previous chapter">Replacing Functions in the Dictionary</a></li>
|
||||
<li>Next: <a href="Ordered_Binary_Trees.html" title="next chapter">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Replacing Functions in the Dictionary — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Recursion Combinators" href="Recursion_Combinators.html" />
|
||||
<link rel="prev" title="Quadratic formula" href="Quadratic.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="replacing-functions-in-the-dictionary">
|
||||
<h1>Replacing Functions in the Dictionary<a class="headerlink" href="#replacing-functions-in-the-dictionary" title="Permalink to this headline">¶</a></h1>
|
||||
<p>For now, there is no way to define new functions from within the Joy
|
||||
language. All functions (and the interpreter) all accept and return a
|
||||
dictionary parameter (in addition to the stack and expression) so that
|
||||
we can implement e.g. a function that adds new functions to the
|
||||
dictionary. However, there’s no function that does that. Adding a new
|
||||
function to the dictionary is a meta-interpreter action, you have to do
|
||||
it in Python, not Joy.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>from notebook_preamble import D, J, V
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="a-long-trace">
|
||||
<h2>A long trace<a class="headerlink" href="#a-long-trace" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>V('[23 18] average')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">.</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="n">average</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="n">average</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="n">cleave</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="n">cleave</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="o">.</span> <span class="n">cleave</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">app2</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">.</span> <span class="n">app2</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="o">.</span> <span class="n">i</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">41</span> <span class="o">.</span> <span class="mf">1.0</span> <span class="o">*</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">41</span> <span class="mf">1.0</span> <span class="o">.</span> <span class="o">*</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mf">41.0</span> <span class="o">.</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mf">41.0</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="mf">41.0</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="o">.</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="o">.</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="o">.</span> <span class="n">i</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="n">size</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="mi">0</span> <span class="n">swap</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mi">0</span> <span class="o">.</span> <span class="n">swap</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="o">.</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">0</span> <span class="mi">23</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="o">.</span> <span class="n">i</span> <span class="p">[</span><span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">0</span> <span class="mi">23</span> <span class="o">.</span> <span class="n">pop</span> <span class="o">++</span> <span class="p">[</span><span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">0</span> <span class="o">.</span> <span class="o">++</span> <span class="p">[</span><span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">1</span> <span class="o">.</span> <span class="p">[</span><span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">1</span> <span class="p">[</span><span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">1</span> <span class="p">[</span><span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="o">.</span> <span class="n">step</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">1</span> <span class="mi">18</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="o">.</span> <span class="n">i</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">1</span> <span class="mi">18</span> <span class="o">.</span> <span class="n">pop</span> <span class="o">++</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">1</span> <span class="o">.</span> <span class="o">++</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">2</span> <span class="o">.</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">2</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="mi">2</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="o">.</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="o">.</span> <span class="n">popd</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="mf">41.0</span> <span class="o">.</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="mf">41.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="o">/</span>
|
||||
<span class="mf">20.5</span> <span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="replacing-size-with-a-python-version">
|
||||
<h2>Replacing <code class="docutils literal notranslate"><span class="pre">size</span></code> with a Python version<a class="headerlink" href="#replacing-size-with-a-python-version" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Both <code class="docutils literal notranslate"><span class="pre">sum</span></code> and <code class="docutils literal notranslate"><span class="pre">size</span></code> each convert a sequence to a single value.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="nb">sum</span> <span class="o">==</span> <span class="mi">0</span> <span class="n">swap</span> <span class="p">[</span><span class="o">+</span><span class="p">]</span> <span class="n">step</span>
|
||||
<span class="n">size</span> <span class="o">==</span> <span class="mi">0</span> <span class="n">swap</span> <span class="p">[</span><span class="n">pop</span> <span class="o">++</span><span class="p">]</span> <span class="n">step</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>An efficient <code class="docutils literal notranslate"><span class="pre">sum</span></code> function is already in the library. But for
|
||||
<code class="docutils literal notranslate"><span class="pre">size</span></code> we can use a “compiled” version hand-written in Python to speed
|
||||
up evaluation and make the trace more readable.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>from joy.library import SimpleFunctionWrapper
|
||||
from joy.utils.stack import iter_stack
|
||||
|
||||
|
||||
@SimpleFunctionWrapper
|
||||
def size(stack):
|
||||
'''Return the size of the sequence on the stack.'''
|
||||
sequence, stack = stack
|
||||
n = 0
|
||||
for _ in iter_stack(sequence):
|
||||
n += 1
|
||||
return n, stack
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Now we replace the old version in the dictionary with the new version,
|
||||
and re-evaluate the expression.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>D['size'] = size
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="a-shorter-trace">
|
||||
<h2>A shorter trace<a class="headerlink" href="#a-shorter-trace" title="Permalink to this headline">¶</a></h2>
|
||||
<p>You can see that <code class="docutils literal notranslate"><span class="pre">size</span></code> now executes in a single step.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>V('[23 18] average')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">.</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="n">average</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="n">average</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="n">cleave</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="n">cleave</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="o">.</span> <span class="n">cleave</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="o">.</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">app2</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">.</span> <span class="n">app2</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span><span class="p">]</span> <span class="o">.</span> <span class="n">i</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="nb">sum</span> <span class="mf">1.0</span> <span class="o">*</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">41</span> <span class="o">.</span> <span class="mf">1.0</span> <span class="o">*</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">41</span> <span class="mf">1.0</span> <span class="o">.</span> <span class="o">*</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mf">41.0</span> <span class="o">.</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mf">41.0</span> <span class="p">[[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="mf">41.0</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="o">.</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="o">.</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="p">[[</span><span class="n">size</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">.</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="p">[</span><span class="n">size</span><span class="p">]</span> <span class="o">.</span> <span class="n">i</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="o">.</span> <span class="n">size</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">2</span> <span class="o">.</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="mi">2</span> <span class="p">[</span><span class="mf">41.0</span> <span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]]</span> <span class="o">.</span> <span class="n">swaack</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">.</span> <span class="n">first</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="mi">2</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="o">.</span> <span class="n">dip</span> <span class="o">/</span>
|
||||
<span class="p">[</span><span class="mi">23</span> <span class="mi">18</span><span class="p">]</span> <span class="mf">41.0</span> <span class="o">.</span> <span class="n">popd</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="mf">41.0</span> <span class="o">.</span> <span class="mi">2</span> <span class="o">/</span>
|
||||
<span class="mf">41.0</span> <span class="mi">2</span> <span class="o">.</span> <span class="o">/</span>
|
||||
<span class="mf">20.5</span> <span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Quadratic.html" title="previous chapter">Quadratic formula</a></li>
|
||||
<li>Next: <a href="Recursion_Combinators.html" title="next chapter">Recursion Combinators</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,463 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Square Spiral Example Joy Code — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Traversing Datastructures with Zippers" href="Zipper.html" />
|
||||
<link rel="prev" title="Newton’s method" href="Newton-Raphson.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>from notebook_preamble import J, V, define
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="square-spiral-example-joy-code">
|
||||
<h1>Square Spiral Example Joy Code<a class="headerlink" href="#square-spiral-example-joy-code" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Here is the example of Joy code from the <code class="docutils literal notranslate"><span class="pre">README</span></code> file:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>[[[abs]ii <=][[<>][pop !-]||]&&][[!-][[++]][[--]]ifte dip][[pop !-][--][++]ifte]ifte
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>It might seem unreadable but with a little familiarity it becomes just
|
||||
as legible as any other notation. Some layout helps:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>[ [[abs] ii <=]
|
||||
[
|
||||
[<>] [pop !-] ||
|
||||
] &&
|
||||
]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This function accepts two integers on the stack and increments or
|
||||
decrements one of them such that the new pair of numbers is the next
|
||||
coordinate pair in a square spiral (like the kind used to construct an
|
||||
Ulam Spiral).</p>
|
||||
<section id="original-form">
|
||||
<h2>Original Form<a class="headerlink" href="#original-form" title="Permalink to this headline">¶</a></h2>
|
||||
<p>It’s adapted from <a class="reference external" href="https://stackoverflow.com/questions/398299/looping-in-a-spiral/31864777#31864777">the original code on
|
||||
StackOverflow</a>:</p>
|
||||
<blockquote>
|
||||
<div><p>If all you’re trying to do is generate the first N points in the
|
||||
spiral (without the original problem’s constraint of masking to an N
|
||||
x M region), the code becomes very simple:</p>
|
||||
</div></blockquote>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>void spiral(const int N)
|
||||
{
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for(int i = 0; i < N; ++i)
|
||||
{
|
||||
cout << x << '\t' << y << '\n';
|
||||
if(abs(x) <= abs(y) && (x != y || x >= 0))
|
||||
x += ((y >= 0) ? 1 : -1);
|
||||
else
|
||||
y += ((x >= 0) ? -1 : 1);
|
||||
}
|
||||
}
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="translation-to-joy">
|
||||
<h2>Translation to Joy<a class="headerlink" href="#translation-to-joy" title="Permalink to this headline">¶</a></h2>
|
||||
<p>I’m going to make a function that take two ints (<code class="docutils literal notranslate"><span class="pre">x</span></code> and <code class="docutils literal notranslate"><span class="pre">y</span></code>) and
|
||||
generates the next pair, we’ll turn it into a generator later using the
|
||||
<code class="docutils literal notranslate"><span class="pre">x</span></code> combinator.</p>
|
||||
<section id="first-boolean-predicate">
|
||||
<h3>First Boolean Predicate<a class="headerlink" href="#first-boolean-predicate" title="Permalink to this headline">¶</a></h3>
|
||||
<p>We need a function that computes <code class="docutils literal notranslate"><span class="pre">abs(x)</span> <span class="pre"><=</span> <span class="pre">abs(y)</span></code>, we can use <code class="docutils literal notranslate"><span class="pre">ii</span></code>
|
||||
to apply <code class="docutils literal notranslate"><span class="pre">abs</span></code> to both values and then compare them with <code class="docutils literal notranslate"><span class="pre"><=</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="nb">abs</span><span class="p">]</span> <span class="n">ii</span> <span class="o"><=</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>I’ve defined two short-circuiting Boolean combinators <code class="docutils literal notranslate"><span class="pre">&&</span></code> and <code class="docutils literal notranslate"><span class="pre">||</span></code>
|
||||
that each accept two quoted predicate programs, run the first, and
|
||||
conditionally run the second only if required (to compute the final
|
||||
Boolean value). They run their predicate arguments <code class="docutils literal notranslate"><span class="pre">nullary</span></code>.</p>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>define('&& [nullary] cons [nullary [0]] dip branch')
|
||||
define('|| [nullary] cons [nullary] dip [1] branch')
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Given those, we can define <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">!=</span> <span class="pre">y</span> <span class="pre">||</span> <span class="pre">x</span> <span class="pre">>=</span> <span class="pre">0</span></code> as:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="o"><></span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="mi">0</span> <span class="o">>=</span><span class="p">]</span> <span class="o">||</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>And <code class="docutils literal notranslate"><span class="pre">(abs(x)</span> <span class="pre"><=</span> <span class="pre">abs(y)</span> <span class="pre">&&</span> <span class="pre">(x</span> <span class="pre">!=</span> <span class="pre">y</span> <span class="pre">||</span> <span class="pre">x</span> <span class="pre">>=</span> <span class="pre">0))</span></code> as:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[</span><span class="nb">abs</span><span class="p">]</span> <span class="n">ii</span> <span class="o"><=</span><span class="p">]</span> <span class="p">[[</span><span class="o"><></span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="mi">0</span> <span class="o">>=</span><span class="p">]</span> <span class="o">||</span><span class="p">]</span> <span class="o">&&</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>It’s a little rough, but, as I say, with a little familiarity it becomes
|
||||
legible.</p>
|
||||
</section>
|
||||
<section id="the-increment-decrement-branches">
|
||||
<h3>The Increment / Decrement Branches<a class="headerlink" href="#the-increment-decrement-branches" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Turning to the branches of the main <code class="docutils literal notranslate"><span class="pre">if</span></code> statement:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>x += ((y >= 0) ? 1 : -1);
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Rewrite as a hybrid (pseudo-code) <code class="docutils literal notranslate"><span class="pre">ifte</span></code> expression:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">y</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[</span><span class="n">x</span> <span class="o">+=</span> <span class="mi">1</span><span class="p">]</span> <span class="p">[</span><span class="n">X</span> <span class="o">-=</span> <span class="mi">1</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Change each C phrase to Joy code:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">0</span> <span class="o">>=</span><span class="p">]</span> <span class="p">[[</span><span class="o">++</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="p">[[</span><span class="o">--</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Factor out the dip from each branch:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">0</span> <span class="o">>=</span><span class="p">]</span> <span class="p">[[</span><span class="o">++</span><span class="p">]]</span> <span class="p">[[</span><span class="o">--</span><span class="p">]]</span> <span class="n">ifte</span> <span class="n">dip</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Similar logic applies to the other branch:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>y += ((x >= 0) ? -1 : 1);
|
||||
|
||||
[x >= 0] [y -= 1] [y += 1] ifte
|
||||
|
||||
[pop 0 >=] [--] [++] ifte
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="not-negative">
|
||||
<h3>“Not Negative”<a class="headerlink" href="#not-negative" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>define('!- 0 >=')
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="putting-the-pieces-together">
|
||||
<h2>Putting the Pieces Together<a class="headerlink" href="#putting-the-pieces-together" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We can assemble the three functions we just defined in quotes and give
|
||||
them them to the <code class="docutils literal notranslate"><span class="pre">ifte</span></code> combinator. With some arrangement to show off
|
||||
the symmetry of the two branches, we have:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>[[[abs] ii <=] [[<>] [pop !-] ||] &&]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
ifte
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>As I was writing this up I realized that, since the <code class="docutils literal notranslate"><span class="pre">&&</span></code> combinator
|
||||
doesn’t consume the stack (below its quoted args), I can unquote the
|
||||
predicate, swap the branches, and use the <code class="docutils literal notranslate"><span class="pre">branch</span></code> combinator instead
|
||||
of <code class="docutils literal notranslate"><span class="pre">ifte</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>[[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
[[pop !-] [--] [++] ifte ]
|
||||
[[ !-] [[++]] [[--]] ifte dip]
|
||||
branch
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>define('spiral_next [[[abs] ii <=] [[<>] [pop !-] ||] &&] [[!-] [[++]] [[--]] ifte dip] [[pop !-] [--] [++] ifte] ifte')
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Let’s try it out:</p>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('0 0 spiral_next')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">1</span> <span class="mi">0</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('1 0 spiral_next')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">1</span> <span class="o">-</span><span class="mi">1</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('1 -1 spiral_next')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">0</span> <span class="o">-</span><span class="mi">1</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('0 -1 spiral_next')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">-</span><span class="mi">1</span> <span class="o">-</span><span class="mi">1</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="turning-it-into-a-generator-with-x">
|
||||
<h2>Turning it into a Generator with <code class="docutils literal notranslate"><span class="pre">x</span></code><a class="headerlink" href="#turning-it-into-a-generator-with-x" title="Permalink to this headline">¶</a></h2>
|
||||
<p>It can be used with the x combinator to make a kind of generator for
|
||||
spiral square coordinates.</p>
|
||||
<p>We can use <code class="docutils literal notranslate"><span class="pre">codireco</span></code> to make a generator</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">codireco</span> <span class="p">:</span><span class="o">:=</span> <span class="n">cons</span> <span class="n">dip</span> <span class="n">rest</span> <span class="n">cons</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>It will look like this:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">value</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Here’s a trace of how it works:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="o">.</span> <span class="n">x</span>
|
||||
<span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="o">.</span> <span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span>
|
||||
<span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="mi">0</span> <span class="o">.</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span>
|
||||
<span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="o">.</span> <span class="n">codireco</span>
|
||||
<span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="o">.</span> <span class="n">cons</span> <span class="n">dip</span> <span class="n">rest</span> <span class="n">cons</span>
|
||||
<span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="p">[</span><span class="mi">0</span> <span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="o">.</span> <span class="n">dip</span> <span class="n">rest</span> <span class="n">cons</span>
|
||||
<span class="o">.</span> <span class="mi">0</span> <span class="n">dup</span> <span class="o">++</span> <span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="n">rest</span> <span class="n">cons</span>
|
||||
<span class="mi">0</span> <span class="o">.</span> <span class="n">dup</span> <span class="o">++</span> <span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="n">rest</span> <span class="n">cons</span>
|
||||
<span class="mi">0</span> <span class="mi">0</span> <span class="o">.</span> <span class="o">++</span> <span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="n">rest</span> <span class="n">cons</span>
|
||||
<span class="mi">0</span> <span class="mi">1</span> <span class="o">.</span> <span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="n">rest</span> <span class="n">cons</span>
|
||||
<span class="mi">0</span> <span class="mi">1</span> <span class="p">[</span><span class="mi">0</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="o">.</span> <span class="n">rest</span> <span class="n">cons</span>
|
||||
<span class="mi">0</span> <span class="mi">1</span> <span class="p">[[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="o">.</span> <span class="n">cons</span>
|
||||
<span class="mi">0</span> <span class="p">[</span><span class="mi">1</span> <span class="p">[</span><span class="n">dup</span> <span class="o">++</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span> <span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>But first we have to change the <code class="docutils literal notranslate"><span class="pre">spiral_next</span></code> function to work on a
|
||||
quoted pair of integers, and leave a copy of the pair on the stack.
|
||||
From:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="n">y</span> <span class="n">x</span> <span class="n">spiral_next</span>
|
||||
<span class="o">---------------------</span>
|
||||
<span class="n">y</span><span class="s1">' x'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>to:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="n">x</span> <span class="n">y</span><span class="p">]</span> <span class="p">[</span><span class="n">spiral_next</span><span class="p">]</span> <span class="n">infra</span>
|
||||
<span class="o">-------------------------------</span>
|
||||
<span class="p">[</span><span class="n">x</span><span class="s1">' y'</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('[0 0] [spiral_next] infra')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">0</span> <span class="mi">1</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>So our generator is:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[</span><span class="n">x</span> <span class="n">y</span><span class="p">]</span> <span class="p">[</span><span class="n">dup</span> <span class="p">[</span><span class="n">spiral_next</span><span class="p">]</span> <span class="n">infra</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Or rather:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[</span><span class="mi">0</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[</span><span class="n">dup</span> <span class="p">[</span><span class="n">spiral_next</span><span class="p">]</span> <span class="n">infra</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>There is a function <code class="docutils literal notranslate"><span class="pre">make_generator</span></code> that will build the generator for
|
||||
us out of the value and stepper function:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="mi">0</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[</span><span class="n">dup</span> <span class="p">[</span><span class="n">spiral_next</span><span class="p">]</span> <span class="n">infra</span><span class="p">]</span> <span class="n">make_generator</span>
|
||||
<span class="o">----------------------------------------------------</span>
|
||||
<span class="p">[[</span><span class="mi">0</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[</span><span class="n">dup</span> <span class="p">[</span><span class="n">spiral_next</span><span class="p">]</span> <span class="n">infra</span><span class="p">]</span> <span class="n">codireco</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Here it is in action:</p>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>J('[0 0] [dup [spiral_next] infra] make_generator x x x x pop')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">0</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[</span><span class="mi">0</span> <span class="mi">1</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span> <span class="mi">1</span><span class="p">]</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span> <span class="mi">0</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Four <code class="docutils literal notranslate"><span class="pre">x</span></code> combinators, four pairs of coordinates.</p>
|
||||
</section>
|
||||
<section id="conclusion">
|
||||
<h2>Conclusion<a class="headerlink" href="#conclusion" title="Permalink to this headline">¶</a></h2>
|
||||
<p>So that’s an example of Joy code. It’s a straightforward translation of
|
||||
the original. It’s a little long for a single definition, you might
|
||||
break it up like so:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> _spn_P ::= [[abs] ii <=] [[<>] [pop !-] ||] &&
|
||||
|
||||
_spn_T ::= [ !-] [[++]] [[--]] ifte dip
|
||||
_spn_E ::= [pop !-] [--] [++] ifte
|
||||
|
||||
spiral_next ::= _spn_P [_spn_E] [_spn_T] branch
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This way it’s easy to see that the function is a branch with two
|
||||
quasi-symmetrical paths.</p>
|
||||
<p>We then used this function to make a simple generator of coordinate
|
||||
pairs, where the next pair in the series can be generated at any time by
|
||||
using the <code class="docutils literal notranslate"><span class="pre">x</span></code> combinator on the generator (which is just a quoted
|
||||
expression containing a copy of the current pair and the “stepper
|
||||
function” to generate the next pair from that.)</p>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>define('_spn_P [[abs] ii <=] [[<>] [pop !-] ||] &&')
|
||||
define('_spn_T [!-] [[++]] [[--]] ifte dip')
|
||||
define('_spn_E [pop !-] [--] [++] ifte')
|
||||
define('spiral_next _spn_P [_spn_E] [_spn_T] branch')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython3 notranslate"><div class="highlight"><pre><span></span>V('23 18 spiral_next')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> . 23 18 spiral_next
|
||||
23 . 18 spiral_next
|
||||
23 18 . spiral_next
|
||||
23 18 . _spn_P [_spn_E] [_spn_T] branch
|
||||
23 18 . [[abs] ii <=] [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . [[<>] [pop !-] ||] && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] . && [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] . [nullary] cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[<>] [pop !-] ||] [nullary] . cons [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] . [nullary [0]] dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [[[<>] [pop !-] ||] nullary] [nullary [0]] . dip branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . nullary [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] . [stack] dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [stack] . dinfrirst [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [[abs] ii <=] [stack] . dip infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . stack [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [18 23] . [[abs] ii <=] infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [18 23] [[abs] ii <=] . infra first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . [abs] ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . ii <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . [dip] dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] [dip] . dupdip i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . dip [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 . abs 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 . 18 [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . [abs] i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [abs] . i <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . abs <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 . <= [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
False . [18 23] swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
False [18 23] . swaack first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 [False] . first [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False . [0] [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False [0] . [[[<>] [pop !-] ||] nullary] branch [_spn_E] [_spn_T] branch
|
||||
23 18 False [0] [[[<>] [pop !-] ||] nullary] . branch [_spn_E] [_spn_T] branch
|
||||
23 18 . 0 [_spn_E] [_spn_T] branch
|
||||
23 18 0 . [_spn_E] [_spn_T] branch
|
||||
23 18 0 [_spn_E] . [_spn_T] branch
|
||||
23 18 0 [_spn_E] [_spn_T] . branch
|
||||
23 18 . _spn_E
|
||||
23 18 . [pop !-] [--] [++] ifte
|
||||
23 18 [pop !-] . [--] [++] ifte
|
||||
23 18 [pop !-] [--] . [++] ifte
|
||||
23 18 [pop !-] [--] [++] . ifte
|
||||
23 18 [pop !-] [--] [++] . [nullary not] dipd branch
|
||||
23 18 [pop !-] [--] [++] [nullary not] . dipd branch
|
||||
23 18 [pop !-] . nullary not [--] [++] branch
|
||||
23 18 [pop !-] . [stack] dinfrirst not [--] [++] branch
|
||||
23 18 [pop !-] [stack] . dinfrirst not [--] [++] branch
|
||||
23 18 [pop !-] [stack] . dip infra first not [--] [++] branch
|
||||
23 18 . stack [pop !-] infra first not [--] [++] branch
|
||||
23 18 [18 23] . [pop !-] infra first not [--] [++] branch
|
||||
23 18 [18 23] [pop !-] . infra first not [--] [++] branch
|
||||
23 18 . pop !- [18 23] swaack first not [--] [++] branch
|
||||
23 . !- [18 23] swaack first not [--] [++] branch
|
||||
23 . 0 >= [18 23] swaack first not [--] [++] branch
|
||||
23 0 . >= [18 23] swaack first not [--] [++] branch
|
||||
True . [18 23] swaack first not [--] [++] branch
|
||||
True [18 23] . swaack first not [--] [++] branch
|
||||
23 18 [True] . first not [--] [++] branch
|
||||
23 18 True . not [--] [++] branch
|
||||
23 18 False . [--] [++] branch
|
||||
23 18 False [--] . [++] branch
|
||||
23 18 False [--] [++] . branch
|
||||
23 18 . --
|
||||
23 17 .
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Newton-Raphson.html" title="previous chapter">Newton’s method</a></li>
|
||||
<li>Next: <a href="Zipper.html" title="next chapter">Traversing Datastructures with Zippers</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,411 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>The Four Fundamental Operations of Definite Action — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="∂RE" href="Derivatives_of_Regular_Expressions.html" />
|
||||
<link rel="prev" title="Categorical Programming" href="Categorical.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="the-four-fundamental-operations-of-definite-action">
|
||||
<h1>The Four Fundamental Operations of Definite Action<a class="headerlink" href="#the-four-fundamental-operations-of-definite-action" title="Permalink to this headline">¶</a></h1>
|
||||
<p>All definite actions (computer program) can be defined by four
|
||||
fundamental patterns of combination:</p>
|
||||
<ol class="arabic simple">
|
||||
<li><p>Sequence</p></li>
|
||||
<li><p>Branch</p></li>
|
||||
<li><p>Loop</p></li>
|
||||
<li><p>Parallel</p></li>
|
||||
</ol>
|
||||
<section id="sequence">
|
||||
<h2>Sequence<a class="headerlink" href="#sequence" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Do one thing after another. In joy this is represented by putting two
|
||||
symbols together, juxtaposition:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">foo</span> <span class="n">bar</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Operations have inputs and outputs. The outputs of <code class="docutils literal notranslate"><span class="pre">foo</span></code> must be
|
||||
compatible in “arity”, type, and shape with the inputs of <code class="docutils literal notranslate"><span class="pre">bar</span></code>.</p>
|
||||
</section>
|
||||
<section id="branch">
|
||||
<h2>Branch<a class="headerlink" href="#branch" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Do one thing or another.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">boolean</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="n">branch</span>
|
||||
|
||||
|
||||
<span class="n">t</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="n">branch</span>
|
||||
<span class="o">----------------------</span>
|
||||
<span class="n">T</span>
|
||||
|
||||
|
||||
<span class="n">f</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="n">branch</span>
|
||||
<span class="o">----------------------</span>
|
||||
<span class="n">F</span>
|
||||
|
||||
|
||||
<span class="n">branch</span> <span class="o">==</span> <span class="n">unit</span> <span class="n">cons</span> <span class="n">swap</span> <span class="n">pick</span> <span class="n">i</span>
|
||||
|
||||
<span class="n">boolean</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="n">branch</span>
|
||||
<span class="n">boolean</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="n">unit</span> <span class="n">cons</span> <span class="n">swap</span> <span class="n">pick</span> <span class="n">i</span>
|
||||
<span class="n">boolean</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[[</span><span class="n">T</span><span class="p">]]</span> <span class="n">cons</span> <span class="n">swap</span> <span class="n">pick</span> <span class="n">i</span>
|
||||
<span class="n">boolean</span> <span class="p">[[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]]</span> <span class="n">swap</span> <span class="n">pick</span> <span class="n">i</span>
|
||||
<span class="p">[[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]]</span> <span class="n">boolean</span> <span class="n">pick</span> <span class="n">i</span>
|
||||
<span class="p">[</span><span class="n">F</span><span class="o">-</span><span class="ow">or</span><span class="o">-</span><span class="n">T</span><span class="p">]</span> <span class="n">i</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Given some branch function <code class="docutils literal notranslate"><span class="pre">G</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">G</span> <span class="o">==</span> <span class="p">[</span><span class="n">F</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="n">branch</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Used in a sequence like so:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">foo</span> <span class="n">G</span> <span class="n">bar</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The inputs and outputs of <code class="docutils literal notranslate"><span class="pre">F</span></code> and <code class="docutils literal notranslate"><span class="pre">T</span></code> must be compatible with the
|
||||
outputs for <code class="docutils literal notranslate"><span class="pre">foo</span></code> and the inputs of <code class="docutils literal notranslate"><span class="pre">bar</span></code>, respectively.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">foo</span> <span class="n">F</span> <span class="n">bar</span>
|
||||
|
||||
<span class="n">foo</span> <span class="n">T</span> <span class="n">bar</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="ifte">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">ifte</span></code><a class="headerlink" href="#ifte" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Often it will be easier on the programmer to write branching code with
|
||||
the predicate specified in a quote. The <code class="docutils literal notranslate"><span class="pre">ifte</span></code> combinator provides
|
||||
this (<code class="docutils literal notranslate"><span class="pre">T</span></code> for “then” and <code class="docutils literal notranslate"><span class="pre">E</span></code> for “else”):</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="p">]</span> <span class="p">[</span><span class="n">E</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Defined in terms of <code class="docutils literal notranslate"><span class="pre">branch</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ifte</span> <span class="o">==</span> <span class="p">[</span><span class="n">nullary</span> <span class="ow">not</span><span class="p">]</span> <span class="n">dip</span> <span class="n">branch</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In this case, <code class="docutils literal notranslate"><span class="pre">P</span></code> must be compatible with the stack and return a
|
||||
Boolean value, and <code class="docutils literal notranslate"><span class="pre">T</span></code> and <code class="docutils literal notranslate"><span class="pre">E</span></code> both must be compatible with the
|
||||
preceeding and following functions, as described above for <code class="docutils literal notranslate"><span class="pre">F</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">T</span></code>. (Note that in the current implementation we are depending on
|
||||
Python for the underlying semantics, so the Boolean value doesn’t <em>have</em>
|
||||
to be Boolean because Python’s rules for “truthiness” will be used to
|
||||
evaluate it. I reflect this in the structure of the stack effect comment
|
||||
of <code class="docutils literal notranslate"><span class="pre">branch</span></code>, it will only accept Boolean values, and in the definition
|
||||
of <code class="docutils literal notranslate"><span class="pre">ifte</span></code> above by including <code class="docutils literal notranslate"><span class="pre">not</span></code> in the quote, which also has the
|
||||
effect that the subject quotes are in the proper order for <code class="docutils literal notranslate"><span class="pre">branch</span></code>.)</p>
|
||||
</section>
|
||||
</section>
|
||||
<section id="loop">
|
||||
<h2>Loop<a class="headerlink" href="#loop" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Do one thing zero or more times.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">boolean</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
|
||||
|
||||
<span class="n">t</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
<span class="o">----------------</span>
|
||||
<span class="n">Q</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
|
||||
|
||||
<span class="o">...</span> <span class="n">f</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
<span class="o">--------------------</span>
|
||||
<span class="o">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">loop</span></code> combinator generates a copy of itself in the true branch.
|
||||
This is the hallmark of recursive defintions. In Thun there is no
|
||||
equivalent to conventional loops. (There is, however, the <code class="docutils literal notranslate"><span class="pre">x</span></code>
|
||||
combinator, defined as <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">==</span> <span class="pre">dup</span> <span class="pre">i</span></code>, which permits recursive
|
||||
constructs that do not need to be directly self-referential, unlike
|
||||
<code class="docutils literal notranslate"><span class="pre">loop</span></code> and <code class="docutils literal notranslate"><span class="pre">genrec</span></code>.)</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">loop</span> <span class="o">==</span> <span class="p">[]</span> <span class="n">swap</span> <span class="p">[</span><span class="n">dup</span> <span class="n">dip</span> <span class="n">loop</span><span class="p">]</span> <span class="n">cons</span> <span class="n">branch</span>
|
||||
|
||||
<span class="n">boolean</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
<span class="n">boolean</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="p">[]</span> <span class="n">swap</span> <span class="p">[</span><span class="n">dup</span> <span class="n">dip</span> <span class="n">loop</span><span class="p">]</span> <span class="n">cons</span> <span class="n">branch</span>
|
||||
<span class="n">boolean</span> <span class="p">[]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="p">[</span><span class="n">dup</span> <span class="n">dip</span> <span class="n">loop</span><span class="p">]</span> <span class="n">cons</span> <span class="n">branch</span>
|
||||
<span class="n">boolean</span> <span class="p">[]</span> <span class="p">[[</span><span class="n">Q</span><span class="p">]</span> <span class="n">dup</span> <span class="n">dip</span> <span class="n">loop</span><span class="p">]</span> <span class="n">branch</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In action the false branch does nothing while the true branch does:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">t</span> <span class="p">[]</span> <span class="p">[[</span><span class="n">Q</span><span class="p">]</span> <span class="n">dup</span> <span class="n">dip</span> <span class="n">loop</span><span class="p">]</span> <span class="n">branch</span>
|
||||
<span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">dup</span> <span class="n">dip</span> <span class="n">loop</span>
|
||||
<span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">dip</span> <span class="n">loop</span>
|
||||
<span class="n">Q</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Because <code class="docutils literal notranslate"><span class="pre">loop</span></code> expects and consumes a Boolean value, the <code class="docutils literal notranslate"><span class="pre">Q</span></code>
|
||||
function must be compatible with the previous stack <em>and itself</em> with a
|
||||
boolean flag for the next iteration:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Q</span> <span class="o">==</span> <span class="n">G</span> <span class="n">b</span>
|
||||
|
||||
<span class="n">Q</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
<span class="n">G</span> <span class="n">b</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
<span class="n">G</span> <span class="n">Q</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
<span class="n">G</span> <span class="n">G</span> <span class="n">b</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
<span class="n">G</span> <span class="n">G</span> <span class="n">Q</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
<span class="n">G</span> <span class="n">G</span> <span class="n">G</span> <span class="n">b</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">loop</span>
|
||||
<span class="n">G</span> <span class="n">G</span> <span class="n">G</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="while">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">while</span></code><a class="headerlink" href="#while" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Keep doing <code class="docutils literal notranslate"><span class="pre">B</span></code> <em>while</em> some predicate <code class="docutils literal notranslate"><span class="pre">P</span></code> is true. This is
|
||||
convenient as the predicate function is made nullary automatically and
|
||||
the body function can be designed without regard to leaving a Boolean
|
||||
flag for the next iteration:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="k">while</span>
|
||||
<span class="o">--------------------------------------</span>
|
||||
<span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">nullary</span> <span class="p">[</span><span class="n">B</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">nullary</span><span class="p">]</span> <span class="n">loop</span>
|
||||
|
||||
|
||||
<span class="k">while</span> <span class="o">==</span> <span class="n">swap</span> <span class="p">[</span><span class="n">nullary</span><span class="p">]</span> <span class="n">cons</span> <span class="n">dup</span> <span class="n">dipd</span> <span class="n">concat</span> <span class="n">loop</span>
|
||||
|
||||
|
||||
<span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="k">while</span>
|
||||
<span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="n">swap</span> <span class="p">[</span><span class="n">nullary</span><span class="p">]</span> <span class="n">cons</span> <span class="n">dup</span> <span class="n">dipd</span> <span class="n">concat</span> <span class="n">loop</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="p">[</span><span class="n">nullary</span><span class="p">]</span> <span class="n">cons</span> <span class="n">dup</span> <span class="n">dipd</span> <span class="n">concat</span> <span class="n">loop</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[[</span><span class="n">P</span><span class="p">]</span> <span class="n">nullary</span><span class="p">]</span> <span class="n">dup</span> <span class="n">dipd</span> <span class="n">concat</span> <span class="n">loop</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[[</span><span class="n">P</span><span class="p">]</span> <span class="n">nullary</span><span class="p">]</span> <span class="p">[[</span><span class="n">P</span><span class="p">]</span> <span class="n">nullary</span><span class="p">]</span> <span class="n">dipd</span> <span class="n">concat</span> <span class="n">loop</span>
|
||||
<span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">nullary</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[[</span><span class="n">P</span><span class="p">]</span> <span class="n">nullary</span><span class="p">]</span> <span class="n">concat</span> <span class="n">loop</span>
|
||||
<span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">nullary</span> <span class="p">[</span><span class="n">B</span> <span class="p">[</span><span class="n">P</span><span class="p">]</span> <span class="n">nullary</span><span class="p">]</span> <span class="n">loop</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="parallel">
|
||||
<h2>Parallel<a class="headerlink" href="#parallel" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <em>parallel</em> operation indicates that two (or more) functions <em>do not
|
||||
interfere</em> with each other and so can run in parallel. The main
|
||||
difficulty in this sort of thing is orchestrating the recombining
|
||||
(“join” or “wait”) of the results of the functions after they finish.</p>
|
||||
<p>The current implementaions and the following definitions <em>are not
|
||||
actually parallel</em> (yet), but there is no reason they couldn’t be
|
||||
reimplemented in terms of e.g. Python threads. I am not concerned with
|
||||
performance of the system just yet, only the elegance of the code it
|
||||
allows us to write.</p>
|
||||
<section id="cleave">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">cleave</span></code><a class="headerlink" href="#cleave" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Joy has a few parallel combinators, the main one being <code class="docutils literal notranslate"><span class="pre">cleave</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">...</span> <span class="n">x</span> <span class="p">[</span><span class="n">A</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="n">cleave</span>
|
||||
<span class="o">---------------------------------------------------------</span>
|
||||
<span class="o">...</span> <span class="p">[</span><span class="n">x</span> <span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">A</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">x</span> <span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="o">---------------------------------------------------------</span>
|
||||
<span class="o">...</span> <span class="n">a</span> <span class="n">b</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">cleave</span></code> combinator expects a value and two quotes and it executes
|
||||
each quote in “separate universes” such that neither can affect the
|
||||
other, then it takes the first item from the stack in each universe and
|
||||
replaces the value and quotes with their respective results.</p>
|
||||
<p>(I think this corresponds to the “fork” operator, the little
|
||||
upward-pointed triangle, that takes two functions <code class="docutils literal notranslate"><span class="pre">A</span> <span class="pre">::</span> <span class="pre">x</span> <span class="pre">-></span> <span class="pre">a</span></code> and
|
||||
<code class="docutils literal notranslate"><span class="pre">B</span> <span class="pre">::</span> <span class="pre">x</span> <span class="pre">-></span> <span class="pre">b</span></code> and returns a function <code class="docutils literal notranslate"><span class="pre">F</span> <span class="pre">::</span> <span class="pre">x</span> <span class="pre">-></span> <span class="pre">(a,</span> <span class="pre">b)</span></code>, in Conal
|
||||
Elliott’s “Compiling to Categories” paper, et. al.)</p>
|
||||
<p>Just a thought, if you <code class="docutils literal notranslate"><span class="pre">cleave</span></code> two jobs and one requires more time to
|
||||
finish than the other you’d like to be able to assign resources
|
||||
accordingly so that they both finish at the same time.</p>
|
||||
</section>
|
||||
<section id="apply-functions">
|
||||
<h3>“Apply” Functions<a class="headerlink" href="#apply-functions" title="Permalink to this headline">¶</a></h3>
|
||||
<p>There are also <code class="docutils literal notranslate"><span class="pre">app2</span></code> and <code class="docutils literal notranslate"><span class="pre">app3</span></code> which run a single quote on more
|
||||
than one value:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="o">...</span> <span class="n">y</span> <span class="n">x</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">app2</span>
|
||||
<span class="o">---------------------------------------------------------</span>
|
||||
<span class="o">...</span> <span class="p">[</span><span class="n">y</span> <span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span> <span class="p">[</span><span class="n">x</span> <span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
|
||||
|
||||
<span class="o">...</span> <span class="n">z</span> <span class="n">y</span> <span class="n">x</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">app3</span>
|
||||
<span class="o">---------------------------------</span>
|
||||
<span class="o">...</span> <span class="p">[</span><span class="n">z</span> <span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="p">[</span><span class="n">y</span> <span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
<span class="p">[</span><span class="n">x</span> <span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="n">infra</span> <span class="n">first</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Because the quoted program can be <code class="docutils literal notranslate"><span class="pre">i</span></code> we can define <code class="docutils literal notranslate"><span class="pre">cleave</span></code> in
|
||||
terms of <code class="docutils literal notranslate"><span class="pre">app2</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">cleave</span> <span class="o">==</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">app2</span> <span class="p">[</span><span class="n">popd</span><span class="p">]</span> <span class="n">dip</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>(I’m not sure why <code class="docutils literal notranslate"><span class="pre">cleave</span></code> was specified to take that value, I may
|
||||
make a combinator that does the same thing but without expecting a
|
||||
value.)</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">clv</span> <span class="o">==</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="n">app2</span>
|
||||
|
||||
<span class="p">[</span><span class="n">A</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="n">clv</span>
|
||||
<span class="o">------------------</span>
|
||||
<span class="n">a</span> <span class="n">b</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="map">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">map</span></code><a class="headerlink" href="#map" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The common <code class="docutils literal notranslate"><span class="pre">map</span></code> function in Joy should also be though of as a
|
||||
<em>parallel</em> operator:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">a</span> <span class="n">b</span> <span class="n">c</span> <span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">Q</span><span class="p">]</span> <span class="nb">map</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>There is no reason why the implementation of <code class="docutils literal notranslate"><span class="pre">map</span></code> couldn’t distribute
|
||||
the <code class="docutils literal notranslate"><span class="pre">Q</span></code> function over e.g. a pool of worker CPUs.</p>
|
||||
</section>
|
||||
<section id="pam">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">pam</span></code><a class="headerlink" href="#pam" title="Permalink to this headline">¶</a></h3>
|
||||
<p>One of my favorite combinators, the <code class="docutils literal notranslate"><span class="pre">pam</span></code> combinator is just:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">pam</span> <span class="o">==</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="nb">map</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This can be used to run any number of programs separately on the current
|
||||
stack and combine their (first) outputs in a result list.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[[</span><span class="n">A</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="o">...</span><span class="p">]</span> <span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="nb">map</span>
|
||||
<span class="o">-------------------------------</span>
|
||||
<span class="p">[</span> <span class="n">a</span> <span class="n">b</span> <span class="n">c</span> <span class="o">...</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="handling-other-kinds-of-join">
|
||||
<h3>Handling Other Kinds of Join<a class="headerlink" href="#handling-other-kinds-of-join" title="Permalink to this headline">¶</a></h3>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">cleave</span></code> operators and others all have pretty brutal join
|
||||
semantics: everything works and we always wait for every
|
||||
sub-computation. We can imagine a few different potentially useful
|
||||
patterns of “joining” results from parallel combinators.</p>
|
||||
<section id="first-to-finish">
|
||||
<h4>first-to-finish<a class="headerlink" href="#first-to-finish" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Thinking about variations of <code class="docutils literal notranslate"><span class="pre">pam</span></code> there could be one that only
|
||||
returns the first result of the first-to-finish sub-program, or the
|
||||
stack could be replaced by its output stack.</p>
|
||||
<p>The other sub-programs would be cancelled.</p>
|
||||
</section>
|
||||
<section id="fulminators">
|
||||
<h4>“Fulminators”<a class="headerlink" href="#fulminators" title="Permalink to this headline">¶</a></h4>
|
||||
<p>Also known as “Futures” or “Promises” (by <em>everybody</em> else. “Fulminators”
|
||||
is what I was going to call them when I was thinking about implementing
|
||||
them in Thun.)</p>
|
||||
<p>The runtime could be amended to permit “thunks” representing the results
|
||||
of in-progress computations to be left on the stack and picked up by
|
||||
subsequent functions. These would themselves be able to leave behind
|
||||
more “thunks”, the values of which depend on the eventual resolution of
|
||||
the values of the previous thunks.</p>
|
||||
<p>In this way you can create “chains” (and more complex shapes) out of
|
||||
normal-looking code that consist of a kind of call-graph interspersed
|
||||
with “asyncronous” … events?</p>
|
||||
<p>In any case, until I can find a rigorous theory that shows that this
|
||||
sort of thing works perfectly in Joy code I’m not going to worry about
|
||||
it. (And I think the Categories can deal with it anyhow? Incremental
|
||||
evaluation, yeah?)</p>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Categorical.html" title="previous chapter">Categorical Programming</a></li>
|
||||
<li>Next: <a href="Derivatives_of_Regular_Expressions.html" title="next chapter">∂RE</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,581 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Treating Trees II: treestep — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="Using x to Generate Values" href="Generator_Programs.html" />
|
||||
<link rel="prev" title="Treating Trees I: Ordered Binary Trees" href="Ordered_Binary_Trees.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="treating-trees-ii-treestep">
|
||||
<h1>Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code><a class="headerlink" href="#treating-trees-ii-treestep" title="Permalink to this headline">¶</a></h1>
|
||||
<p>Let’s consider a tree structure, similar to one described <a class="reference external" href="https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf">“Why
|
||||
functional programming matters” by John
|
||||
Hughes</a>,
|
||||
that consists of a node value followed by zero or more child trees. (The
|
||||
asterisk is meant to indicate the <a class="reference external" href="https://en.wikipedia.org/wiki/Kleene_star">Kleene
|
||||
star</a>.)</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tree</span> <span class="o">=</span> <span class="p">[]</span> <span class="o">|</span> <span class="p">[</span><span class="n">node</span> <span class="n">tree</span><span class="o">*</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>In the spirit of <code class="docutils literal notranslate"><span class="pre">step</span></code> we are going to define a combinator
|
||||
<code class="docutils literal notranslate"><span class="pre">treestep</span></code> which expects a tree and three additional items: a
|
||||
base-case function <code class="docutils literal notranslate"><span class="pre">[B]</span></code>, and two quoted programs <code class="docutils literal notranslate"><span class="pre">[N]</span></code> and <code class="docutils literal notranslate"><span class="pre">[C]</span></code>.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">tree</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="n">treestep</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>If the current tree node is empty then just execute <code class="docutils literal notranslate"><span class="pre">B</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="n">treestep</span>
|
||||
<span class="o">---------------------------</span>
|
||||
<span class="p">[]</span> <span class="n">B</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Otherwise, evaluate <code class="docutils literal notranslate"><span class="pre">N</span></code> on the node value, <code class="docutils literal notranslate"><span class="pre">map</span></code> the whole function
|
||||
(abbreviated here as <code class="docutils literal notranslate"><span class="pre">K</span></code>) over the child trees recursively, and then
|
||||
combine the result with <code class="docutils literal notranslate"><span class="pre">C</span></code>.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="n">node</span> <span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="n">treestep</span>
|
||||
<span class="o">---------------------------------------</span> <span class="n">w</span><span class="o">/</span> <span class="n">K</span> <span class="o">==</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="n">treestep</span>
|
||||
<span class="n">node</span> <span class="n">N</span> <span class="p">[</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">C</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>(Later on we’ll experiment with making <code class="docutils literal notranslate"><span class="pre">map</span></code> part of <code class="docutils literal notranslate"><span class="pre">C</span></code> so you can
|
||||
use other combinators.)</p>
|
||||
<section id="derive-the-recursive-function">
|
||||
<h2>Derive the recursive function.<a class="headerlink" href="#derive-the-recursive-function" title="Permalink to this headline">¶</a></h2>
|
||||
<p>We can begin to derive it by finding the <code class="docutils literal notranslate"><span class="pre">ifte</span></code> stage that <code class="docutils literal notranslate"><span class="pre">genrec</span></code>
|
||||
will produce.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">K</span> <span class="o">==</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">R0</span><span class="p">]</span> <span class="p">[</span><span class="n">R1</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="o">==</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">R0</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">R1</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>So we just have to derive <code class="docutils literal notranslate"><span class="pre">J</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">J</span> <span class="o">==</span> <span class="n">R0</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">R1</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The behavior of <code class="docutils literal notranslate"><span class="pre">J</span></code> is to accept a (non-empty) tree node and arrive at
|
||||
the desired outcome.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[</span><span class="n">node</span> <span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="n">J</span>
|
||||
<span class="o">------------------------------</span>
|
||||
<span class="n">node</span> <span class="n">N</span> <span class="p">[</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">C</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>So <code class="docutils literal notranslate"><span class="pre">J</span></code> will have some form like:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">J</span> <span class="o">==</span> <span class="o">...</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="o">...</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="o">...</span> <span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="o">...</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Let’s dive in. First, unquote the node and <code class="docutils literal notranslate"><span class="pre">dip</span></code> <code class="docutils literal notranslate"><span class="pre">N</span></code>.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">node</span> <span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="n">uncons</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span>
|
||||
<span class="n">node</span> <span class="p">[</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span>
|
||||
<span class="n">node</span> <span class="n">N</span> <span class="p">[</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Next, <code class="docutils literal notranslate"><span class="pre">map</span></code> <code class="docutils literal notranslate"><span class="pre">K</span></code> over the child trees and combine with <code class="docutils literal notranslate"><span class="pre">C</span></code>.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">node</span> <span class="n">N</span> <span class="p">[</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">C</span>
|
||||
<span class="n">node</span> <span class="n">N</span> <span class="p">[</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">C</span>
|
||||
<span class="n">node</span> <span class="n">N</span> <span class="p">[</span><span class="n">K</span><span class="o">.</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="n">C</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>So:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">J</span> <span class="o">==</span> <span class="n">uncons</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">C</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Plug it in and convert to <code class="docutils literal notranslate"><span class="pre">genrec</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">K</span> <span class="o">==</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">J</span> <span class="p">]</span> <span class="n">ifte</span>
|
||||
<span class="o">==</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">uncons</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">ifte</span>
|
||||
<span class="o">==</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">uncons</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="extract-the-givens-to-parameterize-the-program">
|
||||
<h2>Extract the givens to parameterize the program.<a class="headerlink" href="#extract-the-givens-to-parameterize-the-program" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Working backwards:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">uncons</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="n">swap</span> <span class="p">[</span><span class="n">uncons</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">uncons</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="p">[[</span><span class="ow">not</span><span class="p">]</span> <span class="n">swap</span><span class="p">]</span> <span class="n">dip</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="o">^^^^^^^^^^^^^^^^</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="p">[</span><span class="n">uncons</span><span class="p">]</span> <span class="n">swoncat</span> <span class="p">[[</span><span class="ow">not</span><span class="p">]</span> <span class="n">swap</span><span class="p">]</span> <span class="n">dip</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span><span class="p">]</span> <span class="n">cons</span> <span class="p">[</span><span class="n">uncons</span><span class="p">]</span> <span class="n">swoncat</span> <span class="p">[[</span><span class="ow">not</span><span class="p">]</span> <span class="n">swap</span><span class="p">]</span> <span class="n">dip</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="o">^^^^^^^^^^^^^^^^^^^^^^^^^^^</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Extract a couple of auxiliary definitions:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">TS</span><span class="mf">.0</span> <span class="o">==</span> <span class="p">[[</span><span class="ow">not</span><span class="p">]</span> <span class="n">swap</span><span class="p">]</span> <span class="n">dip</span>
|
||||
<span class="n">TS</span><span class="mf">.1</span> <span class="o">==</span> <span class="p">[</span><span class="n">dip</span><span class="p">]</span> <span class="n">cons</span> <span class="p">[</span><span class="n">uncons</span><span class="p">]</span> <span class="n">swoncat</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">TS</span><span class="mf">.1</span> <span class="n">TS</span><span class="mf">.0</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="p">[</span><span class="n">TS</span><span class="mf">.1</span> <span class="n">TS</span><span class="mf">.0</span><span class="p">]</span> <span class="n">dip</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="p">[</span><span class="nb">map</span><span class="p">]</span> <span class="n">swoncat</span> <span class="p">[</span><span class="n">TS</span><span class="mf">.1</span> <span class="n">TS</span><span class="mf">.0</span><span class="p">]</span> <span class="n">dip</span> <span class="n">genrec</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>The givens are all to the left so we have our definition.</p>
|
||||
<section id="alternate-extract-the-givens-to-parameterize-the-program">
|
||||
<h3>(alternate) Extract the givens to parameterize the program.<a class="headerlink" href="#alternate-extract-the-givens-to-parameterize-the-program" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Working backwards:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">uncons</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="n">dip</span><span class="p">]</span> <span class="n">cons</span> <span class="p">[</span><span class="n">uncons</span><span class="p">]</span> <span class="n">swoncat</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="ow">not</span><span class="p">]</span> <span class="n">roll</span><span class="o">></span> <span class="p">[</span><span class="n">dip</span><span class="p">]</span> <span class="n">cons</span> <span class="p">[</span><span class="n">uncons</span><span class="p">]</span> <span class="n">swoncat</span> <span class="p">[</span><span class="nb">map</span> <span class="n">C</span><span class="p">]</span> <span class="n">genrec</span>
|
||||
<span class="o">^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="define-treestep">
|
||||
<h2>Define <code class="docutils literal notranslate"><span class="pre">treestep</span></code><a class="headerlink" href="#define-treestep" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>from notebook_preamble import D, J, V, define, DefinitionWrapper
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>DefinitionWrapper.add_definitions('''
|
||||
|
||||
_treestep_0 == [[not] swap] dip
|
||||
_treestep_1 == [dip] cons [uncons] swoncat
|
||||
treegrind == [_treestep_1 _treestep_0] dip genrec
|
||||
treestep == [map] swoncat treegrind
|
||||
|
||||
''', D)
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="examples">
|
||||
<h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Consider trees, the nodes of which are integers. We can find the sum of
|
||||
all nodes in a tree with this function:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">sumtree</span> <span class="o">==</span> <span class="p">[</span><span class="n">pop</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[]</span> <span class="p">[</span><span class="nb">sum</span> <span class="o">+</span><span class="p">]</span> <span class="n">treestep</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>define('sumtree == [pop 0] [] [sum +] treestep')
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Running this function on an empty tree value gives zero:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="p">[]</span> <span class="p">[</span><span class="n">pop</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[]</span> <span class="p">[</span><span class="nb">sum</span> <span class="o">+</span><span class="p">]</span> <span class="n">treestep</span>
|
||||
<span class="o">------------------------------------</span>
|
||||
<span class="mi">0</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[] sumtree') # Empty tree.
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">0</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Running it on a non-empty node:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">n</span> <span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">pop</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[]</span> <span class="p">[</span><span class="nb">sum</span> <span class="o">+</span><span class="p">]</span> <span class="n">treestep</span>
|
||||
<span class="n">n</span> <span class="p">[</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[[</span><span class="n">pop</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[]</span> <span class="p">[</span><span class="nb">sum</span> <span class="o">+</span><span class="p">]</span> <span class="n">treestep</span><span class="p">]</span> <span class="nb">map</span> <span class="nb">sum</span> <span class="o">+</span>
|
||||
<span class="n">n</span> <span class="p">[</span> <span class="o">...</span> <span class="p">]</span> <span class="nb">sum</span> <span class="o">+</span>
|
||||
<span class="n">n</span> <span class="n">m</span> <span class="o">+</span>
|
||||
<span class="n">n</span><span class="o">+</span><span class="n">m</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[23] sumtree') # No child trees.
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">23</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[23 []] sumtree') # Child tree, empty.
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">23</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[23 [2 [4]] [3]] sumtree') # Non-empty child trees.
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">32</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[23 [2 [8] [9]] [3] [4 []]] sumtree') # Etc...
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">49</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [] [cons sum] treestep') # Alternate "spelling".
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">49</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 23] [cons] treestep') # Replace each node.
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">23</span> <span class="p">[</span><span class="mi">23</span> <span class="p">[</span><span class="mi">23</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span><span class="p">]]</span> <span class="p">[</span><span class="mi">23</span><span class="p">]</span> <span class="p">[</span><span class="mi">23</span> <span class="p">[]]]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">1</span> <span class="p">[</span><span class="mi">1</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="p">[</span><span class="mi">1</span> <span class="p">[]]]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[23 [2 [8] [9]] [3] [4 []]] [] [pop 1] [cons] treestep sumtree')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">6</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[23 [2 [8] [9]] [3] [4 []]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">6</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[4 [3 [] [7]]] [pop 0] [pop 1] [sum +] treestep') # Combine replace and sum into one function.
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">3</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="redefining-the-ordered-binary-tree-in-terms-of-treestep">
|
||||
<h2>Redefining the Ordered Binary Tree in terms of <code class="docutils literal notranslate"><span class="pre">treestep</span></code>.<a class="headerlink" href="#redefining-the-ordered-binary-tree-in-terms-of-treestep" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Tree</span> <span class="o">=</span> <span class="p">[]</span> <span class="o">|</span> <span class="p">[[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">left</span> <span class="n">right</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>What kind of functions can we write for this with our <code class="docutils literal notranslate"><span class="pre">treestep</span></code>?</p>
|
||||
<p>The pattern for processing a non-empty node is:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">node</span> <span class="n">N</span> <span class="p">[</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">C</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Plugging in our BTree structure:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">N</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">C</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="traversal">
|
||||
<h3>Traversal<a class="headerlink" href="#traversal" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">first</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">i</span>
|
||||
<span class="n">key</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">i</span>
|
||||
<span class="n">key</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">i</span>
|
||||
<span class="n">key</span> <span class="p">[</span><span class="n">lkey</span> <span class="n">rkey</span> <span class="p">]</span> <span class="n">i</span>
|
||||
<span class="n">key</span> <span class="n">lkey</span> <span class="n">rkey</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This doesn’t quite work:</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[[3 0] [[2 0] [][]] [[9 0] [[5 0] [[4 0] [][]] [[8 0] [[6 0] [] [[7 0] [][]]][]]][]]] ["B"] [first] [i] treestep')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">3</span> <span class="s1">'B'</span> <span class="s1">'B'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Doesn’t work because <code class="docutils literal notranslate"><span class="pre">map</span></code> extracts the <code class="docutils literal notranslate"><span class="pre">first</span></code> item of whatever its
|
||||
mapped function produces. We have to return a list, rather than
|
||||
depositing our results directly on the stack.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">N</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">C</span>
|
||||
|
||||
<span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">first</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">flatten</span> <span class="n">cons</span>
|
||||
<span class="n">key</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="nb">map</span> <span class="n">flatten</span> <span class="n">cons</span>
|
||||
<span class="n">key</span> <span class="p">[[</span><span class="n">lk</span><span class="p">]</span> <span class="p">[</span><span class="n">rk</span><span class="p">]</span> <span class="p">]</span> <span class="n">flatten</span> <span class="n">cons</span>
|
||||
<span class="n">key</span> <span class="p">[</span> <span class="n">lk</span> <span class="n">rk</span> <span class="p">]</span> <span class="n">cons</span>
|
||||
<span class="p">[</span><span class="n">key</span> <span class="n">lk</span> <span class="n">rk</span> <span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>So:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[]</span> <span class="p">[</span><span class="n">first</span><span class="p">]</span> <span class="p">[</span><span class="n">flatten</span> <span class="n">cons</span><span class="p">]</span> <span class="n">treestep</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [first] [flatten cons] treestep')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">3</span> <span class="mi">2</span> <span class="mi">9</span> <span class="mi">5</span> <span class="mi">4</span> <span class="mi">8</span> <span class="mi">6</span> <span class="mi">7</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>There we go.</p>
|
||||
</section>
|
||||
<section id="in-order-traversal">
|
||||
<h3>In-order traversal<a class="headerlink" href="#in-order-traversal" title="Permalink to this headline">¶</a></h3>
|
||||
<p>From here:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">key</span> <span class="p">[[</span><span class="n">lk</span><span class="p">]</span> <span class="p">[</span><span class="n">rk</span><span class="p">]]</span> <span class="n">C</span>
|
||||
<span class="n">key</span> <span class="p">[[</span><span class="n">lk</span><span class="p">]</span> <span class="p">[</span><span class="n">rk</span><span class="p">]]</span> <span class="n">i</span>
|
||||
<span class="n">key</span> <span class="p">[</span><span class="n">lk</span><span class="p">]</span> <span class="p">[</span><span class="n">rk</span><span class="p">]</span> <span class="n">roll</span><span class="o"><</span>
|
||||
<span class="p">[</span><span class="n">lk</span><span class="p">]</span> <span class="p">[</span><span class="n">rk</span><span class="p">]</span> <span class="n">key</span> <span class="n">swons</span> <span class="n">concat</span>
|
||||
<span class="p">[</span><span class="n">lk</span><span class="p">]</span> <span class="p">[</span><span class="n">key</span> <span class="n">rk</span><span class="p">]</span> <span class="n">concat</span>
|
||||
<span class="p">[</span><span class="n">lk</span> <span class="n">key</span> <span class="n">rk</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>So:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[]</span> <span class="p">[</span><span class="n">i</span> <span class="n">roll</span><span class="o"><</span> <span class="n">swons</span> <span class="n">concat</span><span class="p">]</span> <span class="p">[</span><span class="n">first</span><span class="p">]</span> <span class="n">treestep</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [uncons pop] [i roll< swons concat] treestep')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">2</span> <span class="mi">3</span> <span class="mi">4</span> <span class="mi">5</span> <span class="mi">6</span> <span class="mi">7</span> <span class="mi">8</span> <span class="mi">9</span><span class="p">]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="with-treegrind">
|
||||
<h2>With <code class="docutils literal notranslate"><span class="pre">treegrind</span></code>?<a class="headerlink" href="#with-treegrind" title="Permalink to this headline">¶</a></h2>
|
||||
<p>The <code class="docutils literal notranslate"><span class="pre">treegrind</span></code> function doesn’t include the <code class="docutils literal notranslate"><span class="pre">map</span></code> combinator, so
|
||||
the <code class="docutils literal notranslate"><span class="pre">[C]</span></code> function must arrange to use some combinator on the quoted
|
||||
recursive copy <code class="docutils literal notranslate"><span class="pre">[K]</span></code>. With this function, the pattern for processing a
|
||||
non-empty node is:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">node</span> <span class="n">N</span> <span class="p">[</span><span class="n">tree</span><span class="o">*</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">C</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Plugging in our BTree structure:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">N</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">C</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[["key" "value"] ["left"] ["right"] ] ["B"] ["N"] ["C"] treegrind')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="s1">'key'</span> <span class="s1">'value'</span><span class="p">]</span> <span class="s1">'N'</span> <span class="p">[[</span><span class="s1">'left'</span><span class="p">]</span> <span class="p">[</span><span class="s1">'right'</span><span class="p">]]</span> <span class="p">[[</span><span class="ow">not</span><span class="p">]</span> <span class="p">[</span><span class="s1">'B'</span><span class="p">]</span> <span class="p">[</span><span class="n">uncons</span> <span class="p">[</span><span class="s1">'N'</span><span class="p">]</span> <span class="n">dip</span><span class="p">]</span> <span class="p">[</span><span class="s1">'C'</span><span class="p">]</span> <span class="n">genrec</span><span class="p">]</span> <span class="s1">'C'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="treegrind-with-step">
|
||||
<h2><code class="docutils literal notranslate"><span class="pre">treegrind</span></code> with <code class="docutils literal notranslate"><span class="pre">step</span></code><a class="headerlink" href="#treegrind-with-step" title="Permalink to this headline">¶</a></h2>
|
||||
<p>Iteration through the nodes</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] ["N"] [step] treegrind')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">3</span> <span class="mi">0</span><span class="p">]</span> <span class="s1">'N'</span> <span class="p">[</span><span class="mi">2</span> <span class="mi">0</span><span class="p">]</span> <span class="s1">'N'</span> <span class="p">[</span><span class="mi">9</span> <span class="mi">0</span><span class="p">]</span> <span class="s1">'N'</span> <span class="p">[</span><span class="mi">5</span> <span class="mi">0</span><span class="p">]</span> <span class="s1">'N'</span> <span class="p">[</span><span class="mi">4</span> <span class="mi">0</span><span class="p">]</span> <span class="s1">'N'</span> <span class="p">[</span><span class="mi">8</span> <span class="mi">0</span><span class="p">]</span> <span class="s1">'N'</span> <span class="p">[</span><span class="mi">6</span> <span class="mi">0</span><span class="p">]</span> <span class="s1">'N'</span> <span class="p">[</span><span class="mi">7</span> <span class="mi">0</span><span class="p">]</span> <span class="s1">'N'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Sum the nodes’ keys.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('0 [[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [pop] [first +] [step] treegrind')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">44</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Rebuild the tree using <code class="docutils literal notranslate"><span class="pre">map</span></code> (imitating <code class="docutils literal notranslate"><span class="pre">treestep</span></code>.)</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('[[3 0] [[2 0] [] []] [[9 0] [[5 0] [[4 0] [] []] [[8 0] [[6 0] [] [[7 0] [] []]] []]] []]] [] [[100 +] infra] [map cons] treegrind')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[[</span><span class="mi">103</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[[</span><span class="mi">102</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[]</span> <span class="p">[]]</span> <span class="p">[[</span><span class="mi">109</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[[</span><span class="mi">105</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[[</span><span class="mi">104</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[]</span> <span class="p">[]]</span> <span class="p">[[</span><span class="mi">108</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[[</span><span class="mi">106</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[]</span> <span class="p">[[</span><span class="mi">107</span> <span class="mi">0</span><span class="p">]</span> <span class="p">[]</span> <span class="p">[]]]</span> <span class="p">[]]]</span> <span class="p">[]]]</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="do-we-have-the-flexibility-to-reimplement-tree-get">
|
||||
<h2>Do we have the flexibility to reimplement <code class="docutils literal notranslate"><span class="pre">Tree-get</span></code>?<a class="headerlink" href="#do-we-have-the-flexibility-to-reimplement-tree-get" title="Permalink to this headline">¶</a></h2>
|
||||
<p>I think we do:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">N</span><span class="p">]</span> <span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="n">treegrind</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>We’ll start by saying that the base-case (the key is not in the tree) is
|
||||
user defined, and the per-node function is just the query key literal:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">B</span><span class="p">]</span> <span class="p">[</span><span class="n">query_key</span><span class="p">]</span> <span class="p">[</span><span class="n">C</span><span class="p">]</span> <span class="n">treegrind</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>This means we just have to define <code class="docutils literal notranslate"><span class="pre">C</span></code> from:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">query_key</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">C</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Let’s try <code class="docutils literal notranslate"><span class="pre">cmp</span></code>:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">C</span> <span class="o">==</span> <span class="n">P</span> <span class="p">[</span><span class="n">T</span><span class="o">></span><span class="p">]</span> <span class="p">[</span><span class="n">E</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="o"><</span><span class="p">]</span> <span class="n">cmp</span>
|
||||
|
||||
<span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">query_key</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">P</span> <span class="p">[</span><span class="n">T</span><span class="o">></span><span class="p">]</span> <span class="p">[</span><span class="n">E</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="o"><</span><span class="p">]</span> <span class="n">cmp</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="the-predicate-p">
|
||||
<h3>The predicate <code class="docutils literal notranslate"><span class="pre">P</span></code><a class="headerlink" href="#the-predicate-p" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Seems pretty easy (we must preserve the value in case the keys are
|
||||
equal):</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">query_key</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">P</span>
|
||||
<span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">query_key</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">roll</span><span class="o"><</span>
|
||||
<span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">query_key</span> <span class="p">[</span><span class="n">roll</span><span class="o"><</span> <span class="n">uncons</span> <span class="n">swap</span><span class="p">]</span> <span class="n">dip</span>
|
||||
|
||||
<span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">roll</span><span class="o"><</span> <span class="n">uncons</span> <span class="n">swap</span> <span class="n">query_key</span>
|
||||
<span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="p">[</span><span class="n">key</span> <span class="n">value</span><span class="p">]</span> <span class="n">uncons</span> <span class="n">swap</span> <span class="n">query_key</span>
|
||||
<span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="n">key</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span> <span class="n">swap</span> <span class="n">query_key</span>
|
||||
<span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span> <span class="n">key</span> <span class="n">query_key</span>
|
||||
|
||||
<span class="n">P</span> <span class="o">==</span> <span class="n">roll</span><span class="o"><</span> <span class="p">[</span><span class="n">roll</span><span class="o"><</span> <span class="n">uncons</span> <span class="n">swap</span><span class="p">]</span> <span class="n">dip</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>(Possibly with a swap at the end? Or just swap <code class="docutils literal notranslate"><span class="pre">T<</span></code> and <code class="docutils literal notranslate"><span class="pre">T></span></code>.)</p>
|
||||
<p>So now:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span> <span class="n">key</span> <span class="n">query_key</span> <span class="p">[</span><span class="n">T</span><span class="o">></span><span class="p">]</span> <span class="p">[</span><span class="n">E</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="o"><</span><span class="p">]</span> <span class="n">cmp</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>Becomes one of these three:</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span> <span class="n">T</span><span class="o">></span>
|
||||
<span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span> <span class="n">E</span>
|
||||
<span class="p">[</span><span class="n">left</span> <span class="n">right</span><span class="p">]</span> <span class="p">[</span><span class="n">K</span><span class="p">]</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span> <span class="n">T</span><span class="o"><</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="e">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">E</span></code><a class="headerlink" href="#e" title="Permalink to this headline">¶</a></h3>
|
||||
<p>Easy.</p>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">E</span> <span class="o">==</span> <span class="n">roll</span><span class="o">></span> <span class="n">popop</span> <span class="n">first</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="t-and-t">
|
||||
<h3><code class="docutils literal notranslate"><span class="pre">T<</span></code> and <code class="docutils literal notranslate"><span class="pre">T></span></code><a class="headerlink" href="#t-and-t" title="Permalink to this headline">¶</a></h3>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">T</span><span class="o"><</span> <span class="o">==</span> <span class="n">pop</span> <span class="p">[</span><span class="n">first</span><span class="p">]</span> <span class="n">dip</span> <span class="n">i</span>
|
||||
<span class="n">T</span><span class="o">></span> <span class="o">==</span> <span class="n">pop</span> <span class="p">[</span><span class="n">second</span><span class="p">]</span> <span class="n">dip</span> <span class="n">i</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<section id="putting-it-together">
|
||||
<h2>Putting it together<a class="headerlink" href="#putting-it-together" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">T</span><span class="o">></span> <span class="o">==</span> <span class="n">pop</span> <span class="p">[</span><span class="n">first</span><span class="p">]</span> <span class="n">dip</span> <span class="n">i</span>
|
||||
<span class="n">T</span><span class="o"><</span> <span class="o">==</span> <span class="n">pop</span> <span class="p">[</span><span class="n">second</span><span class="p">]</span> <span class="n">dip</span> <span class="n">i</span>
|
||||
<span class="n">E</span> <span class="o">==</span> <span class="n">roll</span><span class="o">></span> <span class="n">popop</span> <span class="n">first</span>
|
||||
<span class="n">P</span> <span class="o">==</span> <span class="n">roll</span><span class="o"><</span> <span class="p">[</span><span class="n">roll</span><span class="o"><</span> <span class="n">uncons</span> <span class="n">swap</span><span class="p">]</span> <span class="n">dip</span>
|
||||
|
||||
<span class="n">Tree</span><span class="o">-</span><span class="n">get</span> <span class="o">==</span> <span class="p">[</span><span class="n">P</span> <span class="p">[</span><span class="n">T</span><span class="o">></span><span class="p">]</span> <span class="p">[</span><span class="n">E</span><span class="p">]</span> <span class="p">[</span><span class="n">T</span><span class="o"><</span><span class="p">]</span> <span class="n">cmp</span><span class="p">]</span> <span class="n">treegrind</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<p>To me, that seems simpler than the <code class="docutils literal notranslate"><span class="pre">genrec</span></code> version.</p>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>DefinitionWrapper.add_definitions('''
|
||||
|
||||
T> == pop [first] dip i
|
||||
T< == pop [second] dip i
|
||||
E == roll> popop first
|
||||
P == roll< [roll< uncons swap] dip
|
||||
|
||||
Tree-get == [P [T>] [E] [T<] cmp] treegrind
|
||||
|
||||
''', D)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('''\
|
||||
|
||||
[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
|
||||
|
||||
[] [5] Tree-get
|
||||
|
||||
''')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="mi">15</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>J('''\
|
||||
|
||||
[[3 13] [[2 12] [] []] [[9 19] [[5 15] [[4 14] [] []] [[8 18] [[6 16] [] [[7 17] [] []]] []]] []]]
|
||||
|
||||
[pop "nope"] [25] Tree-get
|
||||
|
||||
''')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s1">'nope'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="TypeChecking.html">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Ordered_Binary_Trees.html" title="previous chapter">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li>Next: <a href="Generator_Programs.html" title="next chapter">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,247 +0,0 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
|
||||
|
||||
<title>Type Checking — Thun 0.4.1 documentation</title>
|
||||
<link rel="stylesheet" type="text/css" href="../_static/pygments.css" />
|
||||
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css" />
|
||||
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
|
||||
<script src="../_static/jquery.js"></script>
|
||||
<script src="../_static/underscore.js"></script>
|
||||
<script src="../_static/doctools.js"></script>
|
||||
<link rel="index" title="Index" href="../genindex.html" />
|
||||
<link rel="search" title="Search" href="../search.html" />
|
||||
<link rel="next" title="No Updates" href="NoUpdates.html" />
|
||||
<link rel="prev" title="The Blissful Elegance of Typing Joy" href="Types.html" />
|
||||
|
||||
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
|
||||
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
|
||||
|
||||
</head><body>
|
||||
|
||||
|
||||
<div class="document">
|
||||
<div class="documentwrapper">
|
||||
<div class="bodywrapper">
|
||||
|
||||
|
||||
<div class="body" role="main">
|
||||
|
||||
<section id="type-checking">
|
||||
<h1>Type Checking<a class="headerlink" href="#type-checking" title="Permalink to this headline">¶</a></h1>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>import logging, sys
|
||||
|
||||
logging.basicConfig(
|
||||
format='%(message)s',
|
||||
stream=sys.stdout,
|
||||
level=logging.INFO,
|
||||
)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>from joy.utils.types import (
|
||||
doc_from_stack_effect,
|
||||
infer,
|
||||
reify,
|
||||
unify,
|
||||
FUNCTIONS,
|
||||
JoyTypeError,
|
||||
)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>D = FUNCTIONS.copy()
|
||||
del D['product']
|
||||
globals().update(D)
|
||||
</pre></div>
|
||||
</div>
|
||||
<section id="an-example">
|
||||
<h2>An Example<a class="headerlink" href="#an-example" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>fi, fo = infer(pop, swap, rolldown, rrest, ccons)[0]
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>25 (--) ∘ pop swap rolldown rrest ccons
|
||||
28 (a1 --) ∘ swap rolldown rrest ccons
|
||||
31 (a3 a2 a1 -- a2 a3) ∘ rolldown rrest ccons
|
||||
34 (a4 a3 a2 a1 -- a2 a3 a4) ∘ rrest ccons
|
||||
37 ([a4 a5 ...1] a3 a2 a1 -- a2 a3 [...1]) ∘ ccons
|
||||
40 ([a4 a5 ...1] a3 a2 a1 -- [a2 a3 ...1]) ∘
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>print doc_from_stack_effect(fi, fo)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">([</span><span class="n">a4</span> <span class="n">a5</span> <span class="o">..</span><span class="mf">.1</span><span class="p">]</span> <span class="n">a3</span> <span class="n">a2</span> <span class="n">a1</span> <span class="o">--</span> <span class="p">[</span><span class="n">a2</span> <span class="n">a3</span> <span class="o">..</span><span class="mf">.1</span><span class="p">])</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>from joy.parser import text_to_expression
|
||||
from joy.utils.stack import stack_to_string
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>e = text_to_expression('0 1 2 [3 4]') # reverse order
|
||||
print stack_to_string(e)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">[</span><span class="mi">3</span> <span class="mi">4</span><span class="p">]</span> <span class="mi">2</span> <span class="mi">1</span> <span class="mi">0</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>u = unify(e, fi)[0]
|
||||
u
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="n">a1</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="n">a2</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="n">a3</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="n">a4</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="n">a5</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span> <span class="n">s2</span><span class="p">:</span> <span class="p">(),</span> <span class="n">s1</span><span class="p">:</span> <span class="p">()}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>g = reify(u, (fi, fo))
|
||||
print doc_from_stack_effect(*g)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="o">...</span> <span class="p">[</span><span class="mi">3</span> <span class="mi">4</span> <span class="p">]</span> <span class="mi">2</span> <span class="mi">1</span> <span class="mi">0</span> <span class="o">--</span> <span class="o">...</span> <span class="p">[</span><span class="mi">1</span> <span class="mi">2</span> <span class="p">])</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="unification-works-in-reverse">
|
||||
<h2>Unification Works “in Reverse”<a class="headerlink" href="#unification-works-in-reverse" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>e = text_to_expression('[2 3]')
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>u = unify(e, fo)[0] # output side, not input side
|
||||
u
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="n">a2</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="n">a3</span><span class="p">:</span> <span class="mi">3</span><span class="p">,</span> <span class="n">s2</span><span class="p">:</span> <span class="p">(),</span> <span class="n">s1</span><span class="p">:</span> <span class="p">()}</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>g = reify(u, (fi, fo))
|
||||
print doc_from_stack_effect(*g)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">(</span><span class="o">...</span> <span class="p">[</span><span class="n">a4</span> <span class="n">a5</span> <span class="p">]</span> <span class="mi">3</span> <span class="mi">2</span> <span class="n">a1</span> <span class="o">--</span> <span class="o">...</span> <span class="p">[</span><span class="mi">2</span> <span class="mi">3</span> <span class="p">])</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
<section id="failing-a-check">
|
||||
<h2>Failing a Check<a class="headerlink" href="#failing-a-check" title="Permalink to this headline">¶</a></h2>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>fi, fo = infer(dup, mul)[0]
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>25 (--) ∘ dup mul
|
||||
28 (a1 -- a1 a1) ∘ mul
|
||||
31 (f1 -- f2) ∘
|
||||
31 (i1 -- i2) ∘
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>e = text_to_expression('"two"')
|
||||
print stack_to_string(e)
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="s1">'two'</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-ipython2 notranslate"><div class="highlight"><pre><span></span>try:
|
||||
unify(e, fi)
|
||||
except JoyTypeError, err:
|
||||
print err
|
||||
</pre></div>
|
||||
</div>
|
||||
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">Cannot</span> <span class="n">unify</span> <span class="s1">'two'</span> <span class="ow">and</span> <span class="n">f1</span><span class="o">.</span>
|
||||
</pre></div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
||||
<div class="sphinxsidebarwrapper">
|
||||
<h1 class="logo"><a href="../index.html">Thun</a></h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Navigation</h3>
|
||||
<ul class="current">
|
||||
<li class="toctree-l1"><a class="reference internal" href="Intro.html">Thun: Joy in Python</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../joy.html">Joy Interpreter</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../stack.html">Stack or Quote or Sequence or List…</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../parser.html">Parsing Text into Joy Expressions</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../pretty.html">Tracing Joy Execution</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../library.html">Function Reference</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../lib.html">Functions Grouped by, er, Function with Examples</a></li>
|
||||
<li class="toctree-l1"><a class="reference internal" href="../types.html">Type Inference of Joy Expressions</a></li>
|
||||
<li class="toctree-l1 current"><a class="reference internal" href="index.html">Essays about Programming in Joy</a><ul class="current">
|
||||
<li class="toctree-l2"><a class="reference internal" href="Developing.html">Developing a Program in Joy</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Quadratic.html">Quadratic formula</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Replacing.html">Replacing Functions in the Dictionary</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Recursion_Combinators.html">Recursion Combinators</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Ordered_Binary_Trees.html">Treating Trees I: Ordered Binary Trees</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Treestep.html">Treating Trees II: <code class="docutils literal notranslate"><span class="pre">treestep</span></code></a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Generator_Programs.html">Using <code class="docutils literal notranslate"><span class="pre">x</span></code> to Generate Values</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Newton-Raphson.html">Newton’s method</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Square_Spiral.html">Square Spiral Example Joy Code</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Zipper.html">Traversing Datastructures with Zippers</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Types.html">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li class="toctree-l2 current"><a class="current reference internal" href="#">Type Checking</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="NoUpdates.html">No Updates</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Categorical.html">Categorical Programming</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="The_Four_Operations.html">The Four Fundamental Operations of Definite Action</a></li>
|
||||
<li class="toctree-l2"><a class="reference internal" href="Derivatives_of_Regular_Expressions.html">∂RE</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="relations">
|
||||
<h3>Related Topics</h3>
|
||||
<ul>
|
||||
<li><a href="../index.html">Documentation overview</a><ul>
|
||||
<li><a href="index.html">Essays about Programming in Joy</a><ul>
|
||||
<li>Previous: <a href="Types.html" title="previous chapter">The Blissful Elegance of Typing Joy</a></li>
|
||||
<li>Next: <a href="NoUpdates.html" title="next chapter">No Updates</a></li>
|
||||
</ul></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="searchbox" style="display: none" role="search">
|
||||
<h3 id="searchlabel">Quick search</h3>
|
||||
<div class="searchformwrapper">
|
||||
<form class="search" action="../search.html" method="get">
|
||||
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>$('#searchbox').show(0);</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
</div>
|
||||
<div class="footer" role="contentinfo">
|
||||
<a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">
|
||||
<img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png" />
|
||||
</a>
|
||||
<br />
|
||||
<span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">Thun Documentation</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="https://joypy.osdn.io/" property="cc:attributionName" rel="cc:attributionURL">Simon Forman</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/4.0/">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://osdn.net/projects/joypy/" rel="dct:source">https://osdn.net/projects/joypy/</a>.
|
||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 4.4.0.
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue