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

Static typing for Array methods that return a Variant #10804

Open
4X3L82 opened this issue Sep 22, 2024 · 2 comments
Open

Static typing for Array methods that return a Variant #10804

4X3L82 opened this issue Sep 22, 2024 · 2 comments

Comments

@4X3L82
Copy link

4X3L82 commented Sep 22, 2024

Describe the project you are working on

Any project using Array + built-in methods.

Describe the problem or limitation you are having in your project

I want to have the full project statically typed for safety & performance.

var test :Array[int] = [1,2,10,4,5]
var max : int = test.max()

The second line will be gray and not by type-safe. It's not properly static typed because Array.max() returns a Variant.

This also isn't type-safe:
var max : int = int(test.max())
Or this:
var max : int = test.max() as int
Or this:
var max : int = test.max() if test.max() else 0
Or this:
reduce(func(max: int, i: int) -> int: return i if i > max else max, 0)

As you can see, all these "workarounds" still fail. By failing here I mean that they are not considered to be type-safe.

All the above also goes for min() (and probably for all of the built-in Array methods that return Variant).

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Easier to get static typing everywhere, which is safer + better performance.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

In a perfect world, everything would be handled under the hood, so this would Just WorkTM:

var test :Array[int] = [1,2,10,4,5]
var max : int = test.max()

And both lines would be considered as type-safe.

Alternatives:
Minimal effort option: var max : int = test.max() as int

Since the underlying problem is that max() could return null when the Array is empty, we could address that issue directly by add a default value parameter to max(): var max : int = test.max(default=1000)
This way null could never happen and should be type-safe.

If this enhancement will not be used often, can it be worked around with a few lines of script?

This is "correct" (as in, type-safe with a green line number): var max : int = test[test.find(test.max())]
But I hope we can all agree this is a bit of a ridiculous/over-engineered solution for something that should be simple.

A very simple benchmark points to about 25~50% speed gain with only using max() compared to the above "solution":

var test :Array[int] = [1,2,3,10,9]

var loop := 1000000
var start := Time.get_ticks_usec()
for i in loop:
	var max : int = test.max()
var end := Time.get_ticks_usec()

var start2 := Time.get_ticks_usec()
for i in loop:
	var max2 : int = test[test.find(test.max())]
var end2 := Time.get_ticks_usec()
printt("Only max: ", end-start)
printt("Correct: ", end2-start2)

Output:

Only max: 	81627
Correct: 	135097

A potential alternative solution could be #162.

Is there a reason why this should be core and not an add-on in the asset library?

The required work would probably change internal types and methods.

@AThousandShips
Copy link
Member

AThousandShips commented Sep 22, 2024

@dalexeev
Copy link
Member

See also:

To put it simply, the core currently does not provide information about which parameter and return types are generic and which are not (we cannot assume that Variant is always a generic placeholder). To look at it in more detail, Godot does not have a unified type system and the ability to represent a type as a value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants