bylexus / fparse

A JavaScript Formula Parser
http://fparser.alexi.ch/
MIT License
89 stars 15 forks source link

string params #51

Open pilosof opened 1 year ago

pilosof commented 1 year ago

allow string params to user formula for example:

var fObj = new Formula('if(eq(prop(1),prop(2)), "yes", "no")');
fObj.if=function(a,b,c) {...}
fObj.eq=function(a,b) {...}
fObj.prop=function(a) {...}
bylexus commented 1 year ago

Strings cannot be evaluated numerically, so as a result, strings would not be possible. But I consider allowing them as variable values (not as string literals directly), so that you can pass them as parameters, like this:

const f1 = new Formula('myfunc([p1], [p2])');
f1.myfunc = (p1, p2) => {
    console.log(p1, p2);
    return p1.length > p2.length ? 10 : 20;
};
const res = f1.evaluate({ p1: 'hello', p2: 'woooorld' });
console.log(res);

Note that fparser is not a programming language, but a numerical expression evaluator in the first place.

issidorov commented 1 year ago

I'm started working on "String feature" in my fork.

LuigiPulcini commented 5 months ago

I second this feature request. I think that the fact strings cannot be evaluated numerically is a rather weak argument. The main point here is not about asking the parser to make sense of how to convert strings into numbers: that would be the user-defined functions' job. It would be enough to allow the use of string parameters without triggering syntax errors.

Please consider the following example:

const f1 = new Formula( 'convert( [price], "USD", "EUR" )' );

f1.convert = ( price, from, to ) => {
    return price * fetchExchangeRate( from, to ); // defined elsewhere
};

const res = f1.evaluate( { price: 1000 } );
console.log( res );

// res = 938.68

With the method you are proposing, if the formula above is entered by the end user in a text box, the developer would require a much longer implementation (and more tedious to maintain).

const f1 = new Formula( 'convert( [price], [USD], [EUR] )' );

f1.convert = ( price, from, to ) => {
    return price * fetchExchangeRate( from, to ); // defined elsewhere
};

const currencyCodes = {
    USD: 'USD',
    EUR: 'EUR',
    GBP: 'GBP',
    ... // dozens of other currency codes!
};

const res = f1.evaluate( { price: 1000, ...currencyCodes } );
console.log( res );

// res = 938.68
bylexus commented 5 months ago

OK, I see your point. I will evaluate your pull request (thanks for the work, by the way), and will follow up / merge if it seems to fit.

LuigiPulcini commented 5 months ago

I am glad I was able to contribute, regardless of your final decision about my pull request. 👍