<?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, __) => [1, n]) .primary([Object, Number], (_, n) => [2, n]) .primary([Object, Object], (_, __) => [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, __) => [3, s]) .primary([Object, String], (_, s) => [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 => <span style="color: #D0BF8F;">`a: ${inp.a} b: ${inp.b}`</span>) .primary([Shape(<span style="color: #D0BF8F;">"a"</span>)], inp => <span style="color: #D0BF8F;">`a: ${inp.a} b: <missing>`</span>) .primary([Shape([<span style="color: #D0BF8F;">"c"</span>, 1])], inp => <span style="color: #D0BF8F;">`c: one`</span>) .primary([Shape([<span style="color: #D0BF8F;">"c"</span>, 2])], inp => <span style="color: #D0BF8F;">`c: two`</span>) .primary([Eql(1)], inp => <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: <missing>"</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>