git.fiddlerwoaroof.com
docs/index.html
6660eb1c
 <?xml version="1.0" encoding="utf-8"?>
0a9ffe6c
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
35f07878
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
0a9ffe6c
   <head>
14341a75
     <!-- 2022-03-26 Sat 00:38 -->
0a9ffe6c
     <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1" />
     <title>README for js-generic-functions</title>
     <meta name="author" content="Ed L" />
     <meta name="generator" content="Org Mode" />
     <style>
       #content {
         max-width: 60em;
         margin: auto;
       }
       .title {
         text-align: center;
         margin-bottom: 0.2em;
       }
       .subtitle {
         text-align: center;
         font-size: medium;
         font-weight: bold;
         margin-top: 0;
       }
       .todo {
         font-family: monospace;
         color: red;
       }
       .done {
         font-family: monospace;
         color: green;
       }
       .priority {
         font-family: monospace;
         color: orange;
       }
       .tag {
         background-color: #eee;
         font-family: monospace;
         padding: 2px;
         font-size: 80%;
         font-weight: normal;
       }
       .timestamp {
         color: #bebebe;
       }
       .timestamp-kwd {
         color: #5f9ea0;
       }
       .org-right {
         margin-left: auto;
         margin-right: 0px;
         text-align: right;
       }
       .org-left {
         margin-left: 0px;
         margin-right: auto;
         text-align: left;
       }
       .org-center {
         margin-left: auto;
         margin-right: auto;
         text-align: center;
       }
       .underline {
         text-decoration: underline;
       }
       #postamble p,
       #preamble p {
         font-size: 90%;
         margin: 0.2em;
       }
       p.verse {
         margin-left: 3%;
       }
       pre {
         border: 1px solid #e6e6e6;
         border-radius: 3px;
         background-color: #f2f2f2;
         padding: 8pt;
         font-family: monospace;
         overflow: auto;
         margin: 1.2em;
       }
       pre.src {
         position: relative;
         overflow: auto;
       }
       pre.src:before {
         display: none;
         position: absolute;
         top: -8px;
         right: 12px;
         padding: 3px;
         color: #555;
         background-color: #f2f2f299;
       }
       pre.src:hover:before {
         display: inline;
         margin-top: 14px;
       }
       /* Languages per Org manual */
       pre.src-asymptote:before {
         content: "Asymptote";
       }
       pre.src-awk:before {
         content: "Awk";
       }
       pre.src-authinfo::before {
         content: "Authinfo";
       }
       pre.src-C:before {
         content: "C";
       }
       /* pre.src-C++ doesn't work in CSS */
       pre.src-clojure:before {
         content: "Clojure";
       }
       pre.src-css:before {
         content: "CSS";
       }
       pre.src-D:before {
         content: "D";
       }
       pre.src-ditaa:before {
         content: "ditaa";
       }
       pre.src-dot:before {
         content: "Graphviz";
       }
       pre.src-calc:before {
         content: "Emacs Calc";
       }
       pre.src-emacs-lisp:before {
         content: "Emacs Lisp";
       }
       pre.src-fortran:before {
         content: "Fortran";
       }
       pre.src-gnuplot:before {
         content: "gnuplot";
       }
       pre.src-haskell:before {
         content: "Haskell";
       }
       pre.src-hledger:before {
         content: "hledger";
       }
       pre.src-java:before {
         content: "Java";
       }
       pre.src-js:before {
         content: "Javascript";
       }
       pre.src-latex:before {
         content: "LaTeX";
       }
       pre.src-ledger:before {
         content: "Ledger";
       }
       pre.src-lisp:before {
         content: "Lisp";
       }
       pre.src-lilypond:before {
         content: "Lilypond";
       }
       pre.src-lua:before {
         content: "Lua";
       }
       pre.src-matlab:before {
         content: "MATLAB";
       }
       pre.src-mscgen:before {
         content: "Mscgen";
       }
       pre.src-ocaml:before {
         content: "Objective Caml";
       }
       pre.src-octave:before {
         content: "Octave";
       }
       pre.src-org:before {
         content: "Org mode";
       }
       pre.src-oz:before {
         content: "OZ";
       }
       pre.src-plantuml:before {
         content: "Plantuml";
       }
       pre.src-processing:before {
         content: "Processing.js";
       }
       pre.src-python:before {
         content: "Python";
       }
       pre.src-R:before {
         content: "R";
       }
       pre.src-ruby:before {
         content: "Ruby";
       }
       pre.src-sass:before {
         content: "Sass";
       }
       pre.src-scheme:before {
         content: "Scheme";
       }
       pre.src-screen:before {
         content: "Gnu Screen";
       }
       pre.src-sed:before {
         content: "Sed";
       }
       pre.src-sh:before {
         content: "shell";
       }
       pre.src-sql:before {
         content: "SQL";
       }
       pre.src-sqlite:before {
         content: "SQLite";
       }
       /* additional languages in org.el's org-babel-load-languages alist */
       pre.src-forth:before {
         content: "Forth";
       }
       pre.src-io:before {
         content: "IO";
       }
       pre.src-J:before {
         content: "J";
       }
       pre.src-makefile:before {
         content: "Makefile";
       }
       pre.src-maxima:before {
         content: "Maxima";
       }
       pre.src-perl:before {
         content: "Perl";
       }
       pre.src-picolisp:before {
         content: "Pico Lisp";
       }
       pre.src-scala:before {
         content: "Scala";
       }
       pre.src-shell:before {
         content: "Shell Script";
       }
       pre.src-ebnf2ps:before {
         content: "ebfn2ps";
       }
       /* additional language identifiers per "defun org-babel-execute"
35f07878
        in ob-*.el */
0a9ffe6c
       pre.src-cpp:before {
         content: "C++";
       }
       pre.src-abc:before {
         content: "ABC";
       }
       pre.src-coq:before {
         content: "Coq";
       }
       pre.src-groovy:before {
         content: "Groovy";
       }
       /* additional language identifiers from org-babel-shell-names in
35f07878
      ob-shell.el: ob-shell is the only babel language using a lambda to put
      the execution function name together. */
0a9ffe6c
       pre.src-bash:before {
         content: "bash";
       }
       pre.src-csh:before {
         content: "csh";
       }
       pre.src-ash:before {
         content: "ash";
       }
       pre.src-dash:before {
         content: "dash";
       }
       pre.src-ksh:before {
         content: "ksh";
       }
       pre.src-mksh:before {
         content: "mksh";
       }
       pre.src-posh:before {
         content: "posh";
       }
       /* Additional Emacs modes also supported by the LaTeX listings package */
       pre.src-ada:before {
         content: "Ada";
       }
       pre.src-asm:before {
         content: "Assembler";
       }
       pre.src-caml:before {
         content: "Caml";
       }
       pre.src-delphi:before {
         content: "Delphi";
       }
       pre.src-html:before {
         content: "HTML";
       }
       pre.src-idl:before {
         content: "IDL";
       }
       pre.src-mercury:before {
         content: "Mercury";
       }
       pre.src-metapost:before {
         content: "MetaPost";
       }
       pre.src-modula-2:before {
         content: "Modula-2";
       }
       pre.src-pascal:before {
         content: "Pascal";
       }
       pre.src-ps:before {
         content: "PostScript";
       }
       pre.src-prolog:before {
         content: "Prolog";
       }
       pre.src-simula:before {
         content: "Simula";
       }
       pre.src-tcl:before {
         content: "tcl";
       }
       pre.src-tex:before {
         content: "TeX";
       }
       pre.src-plain-tex:before {
         content: "Plain TeX";
       }
       pre.src-verilog:before {
         content: "Verilog";
       }
       pre.src-vhdl:before {
         content: "VHDL";
       }
       pre.src-xml:before {
         content: "XML";
       }
       pre.src-nxml:before {
         content: "XML";
       }
       /* add a generic configuration mode; LaTeX export needs an additional
35f07878
      (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
0a9ffe6c
       pre.src-conf:before {
         content: "Configuration File";
       }
35f07878
 
0a9ffe6c
       table {
         border-collapse: collapse;
       }
       caption.t-above {
         caption-side: top;
       }
       caption.t-bottom {
         caption-side: bottom;
       }
       td,
       th {
         vertical-align: top;
       }
       th.org-right {
         text-align: center;
       }
       th.org-left {
         text-align: center;
       }
       th.org-center {
         text-align: center;
       }
       td.org-right {
         text-align: right;
       }
       td.org-left {
         text-align: left;
       }
       td.org-center {
         text-align: center;
       }
       dt {
         font-weight: bold;
       }
       .footpara {
         display: inline;
       }
       .footdef {
         margin-bottom: 1em;
       }
       .figure {
         padding: 1em;
       }
       .figure p {
         text-align: center;
       }
       .equation-container {
         display: table;
         text-align: center;
         width: 100%;
       }
       .equation {
         vertical-align: middle;
       }
       .equation-label {
         display: table-cell;
         text-align: right;
         vertical-align: middle;
       }
       .inlinetask {
         padding: 10px;
         border: 2px solid gray;
         margin: 10px;
         background: #ffffcc;
       }
       #org-div-home-and-up {
         text-align: right;
         font-size: 70%;
         white-space: nowrap;
       }
       textarea {
         overflow-x: auto;
       }
       .linenr {
         font-size: smaller;
       }
       .code-highlighted {
         background-color: #ffff00;
       }
       .org-info-js_info-navigation {
         border-style: none;
       }
       #org-info-js_console-label {
         font-size: 10px;
         font-weight: bold;
         white-space: nowrap;
       }
       .org-info-js_search-highlight {
         background-color: #ffff00;
         color: #000000;
         font-weight: bold;
       }
       .org-svg {
         width: 90%;
       }
     </style>
     <link rel="stylesheet" href="./colors.css" />
   </head>
   <body>
     <div id="content" class="content">
       <h1 class="title">README for js-generic-functions</h1>
       <div id="table-of-contents" role="doc-toc">
         <h2>Table of Contents</h2>
         <div id="text-table-of-contents" role="doc-toc">
           <ul>
14341a75
             <li><a href="#org071b24a">1. What is this?</a></li>
0a9ffe6c
             <li>
14341a75
               <a href="#org0f0b569">2. Docs</a>
0a9ffe6c
               <ul>
14341a75
                 <li><a href="#org1cbf251">2.1. Basic Usage</a></li>
0a9ffe6c
                 <li>
14341a75
                   <a href="#org4edb380">2.2. Other sorts of specializers</a>
0a9ffe6c
                 </li>
               </ul>
             </li>
           </ul>
         </div>
       </div>
6660eb1c
       <p>
         <a href="https://www.npmjs.com/package/js-generic-functions"
           ><img
             src="https://img.shields.io/npm/v/js-generic-functions.svg"
             alt="js-generic-functions.svg"
             class="org-svg"
         /></a>
         <img
           src="https://circleci.com/gh/fiddlerwoaroof/js-generic-functions.svg?style=svg"
14341a75
           alt="js-generic-functions.svg?style=svg" />
6660eb1c
       </p>
35f07878
 
14341a75
       <div id="outline-container-org071b24a" class="outline-2">
         <h2 id="org071b24a">
0a9ffe6c
           <span class="section-number-2">1.</span> What is this?
         </h2>
         <div class="outline-text-2" id="text-1">
           <p>
             An implementation of generic functions based on CLOS and the
             protocols defined in the Art of the Metaobject protocol, adapted for
             JS. These adaptations include using the prototype chain instead of
             classes and additionally providing extensible specializers (as in
             <a href="https://github.com/sbcl/specializable"
               >https://github.com/sbcl/specializable</a
             >). For the moment, this is only used to provide a Shape
             specializer, as the details of the interaction between such
             specializers and subtyping are an open question.
           </p>
         </div>
       </div>
35f07878
 
14341a75
       <div id="outline-container-org0f0b569" class="outline-2">
         <h2 id="org0f0b569"><span class="section-number-2">2.</span> Docs</h2>
0a9ffe6c
         <div class="outline-text-2" id="text-2"></div>
14341a75
         <div id="outline-container-org1cbf251" class="outline-3">
           <h3 id="org1cbf251">
0a9ffe6c
             <span class="section-number-3">2.1.</span> Basic Usage
           </h3>
           <div class="outline-text-3" id="text-2-1">
             <div class="org-src-container">
               <pre
                 class="src src-js"
14341a75
                 id="org5a0cb5c"><span style="color: #F0DFAF;">import</span> { defgeneric } from <span style="color: #D0BF8F;">"./genfuns.js"</span>;
35f07878
 </pre>
0a9ffe6c
             </div>
35f07878
 
0a9ffe6c
             <p>
               Defining a function works by calling with some information about
               the function name and arguments. Methods are then added by calling
               the appropriate methods with a pair of arguments: a list of
               specializers (prototypes in the simple case, although there are
               other options) and a function to run if those specializers match.
             </p>
35f07878
 
0a9ffe6c
             <div class="org-src-container">
               <pre
                 class="src src-js"
14341a75
                 id="orgb88093c"><span style="color: #F0DFAF;">const</span> <span style="color: #DC8CC3;">example1generic</span> = defgeneric(<span style="color: #D0BF8F;">"example1"</span>, <span style="color: #D0BF8F;">"a"</span>, <span style="color: #D0BF8F;">"b"</span>)
35f07878
   .primary([Number, Object], (n, __) =&gt; [1, n])
   .primary([Object, Number], (_, n) =&gt; [2, n])
   .primary([Object, Object], (_, __) =&gt; [5, <span style="font-weight: bold;">null</span>]);
 </pre>
0a9ffe6c
             </div>
35f07878
 
0a9ffe6c
             <p>
               After a generic function has been defined, you can get the
               function to call it by accessing its attribute.
             </p>
35f07878
 
0a9ffe6c
             <div class="org-src-container">
               <pre
                 class="src src-js"
14341a75
                 id="org8eb1237"><span style="color: #F0DFAF;">const</span> <span style="color: #DC8CC3;">example1</span> = example1generic.fn;
35f07878
 
 expect(example1(5, {})).toEqual([1, 5]);
 expect(example1({}, 6)).toEqual([2, 6]);
 expect(example1(<span style="color: #D0BF8F;">"hello"</span>, {})).toEqual([5, <span style="font-weight: bold;">null</span>]);
 expect(example1({}, <span style="color: #D0BF8F;">"world"</span>)).toEqual([5, <span style="font-weight: bold;">null</span>]);
 expect(example1({}, {})).toEqual([5, <span style="font-weight: bold;">null</span>]);
 </pre>
0a9ffe6c
             </div>
35f07878
 
0a9ffe6c
             <p>
               If a separate reference to the generic function object is
               maintained, you can add methods like so:
             </p>
35f07878
 
0a9ffe6c
             <div class="org-src-container">
14341a75
               <pre class="src src-js" id="org3eaa9ed">example1generic
35f07878
   .primary([String, Object], (s, __) =&gt; [3, s])
   .primary([Object, String], (_, s) =&gt; [4, s]);
 
 expect(example1(<span style="color: #D0BF8F;">"hello"</span>, {})).toEqual([3, <span style="color: #D0BF8F;">"hello"</span>]);
 expect(example1({}, <span style="color: #D0BF8F;">"world"</span>)).toEqual([4, <span style="color: #D0BF8F;">"world"</span>]);
 </pre>
0a9ffe6c
             </div>
           </div>
         </div>
35f07878
 
14341a75
         <div id="outline-container-org4edb380" class="outline-3">
           <h3 id="org4edb380">
0a9ffe6c
             <span class="section-number-3">2.2.</span> Other sorts of
             specializers
           </h3>
           <div class="outline-text-3" id="text-2-2">
             <div class="org-src-container">
               <pre
                 class="src src-js"
14341a75
                 id="org8310490"><span style="color: #F0DFAF;">import</span> { Shape, Eql } from <span style="color: #D0BF8F;">"./genfuns.js"</span>;
35f07878
 </pre>
0a9ffe6c
             </div>
35f07878
 
0a9ffe6c
             <div class="org-src-container">
               <pre
                 class="src src-js"
14341a75
                 id="org34ae3c2"><span style="color: #F0DFAF;">const</span> <span style="color: #DC8CC3;">example2</span> = defgeneric(<span style="color: #D0BF8F;">"example2"</span>, <span style="color: #D0BF8F;">"inp"</span>)
35f07878
   .primary([Shape(<span style="color: #D0BF8F;">"a"</span>, <span style="color: #D0BF8F;">"b"</span>)], inp =&gt; <span style="color: #D0BF8F;">`a: ${inp.a} b: ${inp.b}`</span>)
   .primary([Shape(<span style="color: #D0BF8F;">"a"</span>)], inp =&gt; <span style="color: #D0BF8F;">`a: ${inp.a} b: &lt;missing&gt;`</span>)
   .primary([Shape([<span style="color: #D0BF8F;">"c"</span>, 1])], inp =&gt; <span style="color: #D0BF8F;">`c: one`</span>)
   .primary([Shape([<span style="color: #D0BF8F;">"c"</span>, 2])], inp =&gt; <span style="color: #D0BF8F;">`c: two`</span>)
   .primary([Eql(1)], inp =&gt; <span style="color: #D0BF8F;">"one"</span>).fn;
 
 expect(example2({ a: 3, q: <span style="color: #D0BF8F;">"whatever"</span> })).toEqual(<span style="color: #D0BF8F;">"a: 3 b: &lt;missing&gt;"</span>);
 expect(example2({ a: 3, b: 4, q: <span style="color: #D0BF8F;">"whatever"</span> })).toEqual(<span style="color: #D0BF8F;">"a: 3 b: 4"</span>);
 expect(example2({ c: 1, q: <span style="color: #D0BF8F;">"whatever"</span> })).toEqual(<span style="color: #D0BF8F;">"c: one"</span>);
 expect(example2({ c: 2, q: <span style="color: #D0BF8F;">"whatever"</span> })).toEqual(<span style="color: #D0BF8F;">"c: two"</span>);
 expect(example2(1)).toEqual(<span style="color: #D0BF8F;">"one"</span>);
 </pre>
0a9ffe6c
             </div>
           </div>
         </div>
       </div>
     </div>
     <div id="postamble" class="status">
       <p class="author">Author: Ed L</p>
14341a75
       <p class="date">Created: 2022-03-26 Sat 00:38</p>
0a9ffe6c
       <p class="validation">
         <a href="https://validator.w3.org/check?uri=referer">Validate</a>
       </p>
     </div>
   </body>
35f07878
 </html>