I’m trying to do the same thing in SuperCollider, but the interpreter freezes each time. I assume it’s going down a recursive rabbit hole. I’ve tried a few different ways:
x = List[1, 2, 3];
x.add(x);
x = List[1, 2, 3];
x.add(`x);
Is this an interpreter bug? Is there a correct way to do this? I played with Refs but they don’t seem to help. Thanks!
Lazy evaluation was the magic word, sorry I forgot to mention that.
I think I figured out a workaround, by wrapping the value in a function:
a = List[1, 2, 3];
a.add({a});
Then I can lazily evaluate it like this:
a[3].value;
I know this might seem pointless without context, but I’m trying to build my own pattern library. It’s graph based, so I want patterns to be able to point to themselves, to enable single-pattern looping.
The data structure is constructed in memory exactly as you describe.
The problem is trying to produce a string to print in the post window.
x = [1, 2, 3]; // OK, obviously
// the empty string blocks posting -- this does not hang
x = x.add(x); ""
// the successful identity test here shows
// that the data structure is properly recursive
x[3] === x[3][3]
-> true
One catch here: “normal” sclang (including running it in SC-IDE) produces post window strings by calling asString on the code block’s result. This method imposes a 512 character limit; a longer result string is truncated, and prints with “…etc…” appended. So the x list in your example will print up to the limit and then stop – no hang.
But, based on your comment in the other thread about preferring vscode, I suppose you’re running it in vscode instead. The language server quark uses CollStream instead of LimitedWriteStream to produce the post window string representation. So it never stops trying to render the infinite recursion.
It’s one of the not-so-ideal things that can happen easily in SC-land, where there isn’t (for instance) a functional spec written down for post window output. So, if someone needs to create an alternate code path to execute code, not going through interpretPrintCmdLine, they are pretty much left to make it up as they go along, and it’s very easy to overlook details like blocking infinite recursion.
You could fix this for yourself in LanguageServer/Providers/EvaluateProvider.sc, around line 46. Probably the easiest way is result[\result] = function.value().asString; and delete the use of CollStream.
It’s graph based, so I want patterns to be able to point to themselves, to enable single-pattern looping.
I don’t know of anything that would prevent you from doing this
Interesting to know this about strings. Today I was writing a variation of sclang-eval-string so the result would not be sent to the post window, but appear as a temporary display in the buffer. It made sense in a particular situation, but maybe that’s not something to be playing too much ))