Could introducing formal interfaces be nonbreaking?

I’m surprised by the talk about formal interfaces coming to the base language. I thought that was impossible before Julia 2.0, as they will necessarily break all the packages who don’t conform to the new interface. For example, there might be some package now where == returns an Int, and that’s allowed.

1 Like

once you make the distinction between traits (a feature) and interfaces (more comments in code, less ambiguous docs, shared cultural values of rigorous testing suites) I think it would become less surprising to see more interfaces before a 2.0

with a stricter interface for ==, returning an Int would not start erroring, but it might give rise to a GH issue (which is not breaking)

GH issue?

GitHub, i.e. “hey package XYZ, you should be aware that the current definition of == here does not satisfy the interface decided upon in v1.x”

Well yes and no. It’s not breaking to add interfaces to the language. It’s breaking to enforce such an interface on a Base abstract type / function. So adding the ability to define an interface isn’t necessarily breaking, but saying AbstractArray now needs to satisfy a specific interface is.

We will of course want the latter, and that’s a whole different discussion…

10 Likes

Maybe make it throw a warning, and 3 years after throwing warnings, turn it into an error? Otherwise it’s useless.

2 Likes

It’s not allowed (according to the doc string). However, yeah, in practice mechanically disallowing that now would be very disruptive. Relevant discussion:

To be specific, this is what the doc string says currently:

The result is of type Bool, except when one of the operands is missing, in which case missing is returned (three-valued logic).

I meant allowed in the sense that it does not throw an error, or even a warning. The docstring does not enforce anything. And without enforcement it is doomed to happen. Hence the need for formal interfaces.

2 Likes

There are many many degrees of freedom in how such a feature might be developed. And there are lots of different possible mechanisms for opt-in and enforcement — and precisely how and when that enforcement happens.

I could imagine many designs that are both non-breaking and still very useful. But it’s all highly speculative.

6 Likes

Such as?

Disagree. More tooling for mechanically enforcing stuff would be nice, however at the end of the day it all comes down to having good documentation. Any static analysis approach is limited due to basic results from computability theory (“does a program halt?”).

One of the Julia compiler developers happens to have a series of relevant blog posts, on the basics of static analysis:

EDIT: what I’m trying to say is that documentation is the most important aspect for ensuring interface compliance or correctness. I’m not arguing against tooling. Formal specifications or model checking or stuff like that are another possibility, however that’s clearly not relied on very much, except in specific industries, where it’s presumably mandated by laws or regulation?

2 Likes

One relevant approach is letting programmers opt into a language subset:

3 Likes

It’s still a bug. I would not consider it breaking to start enforcing interfaces. Of course there is always code that depends on bugs or some undefined behavior, but breaking such code does not violate SemVer.

5 Likes

In principle I agree, but, taking the linked Github issue above as an example, starting to enforce the == return type contract would break Symbolics.jl.

Please. Even in the stdlibs I found (and fixed) several examples of docstrings that contradicted the code. One can do a lot of good static analysis without making it Turing complete. In this particular case one could require the function signature to be ==(a::MyType, b::MyType)::Bool, which is trivial to check.

5 Likes

Sure. What I’m saying is: at the end of the day you still need the docs to be the “word of god”. Because it’s only “a lot of”.

1 Like

I don’t know if I would call that a bug. Julia is a dynamic language, after all. If someone intentionally disregards the Base.== docstring when they implement it for their type, they accept the consequences of doing that. In particular, as we’ve seen, it can be handy to “pun” on operators when you are creating a DSL. I lean toward allowing DSLs to do whatever they want with their function overloads.

2 Likes

Well in the cases I fixed the word of god was the code, the docstrings were wrong. Which I think is the usual case, as docstrings are easy to ignore, bugs less so.

5 Likes

From a quick glance, the extension proposed in Generalize `==` Documentation to not be Statistics-Specific by ChrisRackauckas · Pull Request #53024 · JuliaLang/julia · GitHub seems to broaden the contract, not narrow it. That shouldn’t break code adhering to the currently documented contract. So I wouldn’t necessarily have a problem with that kind of extension. (Edit: actually, I think one of the comments on the issue nails it: It’s fine to use == with a non-standard meaning in a DSL macro, but not in actual code)

A mismatch between documentation and code is always a bug, by definition, and fixing it either by changing the code or fixing the documentation is not “breaking”. This is of course arguable, but I don’t think “wrong documentation” automatically trounces “wrong code”.

1 Like

I agree, and one of those consequences might be having a non-breaking Julia release require some adjustments in the package

1 Like