-
-
Notifications
You must be signed in to change notification settings - Fork 22k
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
GDScript: logical and/or between non boolean value cause a parser error #44688
GDScript: logical and/or between non boolean value cause a parser error #44688
Comments
Confirmed on latest master 85186bc |
I'm not sure if this should be fixed. |
I don't think this is a bug, the logical operators should only accept booleans. |
Closing as it's not a bug. |
Reopening for discussion, since this worked on 3.x. Is this really wanted? I can't see a lot of use cases for this TBH, I feel it's more likely to happen as an user error than anything else. Note that cc @KoBeWi |
A few examples of such conditions in my code: if last_action and Input.is_action_just_released(last_action): #last_action is String if not menu.last_action or action != menu.last_action: if in_water and randi() % 100 == 0: #in_water is array if prev_crouch and not crouch and (check_raycast(Vector2(-15, -45), Vector2(-15, 0)) or check_raycast(Vector2(0, -45)) or check_raycast(Vector2(15, -45), Vector2(15, 0))): #check_raycast() is helper for intersect_ray(), which returns Dictionary if animator.assigned_animation and (target_animation.begins_with(animator.assigned_animation) or animator.assigned_animation.begins_with(target_animation)):
if not projectile_data: #Dictionary Another common thing to do is The main rationale behind keeping the old behavior is that these different objects do evaluate to boolean. If it's possible to do Another problem, this is more personal, is that long time ago I suggested that GDScript should treat non-booleans That said, is there any reason not to keep the old behavior? Does it impact performance or something? If there is a strong reason against supporting objects in boolean operations then I guess I could maybe live with that (in pain, but still ;_;). This mostly affects legacy projects. I'd have to add |
I'd argue that most of those would be more readable using explicit comparisons. E.g. using There's not really any strong reason for not supporting these though, so we might keep the status quo, even if it's not ideal. The only thing is that we have to add all possible combinations of types in |
I don't think it's any less readable. Compare:
You wouldn't normally use Anyways, keeping the status quo would be appreciated. |
The thing is that booleans are usually named using a convention that makes them obvious in this context, so something like In any case, feel free to open a PR adding the missing combinations in the logical operators. |
It goes beyond being easy to read. This issue is about not having a arbitrary language.
But it gets better !
Typing your data you want to be more sure of the data it contains to not have to be as explicit when trying to use that data. Now for the addressing the "less readable" argument.
... is less readable than :
I take that example because that is an extremely common occurrence for me, checking if something exists or is null before actually using it. How can it not be readable ? Why would you force the use of a more explicit when it is already more than obvious in that common case.
The previous version of GDScript was already an ersatz of python, but ok, it was only a bit rougher and mostly due to the way classes and built-in types were different. So yeah, that may not be a "bug" but that's clearly an oversight and the discrepancy in behavior makes it an issue and not just a matter of opinion about readability. |
I think a language should either be strict about For a high level scripting language like GDScript I'd personally prefer the latter. When Got curious and made a breakdown:
String and Vector only working with Types like Vector3, AABB, Quaternion, Rect2, etc. seem to be suffering from the same issues as Vector2. No idea what's going on with NodePath and StringName. They are probably not really relevant in this table but still weird how they behave. |
Maybe it will help if we do what I suggested way back in #20634, which is treating everything except The code would boil down to (ignorant pseudocode): if variant.type == bool:
return variant.operator bool()
else if variant.type == NIL
return false
else
return true btw seems like Signal has also some boolean logic (valid = true, invalid = false), and probably Callable and RID too. EDIT: |
I think it's helpful when things that cannot be null validate to false when their content is empty/0, like an empty string, a dictionary without items, or a vector of magnitude 0. when an user writes something like if, for an example, an array would always validate to true (as it can neither be false nor null), then there would no longer be an application for things like also, I am for |
Yeah I was against it initially, but then incorporated it in my code and it's indeed convenient. But it was a trap, as this issue appeared and it broke lots of my code xd And it doesn't seem like restoring the 3.x behavior is easy/possible. Maybe the solution is to completely forbid non-booleans (maybe except objects) in conditions. Personally I'm fine either way, as I started using
[Freed Object] is like that for technical reasons. Previously it was inconsistent between release and debug and it led to many bugs. IIRC making it evaluate to false implies some performance penalties due to validation. |
For my use case this is very unusable in the current state. I'm very used to languages taking anything passed to a conditional if not true:
pass Works, whereas: if not {}:
pass Or even: if not self.name:
pass Fails with a compile error. If we want to be so strict, we should offer a Due to GDScripts "Open to Everyone" approach, I would say this is a bad idea. Most JS & Python users are used to This is particularly visible for me since in |
Thanks to give that issue some attention. I really need some features from Godot 4 but the amount of refactoring that issue would imply made it very impractical. |
@Vaasref I'm sure this regression will be fixed soon, in some cases what I've done is simply added a helper to my func truthy(item) -> bool:
return item and item != null Please note this covers the following tests (port from Godot 3.x) func test():
assert(truthy("") == false)
assert(truthy("a") == true)
assert(truthy(0) == false)
assert(truthy(1) == true)
assert(truthy(0.0) == false)
assert(truthy(1.0) == true)
assert(truthy([]) == false)
assert(truthy([1]) == true)
assert(truthy({}) == false)
assert(truthy({"a": 1}) == true)
assert(truthy(null) == false)
assert(truthy([Object]) == true)
assert(truthy(Vector2.ONE) == true)
assert(truthy(Vector2.ZERO) == false) But does not cover the following Godot 4.x tests: assert(truthy(&"") == true)
assert(truthy(&"a") == true)
var a = Node.new()
a.free()
assert(truthy(a) == true) In that way it can be easily refactored later when fixed. IMO Godot 4.x is now worth it, and have ported my main projects over already. |
Godot version: 7d972b8
OS/device including version: windows10
Issue description:
if both operands of the and/or operator are compile time known non boolean values, the parser throws error (where it shouldn't)
Minimal reproduction project:
N/A
The text was updated successfully, but these errors were encountered: