-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Default value for eval
scope variables
#660
Comments
You have to change the code generation in See lib/expression/node/SymbolNode.js. return '(' +
'"' + this.name + '" in scope ? scope["' + this.name + '"] : ' +
(Unit.isValuelessUnit(this.name) ?
'new Unit(null, "' + this.name + '")' :
'undef("' + this.name + '")') +
')'; Change it to: return '(' +
'"' + this.name + '" in scope ? scope["' + this.name + '"] : ' +
(Unit.isValuelessUnit(this.name) ?
'new Unit(null, "' + this.name + '")' :
'0') + // <-- change here
')'; This should work (although I haven't tried it). I don't think there is a way without modifying mathjs itself. But I could be wrong. |
Thank you for the hint! |
You're right, changing the I'm marking this as feature request for the ability to register hooks that are called when a symbol wasn't found in the scope. |
sounds good to create the ability to use hooks to adjust the default behavior of the parser. I think we should look a bit more generic than just this specific case where you want a different behavior for |
@josdejong happy to try to get this one moving. Could you give me some guidance on the acceptance criteria for the feature? The use case I've got is that I'm merging several arrays from a query builder with, for example, a month column. But sometimes a symbol is not in the row because there was no data. For example:
Any expression looking for "count" throws an error. All I personally need is a flag to say "don't throw" but I'm happy to look at a handler style thing if that is more useful. Thanks in advance. |
Thanks for your offer @eddieajau 👍 . First step would be to create a clear plan on what kind of "hooks" we want to introduce. So one thing we want to solve is have a hook which triggers in case of an undefined symbol. So we could think about an very specific |
Hi @josdejong ok, shooting from the hip, are we aiming for something like this: import { create, all } from 'mathjs';
const mymath = create(all, {
onUndefinedSymbol: (name) => 0
})
mymath.evaluate('number(unknown)') // 0 And then /**
* Handles an undefined symbol.
*
* @param {string} name
* @throws an error 'Undefined symbol {name}' if no handler defined.
*/
function undef (name) {
if ((config || {}).onUndefinedSymbol) {
return config.onUndefinedSymbol(name);
}
throw new Error('Undefined symbol ' + name);
} Some sort of variation on that kind of theme? |
That is a very simple approach! I'l very careful with adding new global configuration, maybe it's an idea to pass this as an option to I would love to think this use case a bit more through though. It feels a bit like we're introducing a new configuration option for a very specific use case. Normally, when you try to evaluate something and there is a variable missing, there is something wrong and you would like to be informed. Silently "swallowing" an error is something I try to avoid generally in programming (though it would be a concious decision by the one who configures I do understand your use case. But in your case, wouldn't it make sense to write a little pre-processing to your data before evaluation? If I understand you correctly, you know all possible data fields, so you could simply add any missing Do we have more concrete use cases for this feature? Just thinking aloud here... |
Hi @josdejong and thanks for the reply.
Heh, so the problem is that I am building a JSON schema for dynamic queries, ETL, etc. I'm using mathjs FOR the pre-processing step itself ;) Eg: {
// ...
"map": {
"computed-value": "cost/count"
}
} Yes, if I was actually writing the code I could just do a normal map over the result set. Now if I had to add another step I've got to give instructions to the technician (on top of writing the code support for it) to "make sure all expected variables are populated with something otherwise the math library I'm using will throw an error", and that's not ideal. But since I'm dealing with counts and costs of inventory items, if there is no symbol, zero is an appropriate default. For now I am using CI to replace, after the npm install, the SymbolNode code where
The main use case I see are:
Yeah, no worries. Same. I don't mind if it's a parameter for |
Good to hear you have a workaround for the time being, that gives peace of mind :) Thanks for thinking along with trying to get the use cases clear 👍 . I think it's definitely an issue that needs to be addressed. We should make it possible to be able to customize the behavior for undefined symbols. It's also a bit of an edge case, so it may not be necessary to create a full-fledged API for it, as long as it's easy to hook up something custom in this regard.
I do like that idea! It doesn't work right now because the function I've worked out this idea in #2035. What do you think? |
We have a slightly different use case: we try to evaluate expressions like:
We have two cases:
In the second case, we tried to set "foo" to boolean false, but
evaluates as 'true' in JavaScript / Mathjs. Our next trick was to give "foo" the value 'undefined' (which is, in JavaScript at least, something different than "foo" being not defined;
) Our trick works in JavaScript, but not in Mathjs, as it throws an error. |
@koosvanderkolk thanks for sharing your usecase. So would the proposed solution in #2035 solve your issue? (the ping @eddieajau what are your thoughts about #2035? Would it solve your case? |
@josdejong I am not sure, as I would do this:
but I cannot foresee whether this would work (in all cases). |
What would be a solution for your case(s) Koos? |
So far mathjs only supports Just a thought: it may be possible to create an extra conversion function to automatically convert |
The just published |
Thanks! |
…ed function ..." instead when evaluating a non-existing function, and expose internal functions `FunctionNode.onUndefinedFunction(name)` and `SymbolNode.onUndefinedSymbol(name)`
I'd like to avoid
Undefined symbol
error being thrown when user tries to read from an undefined variable in an expression. Instead, I would like that variable to equal 0.That is, for example,
math.eval("x + y", { y: 42 })
should return 42.Is there a way to do it?
The text was updated successfully, but these errors were encountered: