Josh On Designhttp://joshondesign.com/Art, Design, and Usability for Software EngineersFri Jun 07 2013 19:02:23 GMT+0000 (UTC)\nFunctional Reactive Programming with Bacon.jshttp://joshondesign.com/2013/06/07/eventsfrp<p>Lately I've been experimenting with Functional Reactive Programming, or FRP. There are several good libraries to use FRP with Javascript. I chose <a href='https://github.com/raimohanska/bacon.js'>Bacon.js</a>. I'm finding FRP to be very useful but hard to understand.</p> <p>The way FRP is explained often leads to confusion. Most people know what the P is, and the F seems fairly understandable, but the R causes confusion. Examples usually talk about the difference between expressions and statements. Rather than c = a + b setting a value right now, it is an expression which defines that c is always a plus b. It defines a relationship. In <a href='http://jfx.wikia.com/wiki/Introduction_to_Binding_in_JavaFX'>another life</a> I would have called this a binding expression. I suppose expressions get to the heart of what FRP is but it doesn't really explain why it's useful. Let me try another way.</p> <p>FRP is this: <i>working with streams of values that change over time</i>.</p> <p>Perhaps an example would help. Imagine moving a mouse over your browser. It produces a stream of x and y values. Rather than using a callback for every mouse move, we can work with the mouse events as a single object over time: an event stream. Suppose we want to know when the mouse moves past a line on the screen at 100px. In regular code we could do this: <pre><code>$("body").on('mousemove', function(e) { if(e.pageX > 100) { console.log("we are over 100"); } };</code></pre> <p>With FRP we would create a stream based on mouse move, then filter it to only have X values over 100, like this:</p> <pre><code>$("body").toEventStream('mousemove') .filter(function(v) { return v > 100; }) .onValue(function(v) { console.log("we are over 100: " + v); }); </code></pre> <p>This is roughly the same amount of code so it doesn't seem like a big improvement. Trust me, it is. We have separated the action, printing a message, from the source of the stream and any filter operations. We can also add more operations to the stream if we want, and abstract the filters out further.</p> <p.Let's try a more complex example. I want to detect a double click. Double clicks are a bit tricky because you have to always wait for a second click to know if they are close enough to count as a double, however, you don't want to wait too long or the second click from a previous set could combine with the next set. Here's how to do it in FRP.</p> <pre><code>//create a stream of clicks var clicked = $('body').asEventStream('click'); //look for clicks for no longer than 300ms clicked.bufferWithTimeOrCount(300, 2) .filter(function(x) { return x.length == 2; }) .onValue(function(x) { console.log("double clicked: ", x); }); </code></pre> <p>The magic part here is <code>bufferWithTimeOrCount()</code>. It buffers the clicks, sending them to the next stage in the pipeline only if there are two samples or it has been 300ms since the first click. This means the filter function will get an array that is either one or two elements long. If it's one element then it clearly wasn't a double click, so we can filter to include just the two clicks. We already know they are no more than 300ms apart, so we are done.</p> <p>This code still looks a bit clunky, though. I don't like all of those nested functions. JavasSript has a way to deal with this: partial application and function references. In JavaScript a function is a real object so you can pass it around with variables. Let's make some reusable functions for printing to the log and determining if the length of an array is 2.</p> <pre><code>var isTwoValues = function(x) { return (x.length == 2); } var log = function(str) { return function(obj) { console.log(str,obj); } } </code></pre> <p><code>isTwoValues</code> is pretty simple: return true if the array is two elements. The <code>log</code> function is a bit trickier. It doesn't print to the console. Instead it returns a new function which prints to the console. However, it still remembers the first string passed in, so the new function can combine the original string with whatever new object is to be printed. In functional programming this is called a <i>partially applied function</i>. The returned function already has the first argument, <code>str</code>, applied. Later it, when it gets the second argument, it will fully apply the function. These sorts of functions are very handy when dealing with deferred programing like stream processing and event handling. Let's update the code from before using our new functions:</p> <pre><code>clicked.bufferWithTimeOrCount(300,2) .filter(isTwoValues) .onValue(log("double clicked"); </code></pre> <p>Ah. <b>Much</b> nicer looking.</p> <p>Using this same system we could implement a press and hold detector like this:</p> <pre><code>clicked.bufferWithTimeOrCount(600,2) .filter(isOneValue) .filter(function(x) return (x[0] == true); }) //x[0] = true if it's a mouse down. false if it's a mouse up .onValue(log("hold")); </code></pre> <p>Now lets try something really tricky to show off the power of this approach: a swipe detector. A swipe on a touch screen is when the cursor point is moving faster than a certain velocity. Velocity is tricky, however, because we need to calculate an average over multiple samples, and do it in both the x and y directions, and only when the mouse is down. First let's filter out mouse moves when the mouse isn't down, then calculate the difference between each event and the previous one.</p> <pre><code>mouse_move .filter(mouse_down.toProperty()) .diff(null, function(a,b) { if(a) { return { dx: Math.abs(b.pageX-a.pageX), dy: Math.abs(b.pageY-a.pageY), dt: b.timeStamp - a.timeStamp } } else { return { dx:0, dy:0, dt: 0 } } }) </code></pre> <p>Pretty straight forward. Now we want to calculate the average of the last five samples. The <code>slidingWindow</code> function makes this easy.</p> <pre><code> //the five most recent samples .slidingWindow(5,5) //calculate the sum of the samples and velocity .map(function(v) { var tx = 0; var ty = 0; var tt = 0; for(i in v) { tx += v[i].dx; ty += v[i].dy; tt += v[i].dt; } var txy = Math.sqrt(tx*tx + ty*ty); return txy/tt*1000; }) </code></pre> <p>Finally, let's only fire an event when the value is greater than 2000</p> <pre><code> .filter(greaterThan(2000)) .onValue(log("current velocity in pixels per second =, > 2000")); </code></pre> <p>See this code in action <a href="http://joshondesign.com/p/demos/frp/test1.html">here</a><p> <p>Now we have a swipe detector that is robust and extendable. Most importantly, all of these detectors can coexist without interfering with each other, and without a bunch of state variables lying around. To improve this we could make it indicate which direction the swipe took place, and if it started on the edge of the screen or the middle. FRP makes it easy to add these features without breaking existing code. </p> <p>To learn more about Bacon.js, check out <a href="https://github.com/raimohanska/bacon.js">the github project</a> and theses <a href='https://github.com/raimohanska/bacon.js/wiki/Documentation'>tutorials</a>.</p> http://joshondesign.com/2013/06/07/eventsfrp\nConcise Computing: a PNG Parser in 20 lineshttp://joshondesign.com/2013/03/18/ConciseComputing<p>By what standard should we measure if code is "beautiful"? I argue it should be not lines or speed, but rather conciseness and clarity. Can someone who is not familiar with the language still understand what the algorithm does? Can someone not familiar with the task still get a feel for how it works? This metric favors shorter code over longer, but not at the expense of readability. Beautiful code should be as close to expressing the underlying algorithm as possible. How close is the actual code to the most straight forward pseudo code?</p> <p>Some will argue that an elegant implementation is useless if it is too slow; but what if the elegant version is only 5% slower? Is that a good tradeoff? Almost certainly. What if it's 10x slower but only runs for 1% of the time? Then the trade off might be worth it. It depends. Certainly it's good to start with the clear and concise version and only move to a more complex implementation if the speed profiling warrants it. This is what I like to call <i>concise computing.</i></p> <h3>Complexity</h3> <p>Concise code is easier to read, easier to write, and much, much, much easier to maintain. Fewer lines of code means fewer places for bugs to hide. But let me take it from another angle:</p> <p>If you open up the typical programming library, especially older ones, you will find a bunch of complex code; often difficult to understand. This is the case even if the underlying task should be straight forward. Why should code be like this?</p> <p>I think there are two reasons: first, the programming language used to write the library wasn't expressive enough to write the implementation in a way that looks like the algorithm. If a task is naturally described using objects then a language with out direct object support will be at a disadvantage. If the task is really about matching patterns, then a language without matching will necessarily represent the algorithm in a less elegant way. And of course once written we try not to rewrite our code for fear of breaking things. Code is instant legacy.</p> <p>The other reason for complex libraries is speed. While I can describe sound synthesis using pure math... math is expensive to compute. A set of pre-calculated wavetables will be far faster than raw cosine functions. Changing an algorithm to be fast often makes the code hard to understand. But is this really a good excuse?</p> <p>Our software doesn't have to be fast. It has to be fast <i>enough</i>. But <i>enough</i> depends entirely on context and it changes over time as hardware evolves. <code>Math.sin()</code> used to be hugely expensive. When John Carmack wrote Doom he would massively change code to save a few divides. The code was amazing but came at a cost of obscuring the underlying algorithm and being hard to maintain. It doesn't have to be like that anymore.</p> <h3>Ometa</h3> <p>I did not invent concise computing (though I haven't heard the specific term before). It has been a computing goal for over fifty years. The sweet spot for any implementation has shifted over the years as hardware changes, but I think the time has come for most of our coding to move in the direction of conciseness. We have such an excess of CPU power, even in our mobile devices, that in almost every case the concise version wins over a fast but complex one. However, let me stop with the theoretical discussion and give you a concrete example of what I'm saying.</p> <p>I recently discovered a language called <a href='http://tinlizzie.org/ometa/ '>OMeta</a>. OMeta is actually a extension to let you write DSLs in a general purpose host language. My preferred version is <a href='http://tinlizzie.org/ometa-js/#Sample_Project'>OMeta/JS</a>, which extends JavaScript, but there are implementations for SmallTalk, C#, and others. OMeta really exemplifies my thoughts on concise computing.</p> <p><a href='http://www.tinlizzie.org/~awarth/'>Alex Warth</a>, the creator of OMeta, realized many computing tasks, especially writing parsers and compliers, are just different forms of matching. So why not bake it into the language in a way that is convenient but still lets you get at the power of the host language, and treat the parsers as objects that can be extended in various ways. Here's what a simple calculator looks like:</p> <pre><code>SimpleCalc <: Ometa { exp = number | sub | add, sub = exp:a "-" exp:b =< (a-b), add = exp:a "+" exp:b =< (a+b), } result = new SimpleCalc().matchAll("6+7); //result is set to 13 </code></pre> <p>Even if you don't know anything about OMeta you can follow what is going on. This says that <code>exp</code> is a number or a pattern called <code>sub</code> or <code>add</code>. Then it defines <code>sub</code> and <code>add</code> with recursive definitions back to <code>exp</code>. The <code>=></code> part says that the matched expression <i>goes to</i> a small Javascript expression, in this case the part that does the actual math.</p> <p>This code looks a lot like your typical <a href='http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form'>BNF grammar</a>. The magic here is that everything after the <code>=></code> part is regular Javascript. Instead of <code>(a+b)</code> it could be <code>console.log("doing an add")</code>, or call some other function to add in base 16 math, or generate C fucntions. Normally I would have to break out to a special library with weird syntax, or write in a completely different language. OMeta lets us implement algorithms that are naturally expressed with matching, but still remain in our general purpose host language, not some special matching only parser. This is concise computing.</p> <p>OMeta was created as part of Alex Warth's <a href='http://www.vpri.org/pdf/tr2008003_experimenting.pdf '>graduate thesis</a>. You should definitely check it out. For an academic paper it is highly readable. Alex continued his work at VPRI, a research group set up by Alan Kay. Yes, <i>that</i> <a href='http://en.wikipedia.org/wiki/Alan_Kay'>Alan Kay</a>. Though Alex's OMeta is an excellent improvement the original idea goes back to <a href='http://en.wikipedia.org/wiki/META_II'>Meta II</a>, a meta-compiler created back in 1962!!! The battle for concise computing is far from recent.</p> <h3>A PNG Parser in OMeta</h3> <p>Most public uses of OMeta show small examples like the calculator above or language compilers, which is probably it's most obvious application. (I myself am working on my own cross-language system with OMeta which I'll detail in a future blog post). Earlier this month I showed you <a href='http://joshondesign.com/2013/03/05/ometa1'>a markdown word processor with embedded arithmetic expressions</a> built in OMeta. However, today I want to show you a different kind of task: parsing a binary data PNG file in JavaScript.</p> <p>PNG is a fairly simple data format yet many parsers are surprisingly complex. <a href='http://en.wikipedia.org/wiki/Portable_Network_Graphics'>As documented in Wikipedia</a>, PNG consists of a header followed by a series of chunks. Each chunk has a length, type, and payload. Most of the chunks contain metadata about the image. Only one, IDAT, contains a bitmap. The example below does not decompress the actual image data (which requires a <a href='http://en.wikipedia.org/wiki/DEFLATE'>DEFLATE</a> decompressor) , but rather parses and validates all of the metadata chunks; the most likely use for an external parser.</p> <p>Parsing binary data in Javascript has always required hacks because JS has no native binary types. Fortunately, the W3C and Khronos recently remedied this situation with <a href='http://www.khronos.org/registry/typedarray/specs/latest/'>Typed Arrays</a>, a new data type built to support textures and vertices for WebGL. Using typed arrays we can fetch a PNG file from a server and convert it into a large buffer; like this:</p> <pre><code>function fetchBinary() { var req = new XMLHttpRequest(); req.open("GET","icon.png",true); req.responseType = "arraybuffer"; req.onload = function(e) { console.log("loaded"); var buf = req.response; if(buf) { var byteArray = new Uint8Array(buf); console.log("got " + byteArray.byteLength + " bytes"); var arr = []; for(var i=0; i<byteArray.byteLength; i++) { arr.push(byteArray[i]); } processOmeta(arr); } } req.send(null); }</code></pre> <p>The <code>Uint8Array</code> is an array of unsigned bytes (8 bit long 'words'). With this array in hand we can parse the entire structure in less than 20 lines of Ometa. Again, even if you don't know how Ometa works you can get a vague idea of what the program does by reading it.</p> <pre><code>ometa BinaryParser <: Parser { //entire PNG stream start = [header:h (chunk+):c number*:n] -> [h,c,n], //chunk definition chunk = int4:len str4:t apply(t,len):d byte4:crc -> [#chunk, [#type, t], [#length, len], [#data, d], [#crc, crc]], //chunk types IHDR :len = int4:w int4:h byte:dep byte:type byte:comp byte:filter byte:inter -> {type:"IHDR", data:{width:w, height:h, bitdepth:dep, colortype:type, compression:comp, filter:filter, interlace:inter}}, gAMA :len = int4:g -> {type:"gAMA",value:g}, pHYs :len = int4:x int4:y byte:u -> {type:"pHYs", x:x, y:y, units:u}, tEXt :len = repeat('byte',len):d -> {type:"tEXt", data:toAscii(d)}, tIME :len = int2:y byte:mo byte:day byte:hr byte:min byte:sec -> {type:"tIME", year:y, month:mo, day:day, hour:hr, minute:min, second:sec}, IDAT :len = repeat('byte',len):d -> {type:"IDAT", data:"omitted"}, IEND :len = repeat('byte',len):d -> {type:"IEND"}, //useful definitions byte = number, header = 137 80 78 71 13 10 26 10 -> "PNG HEADER", //mandatory header int2 = byte:a byte:b -> bytesToInt2(a,b), //2 bytes to a 16bit integer int4 = byte:a byte:b byte:c byte:d -> bytesToInt(a,b,c,d), //4 bytes to 32bit integer str4 = byte:a byte:b byte:c byte:d -> toAscii([a,b,c,d]), //4 byte string byte4 = repeat('byte',4):d -> d, END } </code></pre> <p>This parser returns a JSON structure that we can loop through to find any chunk we care about.</p> <pre><code>chunk: {"type":"IHDR","data":{"width":33,"height":36,"bitdepth":8,"colortype":2,"compression":0,"filter":0,"interlace":0}} chunk: {"type":"gAMA","value":55555} chunk: {"type":"pHYs","x":2835,"y":2835,"units":1} chunk: {"type":"tEXt","data":"Software0x0 QuickTime 6.5.2 (Mac OS X)0x0 "} chunk: {"type":"tIME","year":2005,"month":4,"day":5,"hour":17,"minute":6,"second":20} chunk: {"type":"IDAT","data":"omitted"} chunk: {"type":"IEND"}</code></pre> <p>In a sense the code above is not really an algorithm, but rather a definition of the PNG format. A <i>runnable</i> specification. For an even more impressive example, the OMeta guys created a TCP/IP parser which <a href='http://www.moserware.com/2008/04/towards-moores-law-software-part-3-of-3.html '>uses the actual ASCII art header definitions</a> from the RFC as the parser code itself.</p> <h3>More</h3> <p>What I've shown you today is merely a hint of what concise computing could be. Imagine an entire operating system from boot to GUI, complete with apps, written in less than 20k lines of code? It sounds crazy yet that is <a exactly <a href='http://www.vpri.org/pdf/tr2011004_steps11.pdf'>what VPRI has done</a>.</p> <p>By writing the most clear and concise code possible we can make our software more maintainable and longer lived. Next time I'll show you the same principle applied to audio synthesis. Feel free to ask questions and continue the discussion.</p> http://joshondesign.com/2013/03/18/ConciseComputingMon Mar 18 2013 22:07:33 GMT+0000 (UTC)\nA Magically Delicious Wordprocessor with OMetahttp://joshondesign.com/2013/03/05/ometa1<p>I've always wanted a magic wordprocessor. Something that helps me organize my thoughts and build ideas organically, rather than spend all of my time worrying about formatting. Something for the internet / cloud age. Given that Microsoft Word hasn't fundamentally changed in over a decade (or possibly two), we aren't likely to get such software from them. Instead, I decided to play around with some ideas using my new favorite programming tool: <a href='http://tinlizzie.org/ometa/'>OMeta</a>.</p> <h3>OMeta</h3> <p>OMeta's story starts with compilers. Compilers are built of many phases: lexing, parsing, applying optimizations, then generating machine code. OMeta's creator, Alessandro Warth, realized that these are all essentially the same thing, pattern matching. The only difference is whether you are matching a stream of characters, tokens, or parts of a tree. Alex created a single language that lets you match over objects (ie: anything) to implement all parts of the compiler using a single tool.</p> <p>OMeta is that single tool: a domain specific programming language for creating pattern matchers. More properly, it is a language extension that can be laid on top of an existing host language. I am using OmetaJS, an extension to JavaScript. The wonderful thing about OMeta is that it's easier to use and extend than dedicated parser generators like Antlr or Yacc because you always have the host language available to do whatever computation you need.</p> <h3>Editor Demo</h3> <p>As my first experiment with OMeta, and new wordprocessors, I created a simple Markdown editor. You type raw text into the left side of the screen and see your properly styled text on the right side. But this editor has a trick up it's sleeve. You can type simple math expressions inside curly braces the editor will evaluate it for you.</p> <p>Play with <a href="http://joshondesign.com/p/demos/ometa/markdown/webeditor.html">the editor here</a></p> <p>Here's what the OMeta code looks like:</p> <pre><code> ometa Foo { //white space toEOL = (~seq('\n') char)*:t '\n' -> t.join(""), //headers h1 = "#" ' ' toEOL:t -> tag("h1",t), h2 = "##" ' ' toEOL:t -> tag("h2",t), h3 = "###" ' ' toEOL:t -> tag("h3",t), //paragraph paraend = seq('\n\n'), para = (expr|strong|em| (~paraend char))+:t -> tag("p",t.join("")), text = (~seq('\n\n') char)*:t -> t.join(""), strong = "**" (~seq('**') char)*:t "**" -> tag("strong",t.join("")), em = "*" (~seq('*') char)*:t "*" -> tag("em",t.join("")), expr = "{" exp:t "}" -> tag("b",t), //code block codeblock = fromTo("```\n", "```\n"):t -> tag("pre",tag("code",esc(t))), //inline expressions num = <digit digit*>:n -> parseInt(n), term = num, expadd = term:a "+" term:b -> (a+b), expmul = term:a "*" term:b -> (a*b), expsub = term:a "-" term:b -> (a-b), expdiv = term:a "/" term:b -> (a/b), exp = (expmul|expdiv|expadd|expsub):e -> (" <b class='expr'>"+e+"</b>") , //pull it all together line = space* (h3|h2|h1|codeblock|para):t space* -> t, top = line*, END }; </code></pre> <p>This editor only understands simple two term arithmetic but it could easily be expanded with variables and more complex functions.</p>http://joshondesign.com/2013/03/05/ometa1Tue Mar 05 2013 22:39:47 GMT+0000 (UTC)\nImproved Easing Functionshttp://joshondesign.com/2013/03/01/improvedEasingEquations<p>Animation is just moving something over time. The rate at which the something moves is defined by a function called an easing equation or interpolation function. It is these equations which make something move slowly at the start and speed up, or slow down near the end. These equations give animation a more life like feel. The most common set of easing equations come from Robert Penner's <a href='http://www.robertpenner.com/easing/'>book and webpage</a>. </p> <p>Penner created a very complete set of equations, including some fun ones like 'spring' and 'bounce'. Unfortunately their formulation isn't the best. Here is one of them <a href='https://github.com/danro/jquery-easing/blob/master/jquery.easing.js'>in JavaScript</a></p> <pre><code> easeInCubic:function(x,t,b,c,d){ returnc*(t/=d)*t*t+b; }, easeOutCubic:function(x,t,b,c,d){ returnc*((t=t/d-1)*t*t+1)+b; }, </code></pre> <p>They really obscure the meaning of the equations, making them hard to understand. I think they were designed this way for efficiency reasons since they were first implemented in Flash ActionScript, where speed would be important on the in-efficient. It makes them much harder to understand and extend, however. Fortunately, we can refactor it to be a lot clearer.</p> <p>Let's start with the <code>easeInCubic</code> equation. Ignore the <code>x</code> parameter (I'm not sure why it's there since it's not used). <code>t</code> is the current time, starting at zero. <code>d</code> is the duration in time. <code>b</code> and <code>c</code> are the starting and ending values. </p> <pre><code>easeInCubic:function(x,t,b,c,d){ returnc*(t/=d)*t*t+b; }, </code></pre> <p>If we divide t by d before calling this function, then t will always be in the range of 0 to 1, and d can be left out of the function. If we define the returned version of t to also be from 0 to 1, then the actual interpolation of b to c can also be done outside of the function. Here is some code which will call the easing equation then interpolate the results:</p> <pre><code> var t = t/d; t = easeInCubic(t); var val = b + t*(c-b); </code></pre> <p>We have moved all of the common code outside the actual easing equation. What that leaves is a value t from 0 to 1 which we must transform into a different t. Here's the new easeInCubic function.</p> <pre><code> function easeInCubic(t) { return Math.pow(t,3); } </code></pre> <p>That is the essence of the equation. Simply raising t to the power of three. The other formulation might be slightly faster, but it's very confusing, and the speed difference today is largely irrelevant since modern VMs can easily optimize the cleaner form.</p> <p>Now let's try to transform the second one. An ease out is the same as an ease in except in reverse. If t when from 0 to 1 then the out version will go from 1 - 0. To get this we subtract t from 1 as shown:</p> <pre><code> function cubicOut(t) { return 1-Math.pow(1-t,3); } </code></pre> <p>However, this looks awfully close to the easeIn version. Rather than writing a new equation we can factor out the differences. Subtract t from 1 before passing it in, then subtract the result from one after getting the return value. The out form just invokes the in form:</p> <pre><code>function easeOutCubic(t) { return 1 - easeInCubic(1-t); }</code></pre> <p>Now we can write other equations in a similarly compact form. easeInQuad and easeOutQuad go from:</p> <pre><code>easeInQuad:function(x,t,b,c,d){ returnc*(t/=d)*t+b; }, easeOutQuad:function(x,t,b,c,d){ return-c*(t/=d)*(t-2)+b; },</code></pre> <p>to</p> <pre><code>function easeInQuad(t) { return t*t; } function easeOutQuad(t) { return 1-easeInQuad(1-t); }</code></pre> <p>Now let's consider the easeInOutCubic. This one smooths both ends of the equation. In reality it's just scaling the easeIn to the first half of the t, from 0 to 0.5. Then it applies an easeOut to the second half, from 0.5 to 1. Rather than this complex form:</p> <pre><code>easeInOutQuad:function(x,t,b,c,d){ if((t/=d/2)<1)returnc/2*t*t+b; return-c/2*((--t)*(t-2)-1)+b; },</code></pre> <p>We can compose our previous functions to define it like so:</p> <pre><code> function cubicInOut(t) { if(t < 0.5) return cubicIn(t*2.0)/2.0; return 1-cubicIn((1-t)*2)/2; } </code></pre> <p>Much cleaner. </p> <p>Here is the original form of elastic out, which gives you a cartoon like bouncing effect:</p> <pre><code>easeOutElastic:function(x,t,b,c,d){ vars=1.70158;varp=0;vara=c; if(t==0)returnb;if((t/=d)==1)returnb+c;if(!p)p=d*.3; if(a<Math.abs(c)){a=c;vars=p/4;} elsevars=p/(2*Math.PI)*Math.asin(c/a); returna*Math.pow(2,-10*t)*Math.sin((t*d-s)*(2*Math.PI)/p)+c+b; }, </code></pre> <p>and here is the reduced form:</p> <pre><code> function easeOutElastic(t) { var p = 0.3; return Math.pow(2,-10*t) * Math.sin((t-p/4)*(2*Math.PI)/p) + 1; } </code></pre> <p>Moral of the story: "Math is your friend" and "always refactor".</p> <p>These new equations will be included in a future release of Amino, my cross platform graphics library.</p> http://joshondesign.com/2013/03/01/improvedEasingEquationsFri Mar 01 2013 06:17:03 GMT+0000 (UTC)\nMake Libraries Morehttp://joshondesign.com/2013/02/13/makelibsmore<p>Software Libraries are good. They allow abstraction and encapsulation; which encourages reuse. They also allow the library to be written by one person and used by another. This is reuse at the programmer level, not just the system level. A library can be written by a person who has domain expertise but used by someone else who has less or no expertise in that domain. For example: an XML parser. The implementer knows the XML spec inside and out, but the user of the lib needs only a basic understanding of XML in order to use the lib.</p> <p>Now that we've established that libraries are good (regardless of whether are are implemented as classes, packages, DLLs, etc.), how can we extend them? Traditionally libraries are very limited in how they can influence the experience of the programmer. The coder simply has new functions to call. A more advanced case is component driven GUI builders where the lib exposes more information so that the IDE can make the library easier to use. Annotating of types in a map component could enhance the GUI builder draw markers, use a dummy tile set, and set positions. This is all standard stuff. Could libraries do more? How could the library author further influence the experience of the library user?</p> <p> Let's do a quick brainstorm:</p> <ul> <li>Extend the language with new operators and syntax specific to the library. A physics library could import operator overloads to enable more math like syntax when dealing with physical units and vectors.</li> <li>Tests that verify aspects of the code that calls the library. This could automate the advice that would be in the documentation, such as "don't pass null to certain functions" or "this function returns an object that you must dispose of".</li> <li>If the lib is used from within an IDE, the lib can insert new documentation into the searchable index of docs.</li> <li>The lib could come with example code and reusable annotated code snippets that would only be applied to projects using the lib.</li> <li>The lib could insert a new package manager into the compiler toolchain. No more messing with Maven POMs.</li> <li>The lib can provide the compiler with new code optimizers for the particular tasks. An imaging analysis library could instruct the compiler on how to better use SIMD instructions when available.</li> </ul> <p>Obviously modifying the environment of the programmer is a dangerous activity so we would need very strict scoping on the changes. A library which extends the language applies only in the parts of the code that actually import the library. Changes are scoped to the code which asks for them.</p> <p>Fundamentally a library is a thing created by one programmer for use by another programmer (or the same programmer at a future date). We should extend the concept of a library to apply to the entire programming experience, not just adding objects and methods. This would allow all environment extensions to be managed in a standard way that is more understandable, flexible, and scoped. I would never need to set up a makefile again. I could simply import in my main.foo code the package manager, repos, code chunks and syntax that I want to use for this project. The library extensions to the compiler handle everything else automatically.</p> <p>Clearly there are challenges with such an approach. We would have to define all of the various ways a library could modify your environment. How would compiler hooks actually work? Annotation processors? A function to modify the AST a different stages of compilation? Would it imply a particular back end like LLVM? I don't have the answers. There clearly are challenges to be solved, but I think the approach is a step forward from today where we have many different components of our programming environment that are dependent on each other but don't actually know about each other. Having a way to organize this mess, even if imperfect, would certainly help us make better software.</p> http://joshondesign.com/2013/02/13/makelibsmoreWed Feb 13 2013 18:00:02 GMT+0000 (UTC)