Promote_op and preallocating result of linear operators

Martin’s koan is highly sarcastic. You don’t want to be using @pure or return_type, either.

This is indeed a very hard problem, and it’s a pain to do correctly. I’d love to see this improve — I’ve spent just a bit of time brainstorming solutions but haven’t seen any silver bullets yet.

The key is that you want the element type to be entirely determined by the values. So the “easy” solution is to just perform your operation on the first element(s), get the resulting value, and then use its type to allocate the container. There are two gotchas that make this hard though:

  • What do you do if the next element returns something different?
  • What do you do in the empty case?

If you get a new element type that doesn’t fit, the standard protocol is to split your function such that you can re-allocate a wider element type and recurse. That is, you want an inner function that can handle picking up at an arbitrary place in your iteration through the elements so that you can “swap out” the destination array to the wider one. Something like this: base/array.jl#L625-L645.

Of course, this is all predicated on having values. What do you do about the empty case? The ideal case is if you can just throw an error — but again, that’s not always possible. So this is where we reach in and ask inference for a little help. This is where it’s appropriate to use Base.return_type.

5 Likes