<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<!--[if !mso]><style>v\:* {behavior:url(#default#VML);}
o\:* {behavior:url(#default#VML);}
w\:* {behavior:url(#default#VML);}
.shape {behavior:url(#default#VML);}
</style><![endif]--><style><!--
/* Font Definitions */
@font-face
{font-family:Helvetica;
panose-1:0 0 0 0 0 0 0 0 0 0;}
@font-face
{font-family:Courier;
panose-1:2 7 3 9 2 2 5 2 4 4;}
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Menlo;
panose-1:2 11 6 9 3 8 4 2 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0cm;
font-size:10.0pt;
font-family:"Calibri",sans-serif;}
h3
{mso-style-priority:9;
mso-style-link:"Heading 3 Char";
mso-margin-top-alt:auto;
margin-right:0cm;
mso-margin-bottom-alt:auto;
margin-left:0cm;
font-size:13.5pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
span.Heading3Char
{mso-style-name:"Heading 3 Char";
mso-style-priority:9;
mso-style-link:"Heading 3";
font-family:"Calibri Light";
color:#1F3763;}
span.EmailStyle20
{mso-style-type:personal-reply;
font-family:"Calibri",sans-serif;
color:windowtext;}
p.p1, li.p1, div.p1
{mso-style-name:p1;
margin:0cm;
font-size:8.5pt;
font-family:Menlo;
color:black;}
p.p2, li.p2, div.p2
{mso-style-name:p2;
margin:0cm;
font-size:8.5pt;
font-family:Menlo;
color:black;}
span.s2
{mso-style-name:s2;
text-decoration:underline;}
span.s1
{mso-style-name:s1;}
span.apple-converted-space
{mso-style-name:apple-converted-space;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;
mso-ligatures:none;}
@page WordSection1
{size:612.0pt 792.0pt;
margin:72.0pt 72.0pt 72.0pt 72.0pt;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-GB" link="blue" vlink="purple" style="word-wrap:break-word;overflow-wrap: break-word;-webkit-nbsp-mode: space;line-break:after-white-space">
<div class="WordSection1">
<p class="p1"><span style="font-size:11.0pt;font-family:"Calibri",sans-serif;mso-fareast-language:EN-US">As Gavin says, you can create what you want with non-record classes, and you can even do it with immutable objects!<br>
<br>
</span><span class="s1">jshell> </span><span class="s2">class</span><span class="s1">
<b>A</b> {</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...>
</span><span class="apple-converted-space"> </span><span class="s2">final</span><span class="s1"> B
<b>b</b>;</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...>
</span><span class="apple-converted-space"> </span><span class="s1"><b>A</b> () {</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...>
</span><span class="apple-converted-space"> </span><span class="s1">b = </span>
<span class="s2">new</span><span class="s1"> B(</span><span class="s2">this</span><span class="s1">);</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...>
</span><span class="apple-converted-space"> </span><span class="s1">}</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...> }</span><o:p></o:p></p>
<p class="p1"><span class="s1">|</span><span class="apple-converted-space"> </span>
<span class="s1">created class A, however, it cannot be referenced until class B is declared</span><o:p></o:p></p>
<p class="p2"><o:p> </o:p></p>
<p class="p1"><span class="s1">jshell> </span><span class="s2">class</span><span class="s1">
<b>B</b> {</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...>
</span><span class="apple-converted-space"> </span><span class="s2">final</span><span class="s1"> A
<b>a</b>;</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...>
</span><span class="apple-converted-space"> </span><span class="s1"><b>B</b> (A
<b>a</b>) {</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...>
</span><span class="apple-converted-space"> </span><span class="s2">this</span><span class="s1">.a = a;</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...>
</span><span class="apple-converted-space"> </span><span class="s1">}</span><o:p></o:p></p>
<p class="p1"><span class="apple-converted-space"> </span><span class="s1">...> }</span><o:p></o:p></p>
<p class="p1"><span class="s1">|</span><span class="apple-converted-space"> </span>
<span class="s1">created class B</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><br>
Using a combination of lambdas or similar to capture that work that needs to be done and leaking `this` out of the constructor you can produce bigger cycles, but for more complex graphs you’d need to do some work to create everything in the right order (or
maybe complete abuse Loom’s threads to yield in the middle of a constructor and pass references around in a queue), but it’s completely evil and probably not worth the effort.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">You can even pull the above trick with records, but you’ll need an extra level of cunning because you must delegate to the canonical constructor, so you’d need to find somewhere
else to stash all the state you’re passing around (private thread local maybe?) and pass entirely dummy values into that constructor, and it’s even more not worth it. You’ll also find that this sort of thing break lots of stuff, such as printing values in
jshell because there is an implicit assumption that nobody would be quite this evil.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">If you were going to be this evil then I think it would be easier to just indirect everything through a single array list or something and use indexes rather than refs.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">Duncan.<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">From:
</span></b><span style="font-size:12.0pt;color:black">amber-dev <amber-dev-retn@openjdk.org> on behalf of Gavin Bierman <gavin.bierman@oracle.com><br>
<b>Date: </b>Tuesday, 4 July 2023 at 11:14<br>
<b>To: </b>David Alayachew <davidalayachew@gmail.com><br>
<b>Cc: </b>amber-dev <amber-dev@openjdk.org><br>
<b>Subject: </b>Re: Question about circular references<o:p></o:p></span></p>
</div>
<div>
<h3><strong><span style="font-family:Helvetica;color:black;background:yellow">[External Email]</span></strong><span style="font-family:Helvetica;color:black"><o:p></o:p></span></h3>
<p class="MsoNormal"><span style="font-size:9.0pt;font-family:Helvetica;color:black"><o:p> </o:p></span></p>
<div class="MsoNormal" align="center" style="text-align:center"><span style="font-size:11.0pt">
<hr size="0" width="100%" align="center">
</span></div>
</div>
<p class="MsoNormal"><span style="font-size:11.0pt">Hi David, <o:p></o:p></span></p>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">I think what you are asking for is “why can’t I build cyclic record values”? <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">This is a reasonable question - it’s a very common question in languages that are build to be immutable from the ground-up, e.g. functional languages. For these languages the solution is either to just add
pointers (e.g Standard ML took this approach), or to support something more first class. If you look at F#, you’ll see that they support this - although it’s pretty hidden in the spec! They allow (i) let expressions to be recursive (with a REC keyword) and
(ii) they provide the AND operator to define mutually recursive value bindings and type declarations. This leads to code like this (taken from <a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/records">https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/records</a> )<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">// Create a Person type and use the Address type that is not defined</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">type Person =</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> { Name: string</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Age: int</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Address: Address }</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">// Define the Address type which is used in the Person record</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">and Address =</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> { Line1: string</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Line2: string</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> PostCode: string</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Occupant: Person }</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">// Create a Person type and use the Address type that is not defined</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">let rec person =</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> {</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Name = "Person name"</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Age = 12</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Address =</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> {</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Line1 = "line 1"</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Line2 = "line 2"</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> PostCode = "abc123"</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> Occupant = person</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> }</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> }</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
</div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">I think this is the sort of thing you are after, right? <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">The issue is that this would create **all sorts of problems**, e.g. around DA/DU, initialisation semantics, pattern matching semantics, etc. etc. <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">As Ron has suggested - if you want to build a cyclic structure then we already have fantastic technology for that - use classes. You want all the other fields to be immutable? Use final! Once we support patterns
in classes, then you’ll get many of the advantages of using records as a client.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">With records we have carved out a subset of classes that fit the design, for which we can give a great experience without massive changes to the language and its semantics. We could have gone further but we
would have to have made compromises that weren’t worth the price. <o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Hope this helps,<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Gavin<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">PS We also provide another option: Want to be a hacker? Make your record with array components and mutate the array contents to your heart's content!<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">record Loop(String head, Loop[] tail){};</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">Loop[] tl = new Loop[]{null};</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">var l = new Loop("hello", tl);</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">// A loop of hellos</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">tl[0]=l;</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">var tmp = l;</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">for(int i=0; i<100; i++){</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> System.out.println(i+": "+tmp.head());</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> tmp=tmp.tail()[0];</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">}</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">// Make l a loop of hello worlds</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">tl[0]=new Loop("world", new Loop[]{l});</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">for(int i=0; i<100; i++){</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> System.out.println(i+": "+tmp.head());</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier"> tmp=tmp.tail()[0];</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:Courier">}</span><span style="font-size:11.0pt"><o:p></o:p></span></p>
</div>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">(Don’t tell anyone I showed you this code :-) )<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt"><br>
<br>
<o:p></o:p></span></p>
<blockquote style="margin-top:5.0pt;margin-bottom:5.0pt">
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">On 30 Jun 2023, at 23:28, David Alayachew <davidalayachew@gmail.com> wrote:<o:p></o:p></span></p>
</div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
<div>
<div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New"">Hello all,<br>
<br>
First off, please let me know if I have CC'd the wrong groups. I've CC'd the Amber Dev Team since this involves records, but it's not specifically about records.<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New"">---<o:p></o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Courier New"">For the past couple of weeks, I have been building a program that uses a State Transition Diagram (aka State Machine, Finite Automata, etc. --
<a href="https://en.wikipedia.org/wiki/Finite-state_machine">
https://en.wikipedia.org/wiki/Finite-state_machine</a>) to model part of its control flow. I've been using some Amber features to facilitate this (and having a wonderful time of it), but then I hit a snag.<br>
<br>
Here is a(n EXTREMELY) simplified version of my actual problem. Imagine I have code like the following.<br>
<br>
```java<br>
<br>
sealed interface Node<T> permits StartNode, BranchingNode, EndNode {...unrelated stuff here...}<br>
<br>
record StartNode<T> (Node<T> a, Node<T> b, Node<T> c) implements Node<T> {}<br>
record BranchingNode<T> (Node<T> a, Node<T> b, Node<T> c, ...fields unrelated to transitioning...) implements Node<T> {}<br>
record EndNode<T> (...fields unrelated to transitioning...) implements Node<T> {}<br>
<br>
```<br>
<br>
This type hierarchy is meant to represent a control flow of sorts. Control flow is (imo) best modeled using a State Transition Diagram, so I instinctively reached for that. And since my API needed to be nothing but the data (each Node needed to be tightly coupled
to my internal state representation), I realized that this is an ideal use case for records.<br>
<br>
Things worked out well enough until I tried to model a circular relationship.<br>
<br>
Through chance, all of my control flows up to this point were tree-like, so I could model them by starting from the "leaves," then climbing up until I got to the "roots". To use State Transition Diagram terminology, I started from my exit states and modeled
my way up to my entry states.<br>
<br>
For example, assume that my State Transition Diagram is as so.<br>
<br>
S ---a---> T<br>
S ---b---> U<br>
S ---c---> V<br>
T ---a---> U<br>
T ---b---> V<br>
T ---c---> E<br>
U ---a---> V<br>
U --b|c--> E<br>
V -a|b|c-> E<br>
<br>
S is my StartNode, and E is my ExitNode.<br>
<br>
In this case, modeling with records is easy. It would look like so.<br>
<br>
```java<br>
<br>
ExitNode<UnrelatedStuff> e = new ExitNode<>(...unrelated...);<br>
BranchingNode<UnrelatedStuff> v = new BranchingNode<>(e, e, e, ...unrelated...);<br>
BranchingNode<UnrelatedStuff> u = new BranchingNode<>(v, e, e, ...unrelated...);<br>
BranchingNode<UnrelatedStuff> t = new BranchingNode<>(u, v, e, ...unrelated...);<br>
StartNode<UnrelatedStuff> s = new StartNode<>(t, u, v);<br>
<br>
return s;<br>
<br>
```<br>
<br>
But once I hit a circular reference, I could not figure out how to model the code using the same format.<br>
<br>
For example, what if I say the following instead?<br>
<br>
V ---a---> T<br>
<br>
How do I model that using my current representation?<br>
<br>
Obviously, I could change my representation, but all of them required me to "taint" my representation in incorrect ways.<br>
<br>
For example, I could swap out my records for simple classes where the references to Node's were mutable. But I strongly disapprove of this strategy because these nodes do NOT have a mutable relationship. Obviously, I could put something in the Javadoc, but
I want to fix the incorrect representation, not put a warning sign in front of it.<br>
<br>
Also, I could use indirection, like having a separate Map whose values are the actual Node references and the keys would be a record Pair<T>(String nodeId, Branch branch) {} where Branch is enum Branch { a, b, c, ; } and then give each Node an id, changing
my record to now be record BranchingNode<T> (String id, ...the same as above...) {}. But ignoring the fact that I now have to deal with managing an id, I've also added a lot of unnecessary bloat and indirection just to get the circular reference I wanted.
What should be a direct relationship now requires a Map lookup.<br>
<br>
In that same vein, someone suggested that I use pattern-matching for switch, but that would require me to create a new switch expression for every single state. That's even more verbose and indirect than the Map. At least with the map, I can put them all in
one expression. This strategy has an expression for each state!<br>
<br>
I've been told that there is another pathway involving reflection, but it basically amounts to breaking the rules of Java. Apparently, you can turn off finality to insert in fields you want, and then turn it back on? I liked this idea the least compared to
all of the others, so I didn't pursue it any further.<br>
<br>
In the end, I decided to go down the Map lookup route. But I just wanted to point out my experience with this because it was a surprising and annoying speed bump along an otherwise smooth road. I didn't think that something as small as a circular reference
would require me to uproot my entire solution.<br>
<br>
And finally, I want to emphasize that the same blockers above apply no matter what pathway I go down. I had actually tried implementing this first as an enum before I tried a record, since an enum would more accurately represent my state.<br>
<br>
```java<br>
<br>
enum State<br>
{<br>
<br>
V(T, EXIT, EXIT), //FAILURE -- T cannot be referenced yet<br>
U(V, EXIT, EXIT),<br>
T(U, V, EXIT),<br>
;<br>
<br>
...public final fields and constructor...<br>
<br>
}<br>
<br>
```<br>
<br>
But even then, the same problem occurred -- I can't reference an enum value until it has been declared. I thought going down the path of records would give me the flexibility I wanted, but no dice.<br>
<br>
It reminded me of that one programming meme.<br>
<br>
> * High Quality<br>
> * Quickly Built<br>
> * Low Cost<br>
> <br>
> You can only pick 2<br>
<br>
But instead, it's<br>
<br>
* Circular Relationship<br>
* Immutability<br>
* Direct References<br>
<br>
What are your thoughts? Is this a problem in your eyes too? Or simply a non-issue?<br>
<br>
Thank you for your time and insight!<br>
David Alayachew<o:p></o:p></span></p>
</div>
</div>
</div>
</blockquote>
</div>
<p class="MsoNormal"><span style="font-size:11.0pt"><o:p> </o:p></span></p>
</div>
</div>
</body>
</html>