{"id":16318611,"url":"https://github.com/vic/nor","last_synced_at":"2025-03-22T21:31:47.293Z","repository":{"id":4250214,"uuid":"5375838","full_name":"vic/NoR","owner":"vic","description":"There's No Return. A javascript reactive programming engine.","archived":false,"fork":false,"pushed_at":"2012-08-19T01:57:12.000Z","size":336,"stargazers_count":20,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-18T15:02:37.063Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://vic.github.com/NoR","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-08-11T00:01:42.000Z","updated_at":"2020-01-11T05:07:16.000Z","dependencies_parsed_at":"2022-09-02T14:00:32.841Z","dependency_job_id":null,"html_url":"https://github.com/vic/NoR","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vic%2FNoR","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vic%2FNoR/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vic%2FNoR/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vic%2FNoR/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vic","download_url":"https://codeload.github.com/vic/NoR/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245022616,"owners_count":20548568,"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":[],"created_at":"2024-10-10T22:24:06.616Z","updated_at":"2025-03-22T21:31:47.018Z","avatar_url":"https://github.com/vic.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NoR - There's No Return.\n\nA reactive programming engine for javascript.\n\n## Getting Started\n\nSo what's `NoR` about?, well, simply put it's just my take at what I\nlearned to be `reactive programming` yet i'm not an expert at all.\n\nEven though the term `reactive` might seem like unknown, most of us\nalready interact with a reactive system all the time.\n\nWhen you open your spreadsheet program and start using formulas that\nuse values from other cells, you can observe that if you change a\nvalue in one of that cells all other cells that depend on it get\nupdated accordingly, well, spreadsheets are one example of\n`reactive programming`.\n\nIf you ever played around with protoboards and logic gates, you can\nrecall that you used to connect all those little gates to achieve\nsomething, say a counter, a clock or any other digital system, well,\nthat's also `reactive`, as soon as you connect all the pieces and\nthrow a little voltage at it, you get it to work (or not :D).\n\nIn our days, we see `reactive` systems all around, in recent web\ndevelopment people are using more and more javascript, and as many\nof us have found, front-end development is almost always enterely\nevent based, that is, when something changes, you have to `react`.\nA lot of libraries handle reacting to changes, from using\n[jQuery][jquery] to act upon a browser event, [Backbone.js][backbone]\nand [Knockout.js][knockout] to bind your view and model, etc.\n\n[jquery]: http://jquery.com\n[knockout]: http://knockoutjs.com\n[backbone]: http://backbonejs.org\n\n## There's No Return\n\nOk, so imagine you build a little logic gate (the [NOR gate][nor])\n\n![The NOR logic gate](http://upload.wikimedia.org/wikipedia/commons/c/c6/NOR_ANSI_Labelled.svg)\n\nIf we try to implement it on javascript, provably it would be like this:\n\n```javascript\nvar NOR = function(a, b){\n  var q = !(a || b); // just for you to see a, b and q\n  return q;\n}\n```\n\nso far so good, well, implementing the `NOR` gate is a trivial\nprogram. But what happens with more complex functions that can\npossibly fail, in you javascript programming, have you ever seen\nfunctions like the following?:\n\n```javascript\nvar complex = function(some, thing){\n   // if everything goes fine, we return a value\n   // otherwise the make function will just\n   // throw an exception, how else do we handle failure?\n   return make(some, thing, strange)\n}\n```\n\nthe bad thing about functions like this is that its users need to\nknow that it can possibly throw an exception as means of handling\nfailure, (would you really throw an exception just because some value\ndoesnt have the form you expected? please dont!). To fix this, most\npeople give the complex function a callback (or a pair of callbacks)\nto be called on success and/or error.\n\n```javascript\nvar complex = function(some, thing, callback){\n   if(everythingGoesFine) {\n     callback(successValue, null)\n   } else {\n     callback(null, errorValue)\n   }\n}\n```\n\nYou see? now *There's No Return*. All the function does is do its\namazing stuff and invoke the callback accordingly. But again as user\nof this function you need to know that callback can take two arguments\nand not just only one, or you can make the complex function take two\ncallbacks one for success and one for error. That is a callback for\neach output the function can have.\n\nHow does this all relates to `NoR` and `reactive programming`?, read on.\n\n[nor]: http://en.wikipedia.org/wiki/NOR_logic\n\n## Reacting to change\n\nSuppose we try to implement our `NOR` logic gate again wihout using\nreturn.\n\n```javascript\nvar NOR = function(a, b, q) {\n  q( !( a || b ) )\n}\n```\n\nSo now our function takes two values `a` and `b` and a callback\nfunction `q`. *Every time you invoke* this function you give it two\nvalues and maybe a different callback. It doenst still reacts to\nchange automatically, whenever the value of `a` or `b` change you\nhave to apply them to the function.\n\nThe logic gates (or the spreadsheet formulas) react to changes on\ntheir input, and automatically produce a new value for them.\n\nNow image our same NOR implementation, but this time with `a` and\n`b` also being functions. These functions if given no arguments just\ngive you the current *state* of each input, and our function looks like:\n\n```javascript\nvar NOR = function(a, b, q) {\n  q( !( a() || b() ) )\n}\n```\n\n## How it works\n\nUsing the `NoR` function to create a *gate* that reacts\nto changes on its inputs, and our NOR gate is:\n\n```javascript\nvar NOR = NoR(function(a, b, q){\n  q( !( a() || b() ) )\n})\n```\n\nLooks pretty much like our previous implementation, the only\ndifference being that the function is wrapped with `NoR`.\nWhat `NoR` does is creating a *cell* for each function parameter.\n\nA *cell* is just something that looks like a function and serves to\nhold a value. When a cell is given no arguments, it just returns its\ncurrent value, but when an argument is given to it, it sets its new\nvalue and notifies everyone interested on that cell of its change.\n\nIn our example, `a`, `b` and `c` are cells, but only the first two are\nused as inputs, the third as an output.\n\nThe return value of the `NoR` function also looks like a function:\n\n```\n; setting a = false b = true\nNOR(false, true) ; =\u003e undefined\n```\n\nHowever it doesnt act as one of those functions that return values or\naccept callbacks. What we have just did is simply setting the `a` *cell*\nto `true` and the `b` *cell* to `false`. The result of the operation is\nasynchronous, that is, we cant be sure in what exact second we have the\nresponse.\n\nJust like with *promises* we have something that represents a value in\nthe future, we dont know exactly when, but it *will* hold the response\nvalue.\n\nSo what we do for using the value of `c` is to listen for changes\non `c` by *subscribing* to it.\n\nFor example:\n\n```javascript\nNOR.c.subscribe(function(newC){\n  console.log(\"OK, the new value of c is\", newC)\n})\n\nNOR.b(false) // here we are changing the value of the b cell\n\n// sometime in the future we see\n// a message printed to stdout.\n```\n\nThe `NoR` function form is:\n\n```javascript\nNoR(gate, wiring, self)\n```\n\nWhere `gate` is a function that receives *cells* and is invoked\nwhenever one of them changes. An `wiring` function can be specified\nthat receives the same *cells* than `gate` for the sake of setting up\ncell subscriptions or creating inner gates. If a value for\n`self` if given it will be wrapped on an special *cell* named\n`self` and its value will be used as `this` whenever `gate` gets\ncalled, of course changing the gate's self will trigger its evaluation.\n\nFor example, to build an `XOR` gate using just the universal `NOR`\ngate, you can do:\n\n![Implementing a XNOR gate using NOR gates](http://upload.wikimedia.org/wikipedia/commons/f/f8/XNOR_using_NOR.svg)\n\n```javascript\n\n// The universal NOR logic gate.\nvar NOR = NoR(function(a, b, g){\n  g( !( a() || b() ) )\n})\n\n// the gate has no implementation as it's actually\n// the result of the combination of several NOR gates\n// and their outputs. We wire all of them on\n// the setup function.\n//\n// Note that the XNOR gate exposes just three ports:\n// a, b and q.\n//\n// However the gates wired inside use some others like\n// x, m and n. Follow the image above.\nvar XNOR = NoR(function(a, b, q){}, function(a, b, x, m, n, q){\n  // Using the new operator on a gate\n  // simply cretes a copy of that gate\n  // and we assign each its ports.\n  new NOR(a, b, x)\n  new NOR(a, x, m)\n  new NOR(b, x, n)\n  new NOR(m, n, q)\n})\n\n```\n\n### On the server\nInstall the module with: `npm install NoR`\n\n```javascript\nvar NoR = require('NoR');\nNoR.awesome(); // \"awesome\"\n```\n\n### In the browser\nDownload the [production version][min] or the [development version][max].\n\n[min]: https://raw.github.com/vic/NoR/master/dist/NoR.min.js\n[max]: https://raw.github.com/vic/NoR/master/dist/NoR.js\n\nIn your web page:\n\n```html\n\u003cscript src=\"dist/NoR.min.js\"\u003e\u003c/script\u003e\n```\n\n## Documentation\n\nUse our [wiki][wiki].\n\n[wiki]: https://github.com/vic/NoR/wiki\n\n## Examples\n\nSee the [examples/][examples] directory and try running some of them.\n\n```shell\n$ node examples/ten_times.js\n```\n\nAn example on how to implement a [JK flip-flop][jk] can be found [here][jke]\n\n![JK flip flip](http://hyperphysics.phy-astr.gsu.edu/hbase/electronic/ietron/jk2.gif)\n\n[jk]: http://hyperphysics.phy-astr.gsu.edu/hbase/electronic/jkflipflop.html#c2\n[examples]: https://github.com/vic/NoR/tree/master/examples\n[jke]: https://github.com/vic/NoR/blob/master/examples/jk-flipflop.js\n\n## Contributing\n\nAll contributions are welcome, of course you [fork][fork] the proyect\ndo some changes on what you are interested, new features, typos,\ntests, examples or anything you want and finally you can send a\n[pull request][pulls] and I'll be more than grateful to you.\n\n[fork]: https://github.com/vic/NoR/fork_select\n[pulls]: https://github.com/vic/NoR/pulls\n\n## Developing\n\nFirst get a [fork][fork] of `NoR` and install its development\ndependencies.\n\n```shell\n$ npm install\n```\n\nTo run specs use the `npm test` command.\n\n## License\nCopyright (c) 2012 Victor Borja\nLicensed under the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvic%2Fnor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvic%2Fnor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvic%2Fnor/lists"}