Proposal for the future of variables #7226
Replies: 5 comments 4 replies
-
i like the idea and would rather it was like this from the start but i think its too late to do it now and its not really a must have |
Beta Was this translation helpful? Give feedback.
-
I think this would be a nice change, but its way too big of a breaking change to be implemented imo |
Beta Was this translation helpful? Give feedback.
-
as always sorry for bad wording Similar to eren I like the idea, as you said would need to be a skript-3 type of addition my main concern is the handling of collection type when defining a variable using code you provided
in the first part you did For myself and for others to not basically have to relearn the a core part of the design I would prefer a path similar to what was mentioned in the queues pr kind of, where we would need to first do At the same time if skript is now aiming to implement collections in a manner that breaks out of old design should skript now use An example of that is your usage of |
Beta Was this translation helpful? Give feedback.
-
In my opinion the proposed changes sound very good, but I wonder what will be of anyone using Skript on versions not supported by the update that would include them, perhaps 2.x and 3.x should keep a similar (if not equal) api and let 2.x be supported for a while to allow users to transition to the newer system or allow this new variable list/map system to be disabled from the config, I know, a hassle. |
Beta Was this translation helpful? Give feedback.
-
It's good. {map} should always reference a map. But how are you gonna do single values now? There should be another pattern for single values. Maybe like Kotlin definition or usage of [ and ] since they're only used for filtering. Or just |
Beta Was this translation helpful? Give feedback.
-
Existing Behavior
Currently, variables are either lists or not lists. Not lists have a single value and a name that ends in something that isn't
::*
. Lists have multiple values and end in::*
, where each value is accessible as a 'not-list' element. All not-lists are accessible directly via hash-map, making individual element access fast. Lists are represented as tree maps, allowing good traversal and organization, but slightly lacking on the list aspect.This means lists are, in effect, String-Object maps, ordered by their keys (0-9, a-z). It also causes ambiguity around not-lists and lists with the same name, excluding the
::*
.{a::*}
and{a}
represent two entirely different things, despite sharing a name. It also means that Skript is rather limited in variable data structures.Goals
This proposal aims to unshackle variables from the concepts of lists and not-lists, paving the way for more varied data types and more intuitive and scalable structures. It aims to provide a structure for lists, queues, maps, and many more such collections to be integrated into Skript variables in a uniform and minimally breaking manner. Ideally, code interfacing with the existing Variables object need not make changes.
It does not aim to change the format of variables for the user, introduce new syntaxes, or provide any methods for users to make structures.
Proposal
This idea revolves around the concept of an access operator. The most relevant one is the subscript operator in most langauges:
variable[0]
. The key here is turning::
from a hardcoded list separator into a more flexible access operator.array[0]
becomes{array::0}
in Skript. The Python slice operator, which returns all the elements in a list,list[:]
, would be{list::*}
. This, so far, is the exact same behavior Skript has already had, just a different way of approaching it.::
is now a flexible access operator that can act on things other than lists.It has several implications that we can take advantage of, though. Since it's no longer hardcoded for a list, it means that
{array::1}
is actually acting on{array}
. This implies that {array} itself is a list or some other collection. This is a departure from Skript's current behavior, and has a few knock-on effects.{list::array::*}
and{list::array}
are no longer completely separate objects, the latter is the collection, the former is the values within the collection.{list::*}
, in the above concept, no longer has to have indices without values. It now has indices and values that are the sublists themselves. This is a major source of confusion for newer users that this proposal would solve.The addition of an access operator also means that it can act on any object that allows it. This means any sort of data type can allow access, and you can have proper types like arrays, maps, queues, and what have you all acting the same:
We could take advantage of this to abandon the current concept of a list and instead support maps (string -> object) and dynamic arrays of objects, removing the weird behavior of current lists to sort by their indices and generally just act like a map instead of a list.
{list::*::value}
to get all matching values, or even{list::*::*}
to get all 2nd-level values.Challenges
Despite the many upsides, there are breaking changes and challenges here.
Not all data structures allow indiscriminate access. Some may only allow
::*
or specific indices like the first and last, like queues, or only allow numbers as indices, like arrays. The operator and types will have to have communication granular and flexible enough to know these restrictions and properly error when they're broken.Compatibility with existing internal logic. To avoid breaking every single syntax in Skript, we still need to put arrays of values in and get arrays of values out. This means that the
::*
operator is going to have to be implemented in every collection. It also leads onto:Confusion between when and where users can use {array} vs {array::*}. Since nearly all of Skript's syntax will be collection agnostic,
::*
will still be used whenever a plural type input is asked for:players/displays
. However, collection-specific syntax will be asking forarray
orarrays
, and they may get confused thatfirst element of {array::*}
works, buthead of {queue::*}
doesn't. Above I showedadd 1 to {array}
. Should this add 1 to the collection, or add 1 to each value within the collection? What aboutadd 1 to {array::*}
? (I think the former should add to the collection, the latter should add to each value, though this is a major breaking change). We will have to decide on the standards around these kinds of interactions.Quick variable access. Currently list elements can be accessed instantly via a single hashmap lookup. Adding in layers of access operations could feasibly slow this down significantly. On the flip side, it also means that lists can be pulled out as local variables, rather than accessing from the root every time. Performance will have to be kept in mind for this.
Future Possibilities
If such a system is implemented, it also opens the gate for typed collections, which only accept certain types, like
player array
. This would require some changes to SkriptPattern types, but theoretically a syntax could ask for a%type collection%
, like%item/slot collection%
, or%item/slot array/queue%
.It also allows addons to register their own types, and opens the door for SkriptReflect to allow custom data structures as a feature.
Feel free to comment your opinions, suggestions, concerns, or criticisms!
Beta Was this translation helpful? Give feedback.
All reactions