git.fiddlerwoaroof.com
Raw Blame History
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
    <!-- 2022-03-26 Sat 00:38 -->
    <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"
       in ob-*.el */
      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
     ob-shell.el: ob-shell is the only babel language using a lambda to put
     the execution function name together. */
      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
     (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
      pre.src-conf:before {
        content: "Configuration File";
      }

      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>
            <li><a href="#org071b24a">1. What is this?</a></li>
            <li>
              <a href="#org0f0b569">2. Docs</a>
              <ul>
                <li><a href="#org1cbf251">2.1. Basic Usage</a></li>
                <li>
                  <a href="#org4edb380">2.2. Other sorts of specializers</a>
                </li>
              </ul>
            </li>
          </ul>
        </div>
      </div>
      <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"
          alt="js-generic-functions.svg?style=svg" />
      </p>

      <div id="outline-container-org071b24a" class="outline-2">
        <h2 id="org071b24a">
          <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>

      <div id="outline-container-org0f0b569" class="outline-2">
        <h2 id="org0f0b569"><span class="section-number-2">2.</span> Docs</h2>
        <div class="outline-text-2" id="text-2"></div>
        <div id="outline-container-org1cbf251" class="outline-3">
          <h3 id="org1cbf251">
            <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"
                id="org5a0cb5c"><span style="color: #F0DFAF;">import</span> { defgeneric } from <span style="color: #D0BF8F;">"./genfuns.js"</span>;
</pre>
            </div>

            <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>

            <div class="org-src-container">
              <pre
                class="src src-js"
                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>)
  .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>
            </div>

            <p>
              After a generic function has been defined, you can get the
              function to call it by accessing its attribute.
            </p>

            <div class="org-src-container">
              <pre
                class="src src-js"
                id="org8eb1237"><span style="color: #F0DFAF;">const</span> <span style="color: #DC8CC3;">example1</span> = example1generic.fn;

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>
            </div>

            <p>
              If a separate reference to the generic function object is
              maintained, you can add methods like so:
            </p>

            <div class="org-src-container">
              <pre class="src src-js" id="org3eaa9ed">example1generic
  .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>
            </div>
          </div>
        </div>

        <div id="outline-container-org4edb380" class="outline-3">
          <h3 id="org4edb380">
            <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"
                id="org8310490"><span style="color: #F0DFAF;">import</span> { Shape, Eql } from <span style="color: #D0BF8F;">"./genfuns.js"</span>;
</pre>
            </div>

            <div class="org-src-container">
              <pre
                class="src src-js"
                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>)
  .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>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div id="postamble" class="status">
      <p class="author">Author: Ed L</p>
      <p class="date">Created: 2022-03-26 Sat 00:38</p>
      <p class="validation">
        <a href="https://validator.w3.org/check?uri=referer">Validate</a>
      </p>
    </div>
  </body>
</html>