Asana Engineering Challenge - FRP

by ephekt

HTML

<script src="http://asana.com/challenge/engineering_challenge_1_lib.js"></script>
<script src="http://asana.com/challenge/engineering_challenge_1_sample_app.js"></script>
<h1>Asana Engineering Challenge - FRP</h1>

<!-- -->

<p>
    For this challenge, we will build a Functional Reactive
    Programming system ("FRP"), which allows us to declare
    reactive values ("re-values") that are dependent <em>only<em> on other
    re-values and/or on mutable values ("mu-values", imagine
    these being values stored in a database). Sort of like a
    generalized spreadsheet.

    This system should allow us to recompute re-values in an
    efficient manner when mu-values change.
</p>

<p>
    We start with the most naive implementation possible -- one
    in which re-values are always recomputed on every access.
    The code is structured in a way to measure a certain "cost"
    of computation based on the number of times a re-value is
    computed. The initial cost is 95 and your goal is to bring
    it down to 19 while preserving general correctness. 
</p>

<p>
    <b>Notes:</b>
    <ol>
        <li>
            This fiddle includes two Javascript files:
            <a target="_blank"
                href="http://asana.com/challenge/engineering_challenge_1_lib.js">
                engineering_challenge_1_lib.js</a> and
            <a target="_blank"
                href="http://asana.com/challenge/engineering_challenge_1_sample_app.js">
                engineering_challenge_1_sample_app.js</a>.
        </li>
        <li>
            JSFiddle <b>does not</b> automatically save your
	    file! If you refresh you <b>will</b> lose your work!
	    Use 'Save' and then 'Update' to save the current
	    version and get a new URL.
        </li>
	<li>
	    This challenge is in Javascript mainly because JSFiddle makes
	    it so easy. We tried to use as little Javascript syntax as
	    reasonably possible. If you're new to Javascript, you
            might want to check out 
	   ...

CSS

h1 {
    font-weight: 600;
}

p {
    margin-top: 10px;
}

ol { 
    margin-left: 1.12em;
    list-style-type: decimal;
}

JavaScript

/////////////////////////////////////////////////
// PLEASE READ THE INSTRUCTIONS TO YOUR RIGHT! //
/////////////////////////////////////////////////

FRP = {
    ///
    /// Mutable Values
    ///

    // Returns a newly created mutable value with a given 
    // initial value
    makeMuValue: function(initial_value) {
        return {
            value: initial_value
        };        
    },

    // Returns the value of a given mutable value
    readMuValue: function(mu_value) {
        return mu_value.value;
    },

    // Changes the value of a given mutable value
    changeMuValue: function(mu_value, new_value) {
        mu_value.value = new_value;
    },



    ///
    /// Reactive Values
    ///
    
    /**
     * Returns a newly created re-value
     * 
     * @param computeFunc {Function} A function that may compute
     *     other re-values and read other mu-values, returning
     *     the computed value of the newly created re-value
     */
    makeReValue: function(computeFunc) {
        return {
            computeFunc: computeFunc
        };
    },

    // Return the computed value of a given reactive value
    computeReValue: function(re_value) {
        return re_value.computeFunc();
    }
};

window.onload = function() {
    SampleApp.run();
};