Extending the core

Nerdamer makes it easy to extend the core and add your own custom functions. To extend the core we'll walk through a simple example. Let's imagine we want to add a custom function called kinetic. We would have two options. One would be to define it using nerdamer.setFunction.

nerdamer.setFunction('kinetic', ['m', 'v'], '(1/2)*m*v^2');

If we then call the function with two new parameters say, a and b then we see that it works as expected

var x = nerdamer('kinetic(a, b)');

This approach work fine for one-liners but fails when it comes to more complex multi-step functions. For the sake of simplicity we'll stick to the one-line example but we'll rewrite it utilizing the core functions.

(function() {
    var core = nerdamer.getCore(), //grab the core
        _ = core.PARSER; //make a shortcut for the PARSER
    function kinetic(m, v) {
        var v_squared = _.pow(v.clone(), new core.Frac(2));
        var mv_squared = _.multiply(m.clone(), v_squared);
        return _.multiply(new Frac(1/2), mv_squared);

There are three important things to keep in mind. (1) Multiplication, division, addition, subtraction, and power, are done using the _.multiply, _.divide, _.add, _.subtract, and _.pow methods (granted that _ has been created as a shortcut for core.PARSER). (2) Those method require their inputs to be Symbols. (3) When using a sum or product of a symbol in subsequent calculations always call clone on the symbol for safety. Nerdamer reuses symbols as much as possible so you would not want to accidentally add or multiply the same symbol twice or more. To wrap it all up just register the the function.


Building this function in this way has one major drawback. When your registered function is called, and you use nerdamer('yourFunction(t)', {t: blah}, 'numer'};, the parser has already seen the request to convert to a numeric output before your function is called. You'll be required to call evaluate to get the desired output.

(function() {
    var core = nerdamer.getCore(),
        _ = core.PARSER,
        Symbol = core.Symbol;
    function kinetic(m, v) {
        var v_squared = _.pow(v.clone(), new Symbol(2));
        var mv_squared = _.multiply(m.clone(), v_squared);
        return _.multiply(new Symbol(1/2), mv_squared);
        name: 'kinetic',
        visible: true,
        numargs: 2,
        build: function() { return kinetic; }

The function can be called just as before. The main benefits of using the second option is the fact that you can have more complex calculations. That's not to say that it can't be done some other way.