Support `yield return` like thing?

The below code is written in C#.

	private static IEnumerable<Node> GetAllDescendants(Node match)
	{
		yield return match;
		if (match.Value is JsonObject obj)
		{
			foreach (var member in obj)
			{
				var localMatch = new Node(member.Value, match.Location!.Append(member.Key));
				foreach (var descendant in GetAllDescendants(localMatch))
				{
					yield return descendant;
				}
			}
		}
		else if (match.Value is JsonArray arr)
		{
			for (var i = 0; i < arr.Count; i++)
			{
				var member = arr[i];
				var localMatch = new Node(member, match.Location!.Append(i));
				foreach (var descendant in GetAllDescendants(localMatch))
				{
					yield return descendant;
				}
			}
		}
	}

I find it quite simple, maybe in Scala it should just be yield.

Scala does have yield, not sure if I understand your question?

It yield the value inside the loop, and all yield will be the resulting IEnumerable just like a lazy list/ stream, it works like a generator , which means if you not iterating the next value , the program is suspended, which means it’s lazy.

Scala has LazyList and also .view to create lazy collections.

This like thing are basically a generators and uses concepts from coroutines. While being possible to implement it requires lots of work to transform generated code, at least when using JVM.
There was once discussion about them Generators via Continuations / Suspendable Functions

4 Likes
def getAllDescendants(j: Json): Iterator[Json] = j match
  case o: Json.Obj => o.iterator.flatMap{ case (k, v) => getAllDescendants(v) }
  case a: Json.Arr => a.iterator.flatMap(getAllDescendants)
  case _           => Iterator(j)

Seems a lot simpler to me (given a Json library that works that way).

(If I misunderstood what the code does, a very similar scheme will work for whatever you had in mind.)

3 Likes