Skip to content
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

Strict comparison? #2060

Closed
koosvanderkolk opened this issue Dec 14, 2020 · 9 comments
Closed

Strict comparison? #2060

koosvanderkolk opened this issue Dec 14, 2020 · 9 comments
Labels

Comments

@koosvanderkolk
Copy link

How to do type-safe comparison in this (excellent) library?

math.evaluate('1==true'); // true

I expect this one to return 'false', as 1 !== true.

@josdejong
Copy link
Owner

Thanks for your question Koos. Mathjs uses type-coercion when comparing values, resulting in expressions like 1==true and "2"==2 to return true. (Similar to JavaScripts ==, and unlike JavaScripts ===).

There are no functions implemented to do strict equality checks. If you need this, you can either create and import a function like strictEqual yourself, or override the built-in equal function with strict behavior.

@josdejong josdejong changed the title Type-safe comparison? Strict comparison? Dec 14, 2020
@koosvanderkolk
Copy link
Author

koosvanderkolk commented Dec 14, 2020

Thanks for the swift response Jos!

Is it perchange on the roadmap to allow for type-safe comparision in expressions? I mean that "1===true" is also allowed as an expression?

I indeed thought of writing a function myself, but... I do not think it can be done in such a way that

math.evaluate('1==true');

will use my custom 'equal' function right? So it should be done something like this:

math.evaluate('strictEqual(1, true)');

@josdejong
Copy link
Owner

Is it perchange on the roadmap to allow for type-safe comparision in expressions? I mean that "1===true" is also allowed as an expression?

This is not on the roadmap, but if there is enough need for it we can consider it and make a plan.

Side note: I think the official name for this is subject "strict equality comparison" (vs. type-coersion), it does not directly have to do with type safety.

I indeed thought of writing a function myself, but... I do not think it can be done in such a way that

math.evaluate('1==true');

will use my custom 'equal' function right? So it should be done something like this:

math.evaluate('strictEqual(1, true)');

When you create a mathjs instance, you can pass your own factory function for equal (and unequal) instead of using the build-in functions, something like:

import { create, all, factory } from 'mathjs'

function strictEqual(a, b) {
  return a === b
}

const math = create({
  ...all,
  
  // pass our own implementation for equal 
  createEqual: factory('equal', [], () => {
    return strictEqual
  })
})

function testEvaluate (expr) {
  console.log(expr, '=', math.evaluate(expr))
}

testEvaluate('"2"==2') // false

// deepEqual uses equal internally
testEvaluate('deepEqual("2", 2)') // false

@koosvanderkolk
Copy link
Author

Thanks!

Just asking for a friend: suppose one is bound to ES5 (so no 'import' etc) how would that work?

This does not work:

function strictEqual(a, b) {
  return a === b;
  };

var my_math = window.math.create({
  // pass our own implementation for equal
  createEqual: window.math.factory('equal', [], () => {
    return strictEqual;
  })
});

console.log(my_math.evaluate('"2"==2'));

@koosvanderkolk
Copy link
Author

koosvanderkolk commented Dec 15, 2020

In the meantime I did find a solution, namely using math.import, with the second argument being {override: true}

window.math.import({
          "smaller": function (a, b) {
            return (a < b);
          }}, {override:true});

@josdejong
Copy link
Owner

In the meantime I did find a solution, namely using math.import, with the second argument being {override: true}

window.math.import({
          "smaller": function (a, b) {
            return (a < b);
          }}, {override:true});

hm, yeah, that works for overriding smaller or equal, but it will not update the functions which have a dependency on equal, like deepEqual. It looks like there are some limitations trying to do this from the bundled version of mathjs.

@koosvanderkolk
Copy link
Author

Mmm... for the time being I think we are fine, but this might indeed pose a problem in the feature.

I am also glad that it seems to be a limitation of the bundled version (and not a limitation of my JS skills ;-), spend hours on it because I thought I was overseeing something obvious...

P.S. Great testimony on your personal home page! <><

@josdejong
Copy link
Owner

Thanks 😄

I'll give this some more thought. Ideally, when overriding an existing function on import, all functions that use the dependency should be re-created again. I thought this was the case but clearly it's not. Have to look into this.

@josdejong
Copy link
Owner

The problem of functions not being recreated is being addressed in #1975. Will close this issue now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants