Hi there, it’s not a problem having a different opinion on it, that’s why we can discuss it here. I’ll try to write the things a bit simple for anyone else reading along.
As already shown above you can already associate methods to structs and enums in Verse via single extension syntax.
Both data types do not imply the strict requirement for the absence of any methods, that’s just just something past programming languages used to do. In several modern languages like Swift and Rust you can have ‘type members’ other than stored properties or associated values.
A class
is ‘reference type’ which for example in Swift as far as I know is heap allocated. An instance of a class
is an object and it follows ‘reference semantics’.
struct
’s and enum
s are value types, but their instances can have both either ‘value’ or ‘reference semantics’ depending on the concrete implementation. For the most part those are stack allocated in Swift.
If we would attach any functions to any of these data types, those functions will first become members of the associated data types and we will refer to those as methods.
Methods are just functions, but their first parameter is always Self
(in Verse context). The function itself is a reference type as it can be captured and referenced from somewhere else. A captured method should also keep the data instance alive, at least if such data instance is an object or otherwise we’re just talking about a copy of some pure data.
So in the end instances of classes, structs and enums (with associated values) are all holding data. Only the way that data is mutated, passed and referenced is different.
Having methods as type members on structs and enums enables some convenient syntactic usage, but furthermore it opens the door for protocol oriented programming. In Verse we’d rather call it ‘interface oriented programming’.
Right now an interface
in Verse is limited to a ‘class’ only, but that’s just a temporary limitation as long as other data types don’t support more type members.
In fact in most cases you actually want to create pure data structured that hold data, but you also want to perform some actions on that data to manipulate it. That does not imply that you have to use classes and objects for those tasks.
In Swift for example, the majority to the types are structs enums and protocols (aka interfaces). Classes and actors are only used where you truly need reference semantics and objects.
Verse could for example expose all stdlib types such as int
, logic
, array
, map
etc. as structs in the future. Those could have explicit type members instead of single type associated extensions.
Here’s an example what Verse already is doing due to the current limitation:
# Module import path: /Verse.org/Verse
Verse<public> := module:
(Input:[]t where t:type).Slice<public>(StartIndex:int, StopIndex:int)<computes><decides>: []t = external {}
(Input:[]t where t:type).Slice<public>(StartIndex:int)<computes><decides>: []t = external {}
(Input:[]t where t:type).Insert<public>(InsertionIndex:int, ElementsToInsert:[]t)<computes><decides>: []t = external {}
I can image we could collapse this to something more elegant and far easier to parse:
array(t: type) := struct {
Slice<public>(StartIndex: int, StopIndex: int)<computes><decides>: array(t)
Slice<public>(StartIndex: int)<computes><decides>: array(t)
Insert<public>(InsertionIndex: int, ElementsToInsert: array(t))<computes><decides>: array(t)
...
}
As previously mentioned, having the ability to use interface
s on data structured other than classes would enable a lot of flexibility and generic algorithms.
All in all from my personal experience there’s a ton of advantages following that direction in the evolution of Verse.