Parametric class issues

I started using Verse and really struggle with the lack of functionality regarding parametric classes. We really need to be able to cast using parametric types and also the ability to declare variable member functions.

Here is an example case:

linked_list_node(t : type) := class<unique>:
    Data : t
    var Next : ?linked_list_node(t) = false

linked_list(t : type) := class:
    var Head : ?linked_list_node(t) = false
    var Tail : ?linked_list_node(t) = false
    AddValue(Value : t) : void =
        Print("Added")
    DoSomethingWithList() : void =
        if(var CurrentNode: linked_node(t) = Head?):
            loop:
                # Do something with CurrentNode.Data
                if (set CurrentNode=CurrentNode.Next?):
                else:
                    break

some_device := class(creative_device):
    IntList: linked_list(int) = linked_list(int){}
    FloatList: linked_list(float) = linked_list(float){}
    AgentList: linked_list(agent) = linked_list(agent){}

This code above would work in an ideal world. It doesn’t tho.

Instead, we have to do this:

linked_list_node_base := class<unique>:
    var Next : ?linked_list_node_base = false

linked_list_node(t : type) :=class(linked_list_node_base):
    Data : t

linked_list_node_int := class(linked_list_node(int)){}
linked_list_node_float := class(linked_list_node(float)){}
linked_list_node_agent := class(linked_list_node(agent)){}

linked_list_base := class:
    var Head: ?linked_list_node_base = false
    var Tail: ?linked_list_node_base = false

linked_list_int:=class(linked_list_base):
    AddValue(Value: int): void =
        # ...
    DoSomethingWithList() : void =
        if(var CurrentNode: linked_node_base = Head?):
            loop:
                if(CurrentEventNode:= linked_list_node_int[CurrentNode]):
                    # Do something with CurrentEventNode.Data
                    if (set CurrentNode=CurrentNode.Next?):
                    else:
                        break

linked_list_float:=class(linked_list_base):
    AddValue(Value: int): void =
        # ...
    DoSomethingWithList() : void =
        if(var CurrentNode: linked_node_base = Head?):
            loop:
                if(CurrentEventNode:= linked_list_node_float[CurrentNode]):
                    # Do something with CurrentEventNode.Data
                    if (set CurrentNode=CurrentNode.Next?):
                    else:
                        break

linked_list_agent:=class(linked_list_base):
    AddValue(Value: int): void =
        # ...
    DoSomethingWithList() : void =
        if(var CurrentNode: linked_node_base = Head?):
            loop:
                if(CurrentEventNode:= linked_list_node_agent[CurrentNode]):
                    # Do something with CurrentEventNode.Data
                    if (set CurrentNode=CurrentNode.Next?):
                    else:
                        break

some_device := class(creative_device):
    IntList: linked_list_int = linked_list_int{}
    FloatList: linked_list_float = linked_list_float{}
    AgentList: linked_list_agent = linked_list_agent{}

The example above is heavily simplified already and in practice, this is way worse than my minimum example. However i hope this makes clear how much those restrictions spaghettify the code and there is no way around it.

I really wish we might get some updates on parametric classes or at least get it put into the roadmap.

In my specific case, that i will not be able to show here, the lack of functionality lead to 900 additional lines of code, while this feature would have kept it doable in like 30 lines of code instead.

@Daigoro Thank you for your feedback. While I cannot guarantee a response, I can confirm that this has been forwarded to the appropriate team.

1 Like

No problem, I guess it is something that will be implemented at some point anyways, since parametric classes are a core Verse feature, that is probably still in WIP state, but since I didn’t see a proper feature request yet, i thought i should probably submit one.

Instead of my example above, it might also best to point to the “Verse Linked List” guide under the assumption that someone wants to make linked lists for multiple types.

Out of curiosity, do you know if there is a Verse roadmap or similar? I’m just curious what kind of things to expect from it in near future.

1 Like

I understand the mutable variable problem you’re talking about, but I don’t see any cast in your example, are you talking about type inference ?

I do agree that parametric types need more involving though, it would be great to be able to start on building generic libraries for sure.

Yeah, I don’t cast inside the “ideal” solution part, since there I don’t need to have a linked_list_node_base. However inside the “currently available” solution’s “DoSomethingWithList” function, I am casting right after the loop starts.

if(CurrentEventNode:= linked_list_node_agent[CurrentNode]):

I could add a parametric class like linked_list_node(t: agent), write the DoSomethingWithList function there with a parametric cast and make the subclasses likelinked_list_node_agent inherit from it, to not rewrite it for every type.

It’s not as good as the “ideal” solution, but would still be a improvement tho.

1 Like

God only knows how much I hate this, makes parametrc classes almost useless.

2 Likes

I stumbled on this post when going through Linked Lists and it seems like there’s almost nothing you can do with Data:any = {} and parametric types don’t seem to be the answer either.

If the linked list Data is some class type then a list of any derived can be made and Data dynamically determined using Object reference casting… But that has the restriction that all data must be derived from some base class and obviously builtin types don’t work at all this way. Is there anything like a generic or template in Verse?

Parametric classes are our generics/templates, but they don’t support mutables yet. The only way to make the linked list work with several types is copy pasting it entirely for several types. An alternative would be using a parametric class without mutable fields, but recreating it entirely on every modification. There are a lot of issues related to that approach, but there isn’t much of an alternative.

The tutorial dodges the entire topic by simply using the any type, which makes the tutorial entirely useless and misleading.