Even more clarification on Type piracy

As @Tamas_Papp mentioned and also in the second comment of the previous thread (and maybe elsewhere), dimension(integ::DEIntegrator) = length(integ.u) is not type piracy because you are not extending the function. In the document:

“Type piracy” refers to the practice of extending or redefining methods in Base or other packages on types that you have not defined.

https://docs.julialang.org/en/stable/manual/style-guide.html#Avoid-type-piracy-1

So, if you define a function from scratch, it is not type piracy.

There are two kinds of the ways you extend functions defined in other packages. (1) At least one of the argument is dispatched on type you defined. (2) None of the type are defined within your package (as in the case of step!).

From the definition of the document, category (1) is not type piracy. In fact, it is often the part of the interface: http://docs.juliadiffeq.org/latest/basics/integrator.html For example, defining iterator in Julia is done by extending Base.iteratoreltype etc.

The example *(x::Symbol, y::Symbol) = Symbol(x,y) in the document falls in category (2). I believe extending functions from other packages (not just Base) this way should be avoided unless there are very good reasons as mentioned in the document. For example, consider those four packages

  • A
  • B: uses A, extend functions in A via type piracy = category (2)
  • C: uses A, extend functions in A via type piracy = category (2)
  • D: uses B and C

Library B and C relies on the type piracy function internally and don’t know about other’s implementation. Now, package D author come in and think that B and C are useful so that B and C are imported into the package D. At this point, I imagine that B or C may break, depending on the order they are loaded. This is exactly the same as the reason why monkey patch has to be avoided.

5 Likes