Hacker News new | ask | show | jobs
by IvoDankolov 5367 days ago
I have two issues with the article (notwithstanding that I had to look it up in google cache because the server wasn't responding).

First, while it's true that in this particular case iterating exposes gritty implementation details (because, to even define "iteration", you need to know about all the possible implementations and how they store items). However, that doesn't mean that the design of the interface can't be changed so that iteration is possible. The fastest I can come up with is adding a concept of inner set (that might or might not be null) and a method containsOuter, that by contract should not dig into the inner set. Then, for the adjoint set implementation you would have (in a more C-family style)

  bool contains(T item)
  {
    bool res = containsOuter(item);
    IntSet next = getInnerSet();
    while(!set && next != null)
    {
      res |= next.containsOuter(item);
      next = next.getInnerSet();
    }
  }
And we have iteration, without having to resort to implementation details. Barring any argument about aesthetic appeal of having this innerSet thingy, the code itself is simple enough to manage (heck, you could have that as a virtual method without any problems if you were in the frame of mind of class inheritance as opposed to interfaces).

Second, I don't see why we can't abstract this iteration business into an iterator. Fine, Java's iterators may or may not be a sprawling mess, but add lazy evaluation to the mix and you have a very, very powerful system. In particular, LINQ and Haskell handle collections quite nicely, and nothing stops you from implementing it in the OO language of your choice (if there aren't already some).

So how do lazy iterators help? Well, infinite sets become stupidly easy to handle. Heck, you can even self reference in C#:

  static IEnumerable<int> Nats()
  {
    yield return 1;
    foreach (var n in Nats().Select(x => x + 1))
      yield return n;
  }
Not that I recommend mapping your collection to itself, mind, but if you wished you could go all out with it. The point is, you can transform an infinite list, filter elements out of it, combine it with another infinite list and then take 10. It won't even take infinite time to compute.

So no, lack of tail recursion is not a detrimental problem to the OO abstraction. An annoying problem, yes, but no more than that.