As we are designing the language, we ran into an interesting problem. Let’s say we introduced a data type called linked_list_of_int. It’s a structure that references itself. It implements a doubly linked, circular list. When the list is empty, its next and prev pointers will point at the node itself. Thus self-referencing.

One straightforward way of initializing an instance of this structure is this:

l linked_list_of_int
l.init()

What if we wanted to use something like a designated initializer? Something like:

l := linked_list_of_int{node={next=&l, prev=&l}}

When we write the code like this, l is declared first and then we assign its value. While l itself does not have valid values, it has an address. We can then refer to that address when we initialize next and prev.

This looks promising, but the problem is that on the right side of the assignment operator we can have a macro. The macro will return a code block that initializes the variable. The problem is that the macro is generic. When we write the macro, we will not know the name of the variable that will store the structure that we initialize. Therefore, having something like self, a generic name that we can use to refer to the destination of the initialization block, is preferable.

The next interesting question to contend with is whether blocks of code that use self should be special block constructs. Do we need something like:

l := init{node={next=&self, prev=&self}}

or can we get along without the init keyword? Arguably, if we can get along without init, then we should do that. Hence the above example will look like this:

l := {node={next=&self, prev=&self}}

This should be somewhat straightforward to implement. The self keyword must appear in the code block to the right of initialization.

The overall problem we are trying to solve here is implementing an optimization called copy elision. With this optimization we are looking for a way to avoid creating a temporary object and then copying it into the memory region allocated for the variable.