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

Expression evaluate issue #500

Open
slaviczavik opened this issue Jan 17, 2024 · 11 comments
Open

Expression evaluate issue #500

slaviczavik opened this issue Jan 17, 2024 · 11 comments
Labels
bug Something isn't working good first issue Good for newcomers PR is more than welcome

Comments

@slaviczavik
Copy link

slaviczavik commented Jan 17, 2024

Describe the bug
Valid expression syntax does not select all objects and throws a warning.

To Reproduce
This simple example shows two layers:

first layer with red circles has applied this filter with deprecated syntax:

[
  "any",
  [">", "level", 0],
  ["!has", "level"]
]

and second and the last layer with black circles has applied this filter:

[
  "any",
  [">", ["get", "level"], 0],
  ["!", ["has", "level"]]
]

These filters should be evaluated equally and should select same objects, but as you can see, the second filter selects just few objects and it throws this warning: Expected value to be of type number, but found null instead.

Expected behavior
The expression syntax should select same objects as the deprecated syntax.

Screenshots
Screenshot 2024-01-17 at 10 39 57

Red circles are those objects with not defined level feature key and should be selected via the ["!", ["has", "level"]] expression.

Desktop

  • OS: macOS 14.2.1
  • Browser: Chrome
  • Version: 120.0.6099.216

Additional context
For some reason the ! is not applied and only objects with defined level feature key are selected.

Important: if the negation expression is placed before the > operator it works as expected. But I remember that this order hadn't worked few months ago, but I cannot remember what version it was.

@slaviczavik slaviczavik added the bug Something isn't working label Jan 17, 2024
@slaviczavik slaviczavik changed the title Expression evaluate issues Expression evaluate issue Jan 17, 2024
@HarelM
Copy link
Member

HarelM commented Jan 17, 2024

Thanks for taking the time to report this issue!
Any chance you can simplify the example and have it all "inline" in the same page (i.e. not link to an external style URL)?
It will make things much easier to reason with.
Maybe even create two layer with different color and alpha to show the overlap of the filter?

@slaviczavik
Copy link
Author

slaviczavik commented Jan 17, 2024

Thanks for taking the time to report this issue! Any chance you can simplify the example and have it all "inline" in the same page (i.e. not link to an external style URL)? It will make things much easier to reason with. Maybe even create two layer with different color and alpha to show the overlap of the filter?

I have updated the example – style is now included inside and it is possible to play with it. I have also tried to apply some style to see how it is overlapped, it should be clearer that black circles have red circles beneath.

@HarelM
Copy link
Member

HarelM commented Jan 17, 2024

If I change the order I think I get the same results, can you verify it?
image

I'm not saying it's not a bug, I'm just surprised about the results...

@HarelM
Copy link
Member

HarelM commented Jan 17, 2024

If you'd like to look into it, there are elaborated expression tests in this repo and you should be able to create some tests for this scenario and test it to see if the behavior, once a test is in place I think it might be simple to fix it.

@slaviczavik
Copy link
Author

If I change the order I think I get the same results, can you verify it?

image

I'm not saying it's not a bug, I'm just surprised about the results...

This order indeed works as expected, but it hadn't worked few months ago.

@neodescis
Copy link
Collaborator

My initial guess is that the "deprecated" expression parser is simply being less strict about type checking. I think in both examples it would be preferable to swap the order to check if the value exists first.

@slaviczavik
Copy link
Author

My initial guess is that the "deprecated" expression parser is simply being less strict about type checking. I think in both examples it would be preferable to swap the order to check if the value exists first.

Is there a specific reason why it would be better to swap order if any operator is used?

@slaviczavik
Copy link
Author

slaviczavik commented Jan 18, 2024

If you'd like to look into it, there are elaborated expression tests in this repo and you should be able to create some tests for this scenario and test it to see if the behavior, once a test is in place I think it might be simple to fix it.

I have just tested the expression with following test and it pass as expected (same result for flipped order):

{
  "expression": [
    "any",
    [">", ["get", "level"], 0],
    ["!", ["has", "level"]]
  ],
  "inputs": [
    [{}, {"properties": {"level": 5}}],
    [{}, {"properties": {"level": 0}}],
    [{}, {"properties": {"level": -5}}],
    [{}, {"properties": {"level": null}}]
  ],
  "expected": {
    "compiled": {
      "result": "success",
      "isFeatureConstant": false,
      "isZoomConstant": true,
      "type": "boolean"
    },
    "outputs": [
      true,
      false,
      false,
      {"error":"Expected value to be of type number, but found null instead."}
    ]
  }
}

but I'm not sure what should be the fourth output, for the > operator it make sense to yell the warning, but not for the ! operator.

@neodescis
Copy link
Collaborator

My initial guess is that the "deprecated" expression parser is simply being less strict about type checking. I think in both examples it would be preferable to swap the order to check if the value exists first.

Is there a specific reason why it would be better to swap order if any operator is used?

I haven't verified this, but I would expect "any" to use short-circuit evaluation. Basically, no need to keep running through all the checks if only one needs to pass.

@slaviczavik
Copy link
Author

slaviczavik commented Jan 18, 2024

My initial guess is that the "deprecated" expression parser is simply being less strict about type checking. I think in both examples it would be preferable to swap the order to check if the value exists first.

Is there a specific reason why it would be better to swap order if any operator is used?

I haven't verified this, but I would expect "any" to use short-circuit evaluation. Basically, no need to keep running through all the checks if only one needs to pass.

That's true, but first expression from the example with > is evaluated to false (because object doesn't contain the attribute) so it continue to the expression with ! and it should be evaluated to true.

But yes, it makes sense to put ! operator first, but validator should accept it even if the negation is not first.

@neodescis
Copy link
Collaborator

neodescis commented Jan 19, 2024

My initial guess is that the "deprecated" expression parser is simply being less strict about type checking. I think in both examples it would be preferable to swap the order to check if the value exists first.

Is there a specific reason why it would be better to swap order if any operator is used?

I haven't verified this, but I would expect "any" to use short-circuit evaluation. Basically, no need to keep running through all the checks if only one needs to pass.

That's true, but first expression from the example with > is evaluated to false (because object doesn't contain the attribute) so it continue to the expression with ! and it should be evaluated to true.

But yes, it makes sense to put ! operator first, but validator should accept it even if the negation is not first.

If the value is not there, then it is (apparently) comparing whether null > 0. I think it's perfectly acceptable for the validator to throw an error on this check. It is also documented as such: https://maplibre.org/maplibre-style-spec/expressions/#%3E

So, I think the bug is really that the deprecated syntax isn't throwing a validation error when it should be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers PR is more than welcome
Projects
None yet
Development

No branches or pull requests

3 participants