Give me a yield break
![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Working in .NET, I've been in a situation where I need to implement a function in an interface that's supposed to return an IEnumerable<T>. (In some cases, I'd argue that IReadOnlyList<T> might make more sense - this way, the caller knows it's not going to be a lazily-evaluated sequence, and you can still return a .NET list, F# list, or array - but I digress).
Maybe the most obvious way to do this is by calling a function that explicitly returns an empty enumerable for you:
IEnumerable<string> SampleInterface.getAll() => Enumerable.Empty<string>();
In F#, it would be even shorter, because of the aggressive type resolution:
interface SampleInterface with member _.getAll() = Seq.empty
There are other clever ways to do the same thing, though, and it might just depend on what you think is the clearest or most readable - which might just mean keeping it consistent with the code around it. First, you can always expand out the function (because clearer isn't always shorter - I think it really does depend on the context of what's around it):
IEnumerable<string> SampleInterface.getAll() { return Enumerable.Empty<string>(); }
But there's also something clever you can do here, if you want to think of your code in a different way - where instead of resulting in "an empty list", it results in "no elements". C# lets you build iterator functions, where your code defines an IEnumerable<T> (and runs every time the resulting object is enumerated). Any function with a yield return
or a yield break
is treated in this way by the compiler. This means you can implement a function that returns "no elements" just by doing this:
IEnumerable<string> SampleInterface.getAll() { yield break; }
It's a bit different in VB.NET, where iterator functions are denoted explicitly - so the yield break isn't needed:
Public Iterator Function getAll() As IEnumerable(Of String) Implements SampleInterface.getAll End Function
That is, in a very literal sense, a function that returns no elements!
Funny thing is that there's no real equivalent to an empty iterator function in F# (not that you'd need it); the compiler won't allow a seq { }
workflow without any elements in it, and suggests you use Seq.empty
or the empty list []
instead.