2

I'm trying to mimic lazy evaluation in JavaScript by evaluating one specific function call in an expression, while leaving the other functions as-is. Is it possible to evaluate just one function in an expression without evaluating the other functions (so that all of the other function calls in the expression are left as-is)?

Here's the function I'm trying to implement:

function evaluateSpecificFunction(theExpression, functionsToEvaluate){
    //Evaluate one specific function in the expression, and return the new expression, with one specific function being evaluated
}

For example:

evaluateSpecificFunction("addTwoNumbers(1, 2) + getGreatestPrimeFactor(10)", addTwoNumbers);
//This should return "3 + getGreatestPrimeFactor(10)", since only one of the functions is being evaluated

evaluateSpecificFunction("addTwoNumbers(1, 2) + getGreatestPrimeFactor(10)", getGreatestPrimeFactor);
//This should return "addTwoNumbers(1, 2) + 5";
Anderson Green
  • 30,230
  • 67
  • 195
  • 328

1 Answers1

3

What you can do is play with replace and a regular expression :

function getGreatestPrimeFactor(n) {
  return n*2;
}

function transform(s, f) {
  return s.replace(new RegExp(f+"\\(([^\\)]*)\\)", "g"), function(m, args) {
    return window[f].apply(null, args.split(',').map(function(v){
       return parseFloat(v)
    }));
  });
}


var result = transform(
    "addTwoNumbers(1, 2) + getGreatestPrimeFactor(10)",
    "getGreatestPrimeFactor"
);

This example assume you deal only with numeric parameters.

Demonstration (open the console)

Of course this code mostly demonstrate the idea, you should, for example, store the functions in a dedicated object and not the global context (window).

EDIT : the new version can handle more than one replacement.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Why not just use `return eval(m);`? It might be appropriate here. And btw, your regex deals badly with nested expressions :-) – Bergi May 01 '13 at 18:20
  • @Bergi: Because `window[f]` may be faster than `eval`. – gen_Eric May 01 '13 at 18:21
  • @Bergi Dealing with nested expression would imply parsing the expression, not just playing with regex. And when I can avoid `eval`, I avoid it... – Denys Séguret May 01 '13 at 18:23
  • @RocketHazmat: Sure it is, but speed doesn't seem to be a concern here. And that `window[f]` thing limits your expressions a lot, in this case to literal number arguments… – Bergi May 01 '13 at 18:28
  • @dystroy: I didn't mean parsing them, but just avoiding them (with `[^()]*`) – Bergi May 01 '13 at 18:29
  • @Bergi Limiting the expressions here is probably a desired feature. I suppose the real application would exploit a dictionary of functions. But of course this could be simplified with eval. – Denys Séguret May 01 '13 at 18:29
  • Perhaps a better approach would be to implement a function that would return its own function call as a string. (For example, `getOwnFunctionCall("3", 3)` would return the string `"getOwnFunctionCall(\"3\", 3)`. Then each function in the expression, except for the function to be evaluated, would need to be temporarily redefined, so that it would return its own function call as a string. – Anderson Green May 01 '13 at 18:39