JavaScript -- pass a boolean (or bitwise) operator as an argument?
Asked Answered
B

4

2

In C# there are various ways to do this C# Pass bitwise operator as parameter specifically the "Bitwise.Operator.OR" object, but can something like this be done in JavaScript? For example:

function check(num1, num2, op) {
    return num1 op num2; //just an example of what the output should be like
}

check(1,2, >); //obviously this is a syntax error, but is there some kind of other object or bitwise operator of some kind I can plug into the place of ">" and change the source function somehow?
Barbosa answered 29/4, 2019 at 2:52 Comment(18)
No there is no way. The only way is to pass a string containing operator and use eval() which is not good.Leyte
@MaheerAli new Function is better here.Spooky
@Spooky how would that work?Frink
@Spooky new Function also uses eval()Leyte
@MaheerAli doesn't the terms ">" and ">>" have constructors of some sort just like true and false?Frink
It'd be repetitive, but you could make an object whose keys are the operators, whose values are a function that you pass the num1 and num2 to, which returns the evaluated expressionCarpometacarpus
@MaheerAli no it doesn't, at least not the evil part: you are not going to the global scope and it is generally better optimisedSpooky
@Carpometacarpus what would the values for that object look like if there are more than 2 variablesFrink
It would depend on the operator. The only ternary operator I know of in JS is the conditional operator cond1 ? expr1 : expr2Carpometacarpus
@Carpometacarpus I mean for the oject with each key being a different operator -- to cover all operators. What would that look like? var operators = { ">": (num1, num2) => num1 > num2, "<": (num1, num2) => num1 < num2 /*...etc...*/ } but how would that work for more than 2 numbers?Frink
@Carpometacarpus don't the operators have some kind of constructor? What are they compiled to?Frink
I thought the only operator that uses more than 2 expressions is the conditional operator. Maybe '?:': (cond, expr1, expr2) => cond ? expr1 : expr2Carpometacarpus
@Carpometacarpus what if you had an expression 2 < 5 && 8 < 10 && 9 > 2... AKA, the "&&" operator, or "||", or "&", etc..Frink
@Carpometacarpus they did talk about bitwise operators, even though they used the > one in their example.Spooky
@Spooky whose "they"Frink
All the bitwise operators look to accept either two or only one argument. If you have multiple operators, then (using the object example) reference that object multiple times, check['&&'](check['<'](2, 5), check['<'](8, 10)) etc, something like thatCarpometacarpus
@Carpometacarpus so the only way to write 2 + 3 + 4 + 5 + 6 would be using nesting?Frink
It's not the only way, but it's one wayCarpometacarpus
L
6

You can create a object with keys as operators and values as functions. You will need Bracket Notation to access the functions.

You can use Rest Parameters and some() and every() for more than two parameters for &&,||.

For the bitwise operator or +,-,*,/ multiple values you can use reduce()

const check = {
  '>':(n1,n2) => n1 > n2,
  '<':(n1,n2) => n1 < n2,
  '&&':(...n) => n.every(Boolean),
  '||':(...n) => n.some(Boolean),
  '&':(...n) => n.slice(1).reduce((ac,a) => ac & a,n[0])
}

console.log(check['>'](4,6)) //false
console.log(check['<'](4,6)) /true
console.log(check['&&'](2 < 5, 8 < 10, 9 > 2)) //true

console.log(check['&'](5,6,7)  === (5 & 6 & 7))
Leyte answered 29/4, 2019 at 3:0 Comment(6)
what if there are more than just 2 numbersFrink
@bluejayke How there could be more than two numbers in greater than or less than operator?Leyte
@bluejayke You can't have more than two operands for > or <. If you want more this for || and && so see the edited answer.Leyte
OK I guess this is pretty much the answer, can you still explain tho why "Boolean" was passed to n.every? and also how would you do this for bitwise operators, or espeically the "&" operator, which continues to the next expression even if its false, for example?Frink
@bluejayke every method takes a callback. So I passed Boolean to it. It will check if all(in first case) or atleast(in second case) are true. n.every(Boolean) is same as n.every(x => x)Leyte
@bluejayke I don't know much about bitwise operators but. It think you can use reduce() for that see the updated answerLeyte
S
2

You can do the exact same thing suggested by the linked answers:

function check(num1, num2, op) {
  return op(num1, num2);
}

// Use it like this
check(3, 7, (x, y) => x > y);

You can also create an object that provides all of these operations:

const Operators = {
  LOGICAL: {
    AND: (x, y) => x && y,
    OR: (x, y) => x || y,
    GT: (x, y) => x > y,
    // ... etc. ...
  },
  BITWISE: {
    AND: (x, y) => x & y,
    OR: (x, y) => x | y,
    XOR: (x, y) => x ^ y,
    // ... etc. ...
  }
};

// Use it like this
check(3, 5, Operators.BITWISE.AND);
Spiderwort answered 29/4, 2019 at 3:2 Comment(5)
what if there is more than 2 variables per operator, like true && false && true && false etc.....Frink
Also this seems to be different than the C# function: Bitwise.Operation(1, 2, Bitwise.Operator.OR); // 3, seemingly "Bitwise.Operator.OR" is a constant, not a functionFrink
Fortunately, nesting helps us here: BITWISE.AND(3, BITWISE.AND(7, BITWISE.AND(12, 93))) is the same as 3 & 7 & 12 & 93 :-DSpiderwort
https://mcmap.net/q/1634637/-c-pass-bitwise-operator-as-parameter - In the example from here it's definitely a static method, not a constant.Spiderwort
Good point, then its just a matter of recursively tracking through itFrink
S
1

How about something like:

 function binaryOperation( obj1, obj2, operation ) {
     return operation( obj1, obj2 );
 }
 function greaterThan( obj1, obj2 ) {
    return obj1 > obj2 ;
 }
 function lessThan( obj1, obj2 ) {
    return obj1 < obj2 ;
 }
 alert( binaryOperation( 10, 20, greaterThan ) );
 alert( binaryOperation( 10, 20, lessThan ) );
Sienkiewicz answered 29/4, 2019 at 3:8 Comment(0)
S
0

It is not possible. But 1 way you can approach this is by doing the following:

function evaluate(v1, v2, op) {
    let res = "" + v1 + op + v2;
    return eval(res)
}
console.log(evaluate(1, 2, "+"));
# outputs 3

But be careful while passing args as they will be evaluated which is dangerous if some hacky code is passed to the function.

Scabby answered 29/4, 2019 at 3:5 Comment(1)
well if you're using eval can't u just eval the entire boolean?Frink

© 2022 - 2024 — McMap. All rights reserved.