Proposal - min, max and Arithmetic Chaining Touchup
#34
TotalTechGeek
started this conversation in
Ideas
Replies: 2 comments 5 replies
-
|
Self +1 Current Votes
|
Beta Was this translation helpful? Give feedback.
2 replies
-
|
My thoughts:
|
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Background
Okay folks!
JSON Logic has
minandmaxoperators. We should more explicitly define its expected behaviors.In the past, we defined: https://github.com/orgs/json-logic/discussions/21 (Arithmetic)
And recently we defined: https://github.com/orgs/json-logic/discussions/28 (Remove Sugaring + Add Chaining Concept)
Proposal
In previous discussions, we've decided we'd like to avoid coercion in most operators, so
minandmaxwill be defined to only work with numbers.I'd like to define min and max with the following:
{ op: n }is the same as{ op: [n] }Min will return the smallest number provided to it.
Max will return the largest number provided to it.
Infinityand-Infinityare currently being considered precision-related constructs, thus are relegated to the implementation to handle idiomatically if encountered.So this proposal defines:
I'd also like to touch up the definitions for the Arithmetic Operators (
+,-,/,*,%), and give them the following modifiers:{ op: n }is the same as{ op: [n] }Tests
max[ { "description": "Max of two numbers", "rule": { "max": [1, 2] }, "data": null, "result": 2 }, { "description": "Max of two numbers (2)", "rule": { "max": [2, 1] }, "data": null, "result": 2 }, { "description": "Max of three numbers", "rule": { "max": [1, 2, 3] }, "data": null, "result": 3 }, { "description": "Max of three numbers (2)", "rule": { "max": [3, 2, 1] }, "data": null, "result": 3 }, { "description": "Max of three numbers", "rule": { "max": [3, 3, 2] }, "data": null, "result": 3 }, { "description": "Max of a multitude of numbers", "rule": { "max": [55, 33, 11, 66, 127, 25, 3] }, "data": null, "result": 127 }, { "description": "Max with all negative numbers", "rule": { "max": [-1, -2, -3] }, "data": null, "result": -1 }, { "description": "Max with a mix of positive and negative numbers", "rule": { "max": [-1, 2, -3] }, "data": null, "result": 2 }, { "description": "Max of one number", "rule": { "max": [1] }, "data": null, "result": 1 }, { "description": "Max of one number, direct", "rule": { "max": 7 }, "data": null, "result": 7 }, { "description": "Max with an operator argument (showing it's not lazy)", "rule": { "max": [1, 2, 3, { "val": "a" }, 5, { "+": "3" }, 4] }, "data": { "a": 7 }, "result": 7 }, { "description": "Max can chain with other operators", "rule": { "max": { "val": "arr" } }, "data": { "arr": [1, 2, 3] }, "result": 3 }, { "description": "Max can chain with other operators (2)", "rule": { "max": { "val": "arr" } }, "data": { "arr": [6, 5, 4] }, "result": 6 }, { "description": "Max can chain with other operators (3)", "rule": { "max": { "merge": [[1, 2], 3, [4, 5]] } }, "data": null, "result": 5 }, { "description": "Max can chain with other operators (4)", "rule": { "max": { "map": [{ "val": "people" }, { "val": "age" }] } }, "data": { "people": [ { "name": "John", "age": 30 }, { "name": "Jane", "age": 25 }, { "name": "Bob", "age": 35 }, { "name": "Alice", "age": 28 } ] }, "result": 35 }, { "description": "Max of a string", "rule": { "max": ["1"] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of a string, direct", "rule": { "max": "2" }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of multiple strings", "rule": { "max": ["1", "2", "3"] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of a string and a number", "rule": { "max": ["1", 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of a string and a number (2)", "rule": { "max": [2, "1"] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of multiple numbers and a string", "rule": { "max": [1, 2, 3, 4, 5, "3", 4] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of a boolean", "rule": { "max": [true] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of a boolean, direct", "rule": { "max": true }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of multiple booleans", "rule": { "max": [true, false, true] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of boolean and a number", "rule": { "max": [true, 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of boolean and a number (2)", "rule": { "max": [2, true] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of a null", "rule": { "max": [null] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of a null, direct", "rule": { "max": null }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of multiple nulls", "rule": { "max": [null, null, null] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of a null and a number", "rule": { "max": [null, 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of a null and a number (2)", "rule": { "max": [2, null] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of an empty array", "rule": { "max": [[]] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of an array with items", "rule": { "max": [[1, 2, 3]] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max with multiple arrays", "rule": { "max": [[1, 2], [3, 4], []] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of an array and a number", "rule": { "max": [[1, 2], 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of an array and a number (2)", "rule": { "max": [2, [1, 2]] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of an object", "rule": { "max": [{}] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of an object, direct", "rule": { "max": {} }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of multiple objects", "rule": { "max": [{}, {}, {}] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of an object and a number", "rule": { "max": [{}, 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max of an object and a number (2)", "rule": { "max": [2, {}] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Max with zero arguments throws", "rule": { "max": [] }, "data": null, "error": { "type": "Invalid Arguments" } } ]min[ { "description": "Min of two numbers", "rule": { "min": [1, 2] }, "data": null, "result": 1 }, { "description": "Min of two numbers (2)", "rule": { "min": [2, 1] }, "data": null, "result": 1 }, { "description": "Min of three numbers", "rule": { "min": [1, 2, 3] }, "data": null, "result": 1 }, { "description": "Min of three numbers (2)", "rule": { "min": [3, 2, 1] }, "data": null, "result": 1 }, { "description": "Min of three numbers", "rule": { "min": [3, 3, 2] }, "data": null, "result": 2 }, { "description": "Min of a multitude of numbers", "rule": { "min": [55, 33, 11, 66, 127, 25, 3] }, "data": null, "result": 3 }, { "description": "Min with all negative numbers", "rule": { "min": [-1, -2, -3] }, "data": null, "result": -3 }, { "description": "Min with a mix of positive and negative numbers", "rule": { "min": [-1, 2, -3] }, "data": null, "result": -3 }, { "description": "Min of one number", "rule": { "min": [1] }, "data": null, "result": 1 }, { "description": "Min of one number, direct", "rule": { "min": 7 }, "data": null, "result": 7 }, { "description": "Min with an operator argument (showing it's not lazy)", "rule": { "min": [1, 2, 3, { "val": "a" }, 5, { "+": "3" }, 4] }, "data": { "a": 7 }, "result": 1 }, { "description": "Min can chain with other operators", "rule": { "min": { "val": "arr" } }, "data": { "arr": [1, 2, 3] }, "result": 1 }, { "description": "Min can chain with other operators (2)", "rule": { "min": { "val": "arr" } }, "data": { "arr": [6, 5, 4] }, "result": 4 }, { "description": "Min can chain with other operators (3)", "rule": { "min": { "merge": [[1, 2], 3, [4, 5]] } }, "data": null, "result": 1 }, { "description": "Min can chain with other operators (4)", "rule": { "min": { "map": [{ "val": "people" }, { "val": "age" }] } }, "data": { "people": [ { "name": "John", "age": 30 }, { "name": "Jane", "age": 25 }, { "name": "Bob", "age": 35 }, { "name": "Alice", "age": 28 } ] }, "result": 25 }, { "description": "Min of a string", "rule": { "min": ["1"] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of a string, direct", "rule": { "min": "2" }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of multiple strings", "rule": { "min": ["1", "2", "3"] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of a string and a number", "rule": { "min": ["1", 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of a string and a number (2)", "rule": { "min": [2, "1"] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of multiple numbers and a string", "rule": { "min": [1, 2, 3, 4, 5, "3", 4] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of a boolean", "rule": { "min": [true] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of a boolean, direct", "rule": { "min": true }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of multiple booleans", "rule": { "min": [true, false, true] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of boolean and a number", "rule": { "min": [true, 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of boolean and a number (2)", "rule": { "min": [2, true] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of a null", "rule": { "min": [null] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of a null, direct", "rule": { "min": null }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of multiple nulls", "rule": { "min": [null, null, null] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of a null and a number", "rule": { "min": [null, 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of a null and a number (2)", "rule": { "min": [2, null] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of an empty array", "rule": { "min": [[]] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of an array with items", "rule": { "min": [[1, 2, 3]] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min with multiple arrays", "rule": { "min": [[1, 2], [3, 4], []] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of an array and a number", "rule": { "min": [[1, 2], 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of an array and a number (2)", "rule": { "min": [2, [1, 2]] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of an object", "rule": { "min": [{}] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of an object, direct", "rule": { "min": {} }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of multiple objects", "rule": { "min": [{}, {}, {}] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of an object and a number", "rule": { "min": [{}, 2] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min of an object and a number (2)", "rule": { "min": [2, {}] }, "data": null, "error": { "type": "Invalid Arguments" } }, { "description": "Min with zero arguments throws", "rule": { "min": [] }, "data": null, "error": { "type": "Invalid Arguments" } } ]Arithmetic Tests
I will add these to their respective files, but I'm grouping them together for this:
[ "Collection of Chained Arithmetic Tests", "Plus", { "description": "Plus can be chained with other operators", "rule": { "+": { "val": "arr" } }, "data": { "arr": [1, 2, 3] }, "result": 6 }, { "description": "Plus can be chained with other operators (2)", "rule": { "+": { "merge": [[1, 2], 3, [4, 5]] } }, "data": null, "result": 15 }, { "description": "Plus can be chained with other operators (3)", "rule": { "+": { "map": [{ "val": "people" }, { "val": "age" }] } }, "data": { "people": [ { "name": "John", "age": 30 }, { "name": "Jane", "age": 25 }, { "name": "Bob", "age": 35 }, { "name": "Alice", "age": 28 } ] }, "result": 118 }, "Multiply", { "description": "Multiply can be chained with other operators", "rule": { "*": { "val": "arr" } }, "data": { "arr": [1, 2, 3] }, "result": 6 }, { "description": "Multiply can be chained with other operators (2)", "rule": { "*": { "merge": [[1, 2], 3, [4, 5]] } }, "data": null, "result": 120 }, { "description": "Multiply can be chained with other operators (3)", "rule": { "*": { "map": [{ "val": "arr" }, { "val": "x" }] } }, "data": { "arr": [ { "x": 30 }, { "x": 25 }, { "x": 35 }, { "x": 28 } ] }, "result": 735000 }, "Minus", { "description": "Minus can be chained with other operators", "rule": { "-": { "val": "arr" } }, "data": { "arr": [10, 7] }, "result": 3 }, { "description": "Minus can be chained with other operators (2)", "rule": { "-": { "merge": [[1], 5] } }, "data": null, "result": -4 }, { "description": "Minus can be chained with other operators (3)", "rule": { "-": { "map": [{ "val": "people" }, { "val": "age" }] } }, "data": { "people": [ { "name": "John", "age": 30 }, { "name": "Jane", "age": 25 }, { "name": "Bob", "age": 35 }, { "name": "Alice", "age": 28 } ] }, "result": -58 }, "Divide", { "description": "Divide can be chained with other operators", "rule": { "/": { "val": "arr" } }, "data": { "arr": [10, 5] }, "result": 2 }, { "description": "Divide can be chained with other operators (2)", "rule": { "/": { "merge": [[20], 5] } }, "data": null, "result": 4 }, { "description": "Divide can be chained with other operators (3)", "rule": { "/": { "map": [{ "val": "arr" }, { "val": "x" }] } }, "data": { "arr": [ { "x": 16 }, { "x": 2 }, { "x": 2 }, { "x": 2 } ] }, "result": 2 }, "Modulo", { "description": "Modulo can be chained with other operators", "rule": { "%": { "val": "arr" } }, "data": { "arr": [10, 3] }, "result": 1 }, { "description": "Modulo can be chained with other operators (2)", "rule": { "%": { "merge": [[20], 3] } }, "data": null, "result": 2 }, { "description": "Modulo can be chained with other operators (3)", "rule": { "%": { "map": [{ "val": "arr" }, { "val": "x" }] } }, "data": { "arr": [ { "x": 17 }, { "x": 4 } ] }, "result": 1 } ]Controvery Warnings
This test suite uses
mergeandmapeven though we haven't re-evaluatedmergeandmapquite yet. However, it is being used in the same way that it was used intests.json, so I'd argue these behaviors are already defined.Beta Was this translation helpful? Give feedback.
All reactions