Created
June 3, 2017 03:36
-
-
Save SeijiEmery/7d3d3b7d561ca669e6212c24866d9a82 to your computer and use it in GitHub Desktop.
Another FRP example (JS)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // Observables / behaviors / whatever you want to call these are a pretty simple concept: | |
| // instead of direct variables you operate with functions, and chains that you can mutate | |
| // with more functions. The real work, of course, is in writing a framework / implementation | |
| // that doesn't suck / have terrible performance, since calling 10-20 functions to read one | |
| // variable is not exactly efficient x) | |
| // | |
| // A real library (eg. Rx, React) would have layers of caching and careful engineering that | |
| // this naive implementation does not have. Nevertheless, the core idea is trivial; it's | |
| // building an efficient implementation that's difficult. | |
| // | |
| (function () { | |
| if (typeof(assert) !== "function") { | |
| this.assert = function assert (condition, msg) { | |
| if (!condition) { | |
| if (msg) throw new Error("Assertion failed: "+msg); | |
| else throw new Error("Assertion failed"); | |
| } | |
| } | |
| } | |
| })(); | |
| function Observable () {} | |
| function ObservableSource (value) { | |
| this._value = value; | |
| } | |
| ObservableSource.prototype = Object.create(Observable); | |
| ObservableSource.prototype.constructor = ObservableSource; | |
| ObservableSource.prototype.set = function (value) { this._value = value; } | |
| ObservableSource.prototype.value = function () { return this._value; } | |
| function SingleObserver (parent, fcn) { | |
| this.parent = parent; | |
| this.fcn = fcn; | |
| } | |
| SingleObserver.prototype = Object.create(Observable); | |
| SingleObserver.prototype.constructor = SingleObserver; | |
| SingleObserver.prototype.value = function () { | |
| return this.fcn.call(this, this.parent.value()); | |
| } | |
| function MultiObserver (parents, fcn) { | |
| this.fcn = fcn; | |
| this.parents = parents; | |
| } | |
| MultiObserver.prototype = Object.create(Observable); | |
| MultiObserver.prototype.constructor = MultiObserver; | |
| MultiObserver.prototype.value = function () { | |
| return this.fcn.apply(this, this.parents.map(function (parent) { return parent.value(); })); | |
| } | |
| function observe (sources, fcn) { | |
| if (sources instanceof Array && sources.length != 1) { | |
| return new MultiObserver(sources, fcn); | |
| } | |
| return new SingleObserver(sources, fcn); | |
| } | |
| function isObservable (x) { return typeof(x) === "object" && typeof(x.value) === "function"; } | |
| assert(isObservable(new ObservableSource())); | |
| assert(isObservable(new MultiObserver())); | |
| assert(isObservable(new SingleObserver())); | |
| assert(isObservable({ value: function (){} })); | |
| assert(!isObservable({ value: {} })); | |
| assert(!isObservable({})); | |
| assert(!isObservable("fubar")); | |
| assert(!isObservable(10)); | |
| assert(!isObservable(function () {})); | |
| function observableBinaryFcn (a, b, fcn) { | |
| if (isObservable(a) && isObservable(b)) { | |
| return new MultiObserver([ a, b ], fcn); | |
| } else if (isObservable(a)) { | |
| return new SingleObserver(a, function (value) { return fcn(value, b); }); | |
| } else if (isObservable(b)) { | |
| return new SingleObserver(b, function (value) { return fcn(a, value); }); | |
| } else { | |
| return fcn(a, b); | |
| } | |
| } | |
| function plus (a, b) { return observableBinaryFcn(a, b, function (a, b) { return a + b; }); } | |
| function minus (a, b) { return observableBinaryFcn(a, b, function (a, b) { return a - b; }); } | |
| function mul (a, b) { return observableBinaryFcn(a, b, function (a, b) { return a * b; }); } | |
| function div (a, b) { return observableBinaryFcn(a, b, function (a, b) { return a / b; }); } | |
| function mod (a, b) { return observableBinaryFcn(a, b, function (a, b) { return a % b; }); } | |
| assert(plus (2, -3) == -1); | |
| assert(minus(2, -3) == 5); | |
| assert(mul(2, -3) == -6); | |
| assert(div(2, -3) == -(2 / 3)); | |
| assert(mod(2, -3) == (2 % (-3))); | |
| var Window = { | |
| x: new ObservableSource(0.0), | |
| y: new ObservableSource(0.0), | |
| }; | |
| var a = new SingleObserver(Window.x, function (value) { return value + 100.0; }); | |
| var b = observe(Window.x, function (value) { return value + 100.0; }); | |
| var c = plus(Window.x, 100.0); | |
| assert(Window.x.value() == 0); | |
| assert(a.value() == 100.0); | |
| assert(b.value() == 100.0); | |
| assert(c.value() == 100.0); | |
| Window.x.set(50.0); | |
| assert(Window.x.value() == 50.0); | |
| assert(a.value() == 150.0); | |
| assert(b.value() == 150.0); | |
| assert(c.value() == 150.0); | |
| // console.log("Window.x = "+Window.x.value()); | |
| // console.log("1st: "+new SingleObserver(Window.x, function (value) { return value + 100; }).value()); | |
| // console.log("2nd: "+observe(Window.x, function (value) { return value + 100; }).value()); | |
| // console.log("3rd: "+plus(Window.x, 100).value()); | |
| Window.x.set(800); | |
| Window.y.set(600); | |
| var xt = plus(mod(plus(Window.x, 100), 200), -40); | |
| var windowPerimeter = mul(plus(Window.x, Window.y), 2); | |
| var windowArea = mul(Window.x, Window.y); | |
| var windowAspect = div(Window.x, Window.y); | |
| function writeValues () { | |
| console.log( | |
| "x = "+Window.x.value()+ | |
| ", y = "+Window.y.value()+ | |
| ", xt = "+xt.value()+ | |
| ", p = "+windowPerimeter.value()+ | |
| ", a = "+windowArea.value()+ | |
| ", r = "+windowAspect.value() | |
| ); | |
| } | |
| writeValues(); | |
| for (var i = 100; i --> 0; ) { | |
| Window.x.set(Window.x.value() + (Math.random() * 50) - 25); | |
| writeValues(); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| x = 800, y = 600, xt = 60, p = 2800, a = 480000, r = 1.3333333333333333 | |
| x = 811.1414096900262, y = 600, xt = 71.1414096900262, p = 2822.2828193800524, a = 486684.8458140157, r = 1.351902349483377 | |
| x = 816.2675946834497, y = 600, xt = 76.26759468344972, p = 2832.5351893668994, a = 489760.55681006983, r = 1.360445991139083 | |
| x = 812.6638973946683, y = 600, xt = 72.66389739466831, p = 2825.3277947893366, a = 487598.338436801, r = 1.354439828991114 | |
| x = 813.5603960137814, y = 600, xt = 73.56039601378143, p = 2827.120792027563, a = 488136.23760826886, r = 1.3559339933563024 | |
| x = 807.5097443303093, y = 600, xt = 67.50974433030933, p = 2815.0194886606187, a = 484505.8465981856, r = 1.345849573883849 | |
| x = 792.3978895996697, y = 600, xt = 52.397889599669725, p = 2784.7957791993394, a = 475438.73375980183, r = 1.320663149332783 | |
| x = 797.7577502606437, y = 600, xt = 57.75775026064366, p = 2795.5155005212873, a = 478654.6501563862, r = 1.329596250434406 | |
| x = 809.9614890990779, y = 600, xt = 69.96148909907788, p = 2819.9229781981558, a = 485976.8934594467, r = 1.3499358151651297 | |
| x = 817.3078604741022, y = 600, xt = 77.3078604741022, p = 2834.6157209482044, a = 490384.7162844613, r = 1.362179767456837 | |
| x = 807.1250254521146, y = 600, xt = 67.12502545211464, p = 2814.2500509042293, a = 484275.0152712688, r = 1.3452083757535245 | |
| x = 792.3842651420273, y = 600, xt = 52.38426514202729, p = 2784.7685302840546, a = 475430.5590852164, r = 1.3206404419033788 | |
| x = 781.9253513356671, y = 600, xt = 41.925351335667074, p = 2763.850702671334, a = 469155.21080140024, r = 1.3032089188927785 | |
| x = 781.5086592687294, y = 600, xt = 41.50865926872939, p = 2763.017318537459, a = 468905.19556123763, r = 1.302514432114549 | |
| x = 786.087188066449, y = 600, xt = 46.087188066449016, p = 2772.174376132898, a = 471652.3128398694, r = 1.3101453134440817 | |
| x = 766.3957631331868, y = 600, xt = 26.395763133186847, p = 2732.7915262663737, a = 459837.4578799121, r = 1.2773262718886447 | |
| x = 762.3783522401936, y = 600, xt = 22.378352240193635, p = 2724.7567044803873, a = 457427.0113441162, r = 1.2706305870669894 | |
| x = 750.8052830235101, y = 600, xt = 10.805283023510128, p = 2701.6105660470203, a = 450483.1698141061, r = 1.251342138372517 | |
| x = 756.1171146691777, y = 600, xt = 16.11711466917768, p = 2712.2342293383554, a = 453670.2688015066, r = 1.2601951911152962 | |
| x = 752.6789672207087, y = 600, xt = 12.678967220708728, p = 2705.3579344414175, a = 451607.38033242524, r = 1.2544649453678478 | |
| x = 738.6347890365869, y = 600, xt = -1.3652109634131193, p = 2677.2695780731738, a = 443180.8734219521, r = 1.2310579817276448 | |
| x = 752.8310795780271, y = 600, xt = 12.83107957802713, p = 2705.6621591560543, a = 451698.6477468163, r = 1.2547184659633785 | |
| x = 734.9847904173657, y = 600, xt = -5.01520958263427, p = 2669.9695808347315, a = 440990.87425041944, r = 1.2249746506956096 | |
| x = 745.1338502112776, y = 600, xt = 5.133850211277604, p = 2690.267700422555, a = 447080.31012676656, r = 1.2418897503521293 | |
| x = 751.7314510070719, y = 600, xt = 11.731451007071882, p = 2703.4629020141438, a = 451038.87060424313, r = 1.252885751678453 | |
| x = 732.7893087523989, y = 600, xt = -7.210691247601062, p = 2665.578617504798, a = 439673.58525143936, r = 1.2213155145873316 | |
| x = 737.5216501415707, y = 600, xt = -2.478349858429283, p = 2675.0433002831414, a = 442512.99008494243, r = 1.2292027502359513 | |
| x = 727.6498130522668, y = 600, xt = -12.350186947733164, p = 2655.2996261045337, a = 436589.8878313601, r = 1.2127496884204447 | |
| x = 710.7992438017391, y = 600, xt = -29.200756198260933, p = 2621.598487603478, a = 426479.54628104344, r = 1.1846654063362319 | |
| x = 715.6434723641723, y = 600, xt = -24.35652763582766, p = 2631.2869447283447, a = 429386.0834185034, r = 1.192739120606954 | |
| x = 728.449239989277, y = 600, xt = -11.550760010723025, p = 2656.898479978554, a = 437069.5439935662, r = 1.214082066648795 | |
| x = 738.9790490851738, y = 600, xt = -1.0209509148262441, p = 2677.9580981703475, a = 443387.42945110425, r = 1.2316317484752897 | |
| x = 718.1529819616117, y = 600, xt = -21.84701803838834, p = 2636.3059639232233, a = 430891.789176967, r = 1.196921636602686 | |
| x = 697.1453469479457, y = 600, xt = 157.14534694794565, p = 2594.2906938958913, a = 418287.2081687674, r = 1.1619089115799095 | |
| x = 693.631188897416, y = 600, xt = 153.631188897416, p = 2587.262377794832, a = 416178.7133384496, r = 1.1560519814956933 | |
| x = 696.7661124886945, y = 600, xt = 156.7661124886945, p = 2593.532224977389, a = 418059.6674932167, r = 1.1612768541478242 | |
| x = 700.2520864130929, y = 600, xt = -39.74791358690709, p = 2600.504172826186, a = 420151.25184785575, r = 1.1670868106884882 | |
| x = 683.2349179196171, y = 600, xt = 143.23491791961715, p = 2566.4698358392343, a = 409940.9507517703, r = 1.1387248631993618 | |
| x = 692.990521597676, y = 600, xt = 152.99052159767598, p = 2585.981043195352, a = 415794.3129586056, r = 1.1549842026627932 | |
| x = 701.8245151033625, y = 600, xt = -38.1754848966375, p = 2603.649030206725, a = 421094.7090620175, r = 1.1697075251722708 | |
| x = 701.0193427326158, y = 600, xt = -38.98065726738423, p = 2602.0386854652315, a = 420611.60563956946, r = 1.1683655712210264 | |
| x = 709.204861021135, y = 600, xt = -30.795138978864998, p = 2618.40972204227, a = 425522.916612681, r = 1.1820081017018917 | |
| x = 713.0656526540406, y = 600, xt = -26.934347345959395, p = 2626.131305308081, a = 427839.39159242436, r = 1.188442754423401 | |
| x = 701.534994202666, y = 600, xt = -38.465005797334015, p = 2603.069988405332, a = 420920.9965215996, r = 1.1692249903377767 | |
| x = 679.33937641792, y = 600, xt = 139.33937641792, p = 2558.67875283584, a = 407603.625850752, r = 1.1322322940298666 | |
| x = 660.6042247381993, y = 600, xt = 120.60422473819926, p = 2521.2084494763985, a = 396362.53484291956, r = 1.101007041230332 | |
| x = 685.236297280062, y = 600, xt = 145.236297280062, p = 2570.472594560124, a = 411141.7783680372, r = 1.14206049546677 | |
| x = 667.9088157601655, y = 600, xt = 127.90881576016545, p = 2535.817631520331, a = 400745.2894560993, r = 1.1131813596002758 | |
| x = 684.87187421415, y = 600, xt = 144.87187421415, p = 2569.7437484283, a = 410923.12452849, r = 1.14145312369025 | |
| x = 694.6466680848971, y = 600, xt = 154.6466680848971, p = 2589.293336169794, a = 416788.00085093826, r = 1.157744446808162 | |
| x = 670.4792897682637, y = 600, xt = 130.4792897682637, p = 2540.9585795365274, a = 402287.5738609582, r = 1.1174654829471062 | |
| x = 662.6230686088093, y = 600, xt = 122.62306860880926, p = 2525.2461372176185, a = 397573.84116528556, r = 1.104371781014682 | |
| x = 680.6409137905575, y = 600, xt = 140.64091379055753, p = 2561.281827581115, a = 408384.5482743345, r = 1.1344015229842626 | |
| x = 667.2909192973748, y = 600, xt = 127.29091929737478, p = 2534.5818385947496, a = 400374.5515784249, r = 1.1121515321622912 | |
| x = 691.4108746103011, y = 600, xt = 151.4108746103011, p = 2582.821749220602, a = 414846.52476618066, r = 1.1523514576838352 | |
| x = 695.4242332256399, y = 600, xt = 155.4242332256399, p = 2590.84846645128, a = 417254.53993538395, r = 1.1590403887093998 | |
| x = 689.4368170876987, y = 600, xt = 149.43681708769873, p = 2578.8736341753975, a = 413662.09025261924, r = 1.1490613618128311 | |
| x = 666.9139718054794, y = 600, xt = 126.91397180547938, p = 2533.8279436109588, a = 400148.3830832876, r = 1.1115232863424656 | |
| x = 648.4661930473521, y = 600, xt = 108.46619304735214, p = 2496.9323860947043, a = 389079.7158284113, r = 1.0807769884122536 | |
| x = 658.9438696275465, y = 600, xt = 118.94386962754652, p = 2517.887739255093, a = 395366.3217765279, r = 1.0982397827125776 | |
| x = 644.1252282238565, y = 600, xt = 104.12522822385654, p = 2488.250456447713, a = 386475.1369343139, r = 1.073542047039761 | |
| x = 636.2589447991922, y = 600, xt = 96.25894479919225, p = 2472.5178895983845, a = 381755.36687951535, r = 1.0604315746653203 | |
| x = 628.0233757453971, y = 600, xt = 88.02337574539706, p = 2456.046751490794, a = 376814.02544723824, r = 1.0467056262423284 | |
| x = 613.8944733073004, y = 600, xt = 73.89447330730036, p = 2427.7889466146007, a = 368336.6839843802, r = 1.0231574555121672 | |
| x = 636.1213543452322, y = 600, xt = 96.12135434523225, p = 2472.2427086904645, a = 381672.81260713935, r = 1.0602022572420537 | |
| x = 611.7849749745801, y = 600, xt = 71.78497497458011, p = 2423.56994994916, a = 367070.98498474807, r = 1.0196416249576334 | |
| x = 603.5669230506755, y = 600, xt = 63.56692305067554, p = 2407.133846101351, a = 362140.1538304053, r = 1.005944871751126 | |
| x = 601.2897957232781, y = 600, xt = 61.289795723278075, p = 2402.579591446556, a = 360773.87743396685, r = 1.0021496595387969 | |
| x = 619.8490461101755, y = 600, xt = 79.84904611017555, p = 2439.698092220351, a = 371909.42766610533, r = 1.0330817435169592 | |
| x = 610.8947806060314, y = 600, xt = 70.89478060603142, p = 2421.789561212063, a = 366536.86836361885, r = 1.018157967676719 | |
| x = 596.0735492408276, y = 600, xt = 56.07354924082756, p = 2392.147098481655, a = 357644.12954449654, r = 0.9934559154013792 | |
| x = 591.593876236584, y = 600, xt = 51.59387623658404, p = 2383.187752473168, a = 354956.3257419504, r = 0.9859897937276401 | |
| x = 595.3466177452356, y = 600, xt = 55.34661774523556, p = 2390.693235490471, a = 357207.97064714134, r = 0.992244362908726 | |
| x = 577.0082934643142, y = 600, xt = 37.00829346431419, p = 2354.0165869286284, a = 346204.9760785885, r = 0.9616804891071903 | |
| x = 561.7939478135668, y = 600, xt = 21.793947813566774, p = 2323.5878956271335, a = 337076.36868814006, r = 0.9363232463559447 | |
| x = 570.4965196317062, y = 600, xt = 30.496519631706178, p = 2340.9930392634124, a = 342297.9117790237, r = 0.9508275327195103 | |
| x = 546.8247958109714, y = 600, xt = 6.824795810971409, p = 2293.649591621943, a = 328094.87748658285, r = 0.9113746596849523 | |
| x = 566.1859879735857, y = 600, xt = 26.185987973585725, p = 2332.3719759471714, a = 339711.59278415143, r = 0.9436433132893095 | |
| x = 572.4456686526537, y = 600, xt = 32.445668652653694, p = 2344.8913373053074, a = 343467.4011915922, r = 0.9540761144210895 | |
| x = 562.2193172457628, y = 600, xt = 22.219317245762795, p = 2324.4386344915256, a = 337331.5903474577, r = 0.9370321954096047 | |
| x = 563.0982828442939, y = 600, xt = 23.098282844293863, p = 2326.1965656885877, a = 337858.9697065763, r = 0.9384971380738231 | |
| x = 538.8428039499559, y = 600, xt = -1.1571960500441492, p = 2277.6856078999117, a = 323305.6823699735, r = 0.898071339916593 | |
| x = 532.8662855084985, y = 600, xt = -7.1337144915014505, p = 2265.732571016997, a = 319719.77130509913, r = 0.8881104758474976 | |
| x = 545.147310802713, y = 600, xt = 5.1473108027130365, p = 2290.294621605426, a = 327088.3864816278, r = 0.9085788513378551 | |
| x = 538.7105683563277, y = 600, xt = -1.2894316436722875, p = 2277.4211367126554, a = 323226.3410137966, r = 0.8978509472605462 | |
| x = 516.2962767295539, y = 600, xt = -23.703723270446062, p = 2232.592553459108, a = 309777.76603773236, r = 0.8604937945492566 | |
| x = 514.8046711226925, y = 600, xt = -25.195328877307475, p = 2229.609342245385, a = 308882.8026736155, r = 0.8580077852044875 | |
| x = 534.1744352015667, y = 600, xt = -5.825564798433334, p = 2268.3488704031333, a = 320504.66112094, r = 0.8902907253359444 | |
| x = 547.8497329051606, y = 600, xt = 7.849732905160636, p = 2295.6994658103213, a = 328709.8397430964, r = 0.9130828881752677 | |
| x = 543.9860105514526, y = 600, xt = 3.9860105514526367, p = 2287.9720211029053, a = 326391.6063308716, r = 0.9066433509190878 | |
| x = 556.5075480262749, y = 600, xt = 16.50754802627489, p = 2313.01509605255, a = 333904.52881576493, r = 0.9275125800437914 | |
| x = 547.4846170167439, y = 600, xt = 7.484617016743869, p = 2294.9692340334877, a = 328490.7702100463, r = 0.9124743616945731 | |
| x = 542.9808599757962, y = 600, xt = 2.980859975796193, p = 2285.9617199515924, a = 325788.5159854777, r = 0.9049680999596603 | |
| x = 558.1431346363388, y = 600, xt = 18.1431346363388, p = 2316.2862692726776, a = 334885.8807818033, r = 0.9302385577272313 | |
| x = 557.7623278019018, y = 600, xt = 17.762327801901847, p = 2315.5246556038037, a = 334657.3966811411, r = 0.9296038796698364 | |
| x = 565.9123415942304, y = 600, xt = 25.912341594230384, p = 2331.8246831884608, a = 339547.40495653823, r = 0.943187235990384 | |
| x = 587.1231290278956, y = 600, xt = 47.12312902789563, p = 2374.2462580557913, a = 352273.8774167374, r = 0.978538548379826 | |
| x = 596.1921920767054, y = 600, xt = 56.192192076705396, p = 2392.384384153411, a = 357715.31524602324, r = 0.9936536534611756 | |
| x = 599.0806587506086, y = 600, xt = 59.08065875060856, p = 2398.161317501217, a = 359448.39525036514, r = 0.9984677645843476 | |
| x = 599.1503421100788, y = 600, xt = 59.15034211007878, p = 2398.3006842201576, a = 359490.20526604727, r = 0.9985839035167979 | |
| x = 583.600834524259, y = 600, xt = 43.60083452425897, p = 2367.201669048518, a = 350160.5007145554, r = 0.9726680575404316 | |
| [Finished in 0.1s] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment