mathjs
mathjs copied to clipboard
Implement support for more than 2 arguments for logical functions `and`, `or`, and `xor`
As and
, or
, and xor
are associative and commutative, in function form there's no reason they could not take multiple arguments like their arithmetic counterparts add
and multiply
.
Interesting idea. Yeah, makes sense. I guess that could be very interesting for example for function simplify
if that would be capable to deal with a and b and c
. I'm not sure if people would actually enter something like and(a, b, c)
as a function call over the and
operator.
Do you have some concrete use cases where this can prove valuable?
Well, first there's the consistency with add
and multiply
(I was surprised when add
and or
did not work this way) and simply the principle to be as general as is feasible.
Second, if you have a large conjunction or disjunction, and(A,B,C,D)
is more compact and potentially clearer than A and B and C and D
and means you don't have to worry whether/where you need parentheses in and(A or B, C or D, E or F)
or or(A and B, C and D, E and F)
And finally, I agree: simplify and/or simplifyCore could/ought to handle things like A and false -> A
and B or not B -> true
and just as with + and *, detecting these patterns in the midst of intervening operands is most feasible if they can be flattened.
That's all I can think of at the moment, but I also don't see any harm in this generalization.
Makes sense: consistency, and large sets of values. I'm convinced 😄 .
I'll change the title of this issue to reflect the plans.
Having add
, multiply
, and
, or
take arbitrary arguments is very reminiscent of Scheme. It may be worth considering going all the way with it, see:
https://www.gnu.org/software/mit-scheme/documentation/stable/mit-scheme-ref.pdf
This would also include unary and nullary versions. Granted, these would be of limited use for now, unless somebody is machine generating expressions on the fly. Perhaps in the future there could be some kind of argument packing/unpacking in the style of JavaScript's rest parameters/spread syntax.
Anyhow, that's just some food for thought.
Thanks for your inputs Daniel 👍
Thanks to the excellent customizability of mathjs, it is not too difficult to replace the builtin functions with n-ary versions:
import { create, evaluateDependencies, factory, typed } from 'mathjs'
// See: mathjs/src/plain/number/logical.js
function andNumber(x, y) {
return !!(x && y)
}
function orNumber(x, y) {
return !!(x || y)
}
function xorNumber(x, y) {
return !!x !== !!y
}
const math = create({
evaluateDependencies,
createAdd: factory('add', ['addScalar'], ({ addScalar }) =>
typed('add', {
'': () => 0,
'...': (xs) => xs.reduce((x, y) => addScalar(x, y)),
}),
),
createMultiply: factory('multiply', ['multiplyScalar'], ({ multiplyScalar }) =>
typed('multiply', {
'': () => 1,
'...': (xs) => xs.reduce((x, y) => multiplyScalar(x, y)),
}),
),
createAnd: factory('and', [], () =>
typed('and', {
'': () => true,
'...': (xs) => xs.reduce(andNumber),
}),
),
createOr: factory('or', [], () =>
typed('or', {
'': () => false,
'...': (xs) => xs.reduce(orNumber),
}),
),
createXor: factory('xor', [], () =>
typed('xor', {
'': () => false,
'...': (xs) => xs.reduce(xorNumber),
}),
),
})
export default math
Just sharing in case anyone wants to use these instead of waiting for the library to be updated. Note that these would need to be extended to also work with arrays/matrices (see here).
Btw.: I copied andNumber
, orNumber
, xorNumber
from the mathjs source, but are they exported as part of the public API?
Thanks for sharing @filonik 👍
Btw.: I copied
andNumber
,orNumber
,xorNumber
from the mathjs source, but are they exported as part of the public API?
They are not exported themselves, but their factory functions createAnd
, createOr
, etc are exported via mathjs/number
.
Hello @josdejong . It's my first contribution to Open Source so I'm working to implement this and I have a few questions:
1.- It's correct to extend the functionality in the same file to the two arguments? and.js
, or.js
and xor.js
. I have it done here but I don't know if it's 100% right.
2.- I have troubles to make the tests with 3 parameters. Complex, units, bignumbers... maybe can be a lot of tests. It's all right if I upload some samples and take a look if it's all fine?
Thanks
Thanks @psirdev for picking this up!
- I think best is to extend the original functions with a new signature, i.e. the
and.js
. You can probably do the same as inadd.js
, add a signature like'any, any, ...any'
and loop over the rest parameters, applying the function itself. - I think the new unit tests can focus on checking that the functions accept more than two arguments, and with mixed data types, but you do not have to test all possible combinations of all data types.