AW: [External] : Re: Question about circular references

redio.development at gmail.com redio.development at gmail.com
Tue Jul 4 07:39:46 UTC 2023


I think the main problem as I understand it is, that you cannot forward declare the identity of an object. So it’s technically not a record problem but a class problem.

If you could forward declare an uninitialized Object reference like this pseudo code does:

EndNode e = new EndNode();

BranchNode v = uninit;

BranchNode u = new BranchNode(v, e, e);

BranchNode t = new BranchNode(u, v, e);

v = new BranchNode(t, e, e);

StartNode s = new StartNode(t, u, v);

 

You wouldn’t have that problem. The problem here is that you would need the notion of references that are neither null nor an object but in some sort of null with identity that is later initialized.

An easy solution would be to go for an ID instead of java references. IDs have the benefit that you can forward declare them:

 

public class Test {

    public static void main(String[] args) {

        EndNode e = new EndNode(UUID.randomUUID());

        UUID vUUID = UUID.randomUUID();

        BranchNode u = new BranchNode(UUID.randomUUID(), vUUID, e.self(), e.self());

        BranchNode t = new BranchNode(UUID.randomUUID(), u.self(), vUUID, e.self());

        BranchNode v = new BranchNode(vUUID, t.self(), e.self(), e.self());

        StartNode s = new StartNode(UUID.randomUUID(), t.self(), u.self(), v.self());

    }

}

 

class NodeStore {

    public static final Map<UUID, Node> map = new HashMap<>();

}

 

sealed interface Node {

    UUID self();

}

 

record StartNode(UUID self, UUID a, UUID b, UUID c) implements Node {

 

    public StartNode {

        NodeStore.map.put(self, this);

    }

}

 

record BranchNode(UUID self, UUID a, UUID b, UUID c) implements Node {

    public BranchNode {

        NodeStore.map.put(self, this);

    }

}

 

record EndNode(UUID self) implements Node {

    public EndNode {

        NodeStore.map.put(self, this);

    }

}

 

The downside is that you are responsible to manage the IDs instead of the runtime.

 

Hope that helps

 

Great Regards

RedIODev

 

Von: amber-dev <amber-dev-retn at openjdk.org> Im Auftrag von David Alayachew
Gesendet: Dienstag, 4. Juli 2023 03:43
An: Ron Pressler <ron.pressler at oracle.com>
Cc: amber-dev <amber-dev at openjdk.org>
Betreff: Re: [External] : Re: Question about circular references

 

 

Hello Ron,

 

Thank you for your response!


> I don’t see a lack of representability. Java’s records
> can represent tuples — the thing they are meant to
> represent.

Apologies, I was not clear here. My question to you is actually, do you see a problem with the fact that records cannot represent a circular reference to themselves?

According to the definitions I cited earlier, tuples/product types have circular references in their domain of possible values, and therefore, we do have a lack of representability if I model my data as nodes, and not edges. The fact that you can sidestep that by modelling it as edges does not change the fact that you do indeed have a gap of representability.

And to be clear, this question rises above State Transition Diagrams and just talks about circular references alone.

> and if you want to represent a graph in a more
> OOPy/pointery way, i.e. not with tuples, use classes that
> aren’t tuples, which are also representable in Java (and
> you can also make them immutable if you like).

Are you saying you can accomplish this without indirection, as in without a Map lookup or something equivalent? If so, please demonstrate.

> To represent a potentially cyclic graph with tuples you
> can use the ordinary representation of edges

I understand your point, but this requires me to apply an ill fitting model because the language is unable to map the one I actually need.

I am modeling control flow. The question that I am constantly asking is "What are my next possible steps from this current node?" Rather than having the node store that information directly, you are telling me to create a set of edges and simply perform a lookup on this set, filtering down to the ones that start/end (assuming bidirectional) with my current node so that I can figure out what my next option is. Do you see what I mean when I say that this ia a bad fit?

Yes, technically, that works, but this is even worse in the department of indirection. I didn't want to avoid indirection because indirection is in and of itself bad. I wanted to avoid indirection so that my model would have as little intellectual and data overhead as possible. I wanted to be able to answer my question as directly as possible so that I can reason about my problem as easily as possible. Your solution goes completely in the opposite direction of that and adds so much overhead that I would sooner choose the workarounds I mentioned originally.

And I'm sure that your strategy would be more useful in a weighted graph or something, but hopefully you see where I am coming from here?

 

Thank you for your time and insight!

David Alayachew

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20230704/3d224a46/attachment-0001.htm>


More information about the amber-dev mailing list