{"id":29463676,"url":"https://github.com/fiddlerwoaroof/js-generic-functions","last_synced_at":"2025-07-14T05:38:22.796Z","repository":{"id":35076770,"uuid":"148074442","full_name":"fiddlerwoaroof/js-generic-functions","owner":"fiddlerwoaroof","description":"multimethods for javascript","archived":false,"fork":false,"pushed_at":"2025-07-06T21:13:24.000Z","size":23696,"stargazers_count":5,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-14T05:17:00.246Z","etag":null,"topics":["javascript","multimethods"],"latest_commit_sha":null,"homepage":"https://fiddlerwoaroof.github.io/js-generic-functions/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fiddlerwoaroof.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-09-09T23:28:23.000Z","updated_at":"2025-07-06T21:12:42.000Z","dependencies_parsed_at":"2023-10-21T10:25:10.640Z","dependency_job_id":"efadbe8a-aa84-48be-88aa-c92c64a3205b","html_url":"https://github.com/fiddlerwoaroof/js-generic-functions","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/fiddlerwoaroof/js-generic-functions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiddlerwoaroof%2Fjs-generic-functions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiddlerwoaroof%2Fjs-generic-functions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiddlerwoaroof%2Fjs-generic-functions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiddlerwoaroof%2Fjs-generic-functions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fiddlerwoaroof","download_url":"https://codeload.github.com/fiddlerwoaroof/js-generic-functions/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fiddlerwoaroof%2Fjs-generic-functions/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265246229,"owners_count":23734111,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","multimethods"],"created_at":"2025-07-14T05:38:22.252Z","updated_at":"2025-07-14T05:38:22.776Z","avatar_url":"https://github.com/fiddlerwoaroof.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+TITLE: README for js-generic-functions\n#+AUTHOR: Ed L\n#+HTML_HEAD: \u003clink rel=\"stylesheet\" href=\"./colors.css\" /\u003e\n#+EXPORT_FILE_NAME: docs/index.html\n\n[[https://www.npmjs.com/package/js-generic-functions][https://img.shields.io/npm/v/js-generic-functions.svg]] [[https://circleci.com/gh/fiddlerwoaroof/js-generic-functions.svg?style=svg]]\n\n** What is this?\n\n\nAn implementation of generic functions based on CLOS and the protocols\ndefined in the Art of the Metaobject protocol, adapted for JS.  These\nadaptations include using the prototype chain instead of classes and\nadditionally providing extensible specializers (as in\nhttps://github.com/sbcl/specializable). For the moment, this is only\nused to provide a Shape specializer, as the details of the interaction\nbetween such specializers and subtyping are an open question.\n\n** Docs\n\n*** Basic Usage\n\n#+NAME: imports\n#+BEGIN_SRC js\nimport { defgeneric } from \"./genfuns.js\";\n#+END_SRC\n\nDefining a function works by calling src_js{defgeneric} with some\ninformation about the function name and arguments. Methods are then\nadded by calling the appropriate methods with a pair of arguments: a\nlist of specializers (prototypes in the simple case, although there\nare other options) and a function to run if those specializers match.\n\n#+NAME: basic-definition\n#+BEGIN_SRC js\n  const example1generic = defgeneric(\"example1\", \"a\", \"b\")\n    .primary([Number, Object], (n, __) =\u003e [1, n])\n    .primary([Object, Number], (_, n) =\u003e [2, n])\n    .primary([Object, Object], (_, __) =\u003e [5, null]);\n#+END_SRC\n\nAfter a generic function has been defined, you can get the function to\ncall it by accessing its src_js{.fn} attribute.\n\n#+NAME: call-the-function\n#+BEGIN_SRC js\n  const example1 = example1generic.fn;\n\n  expect(example1(5, {})).toEqual([1, 5]);\n  expect(example1({}, 6)).toEqual([2, 6]);\n  expect(example1(\"hello\", {})).toEqual([5, null]);\n  expect(example1({}, \"world\")).toEqual([5, null]);\n  expect(example1({}, {})).toEqual([5, null]);\n#+END_SRC\n\nIf a separate reference to the generic function object is maintained,\nyou can add methods like so:\n\n#+NAME: add-methods\n#+BEGIN_SRC js\n  example1generic\n    .primary([String, Object], (s, __) =\u003e [3, s])\n    .primary([Object, String], (_, s) =\u003e [4, s]);\n\n  expect(example1(\"hello\", {})).toEqual([3, \"hello\"]);\n  expect(example1({}, \"world\")).toEqual([4, \"world\"]);\n#+END_SRC\n\n*** Other sorts of specializers\n#+NAME: specializer-import\n#+BEGIN_SRC js\n  import { Shape, Eql } from \"./genfuns.js\";\n#+END_SRC\n\n\n\n#+NAME: specializer-examples\n#+BEGIN_SRC js\n  const example2 = defgeneric(\"example2\", \"inp\")\n    .primary([Shape(\"a\", \"b\")], inp =\u003e `a: ${inp.a} b: ${inp.b}`)\n    .primary([Shape(\"a\")], inp =\u003e `a: ${inp.a} b: \u003cmissing\u003e`)\n    .primary([Shape([\"c\", 1])], inp =\u003e `c: one`)\n    .primary([Shape([\"c\", 2])], inp =\u003e `c: two`)\n    .primary([Eql(1)], inp =\u003e \"one\").fn;\n\n  expect(example2({ a: 3, q: \"whatever\" })).toEqual(\"a: 3 b: \u003cmissing\u003e\");\n  expect(example2({ a: 3, b: 4, q: \"whatever\" })).toEqual(\"a: 3 b: 4\");\n  expect(example2({ c: 1, q: \"whatever\" })).toEqual(\"c: one\");\n  expect(example2({ c: 2, q: \"whatever\" })).toEqual(\"c: two\");\n  expect(example2(1)).toEqual(\"one\");\n#+END_SRC\n\n#+BEGIN_SRC js :tangle src/doc.test.js :comments noweb :noweb tangle :exports none\n  \u003c\u003cimports\u003e\u003e\n  \u003c\u003cspecializer-import\u003e\u003e\n\n  describe(\"defgeneric\", () =\u003e {\n    test(\"methods get called appropriately\", () =\u003e {\n      \u003c\u003cbasic-definition\u003e\u003e\n\n      \u003c\u003ccall-the-function\u003e\u003e\n\n      \u003c\u003cadd-methods\u003e\u003e\n\n      \u003c\u003csample1\u003e\u003e\n    });\n    test ('specializers work as expected', () =\u003e {\n      \u003c\u003cspecializer-examples\u003e\u003e\n    })\n  });\n#+END_SRC\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffiddlerwoaroof%2Fjs-generic-functions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffiddlerwoaroof%2Fjs-generic-functions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffiddlerwoaroof%2Fjs-generic-functions/lists"}