rafaqz / Interfaces.jl

Macros to define and implement interfaces, to ensure they are checked and correct.
MIT License
72 stars 4 forks source link

Elaborate on goals #12

Open stemann opened 1 year ago

stemann commented 1 year ago

I think it would be an idea to elaborate a bit on the goals of this package - and hence on the goals of defining and implementing interfaces in Julia. (as this package has claimed a rather generic name - and is making good use of it 👍)

I.e. to compile a more elaborate list of goals and get these in the README/documentation.

To compile answers for issues brought up e.g. in

E.g., the obvious one:

  1. An interface should define which methods to implement.
stemann commented 1 year ago

But perhaps it's better to keep (suggested) goals in separate comments, so they can be easily voted for.

stemann commented 1 year ago
  1. Defining and implementing interfaces should be adoptable by the ecosystem, so the method should be compatible with the current direction of the community: A. Using traits to define interfaces informally. B. Reducing TTFX. C. Enabling static analysis. D. Enabling static compilation.

As mentioned in https://github.com/rafaqz/Interfaces.jl/issues/11#issuecomment-1568515893

stemann commented 1 year ago
  1. (supporting 2) The cost of both defining an interface and stating that an interface is implemented should be purely compile time and not a lot of it (close to zero).
rafaqz commented 1 year ago

These are great, thanks.

We can probably finish them up in a readme PR where anyone can suggest edits and additional points?

stemann commented 1 year ago

We can probably finish them up in a readme PR where anyone can suggest edits and additional points?

Yes 👍

rafaqz commented 1 year ago
  1. There should be (semi)automated testing to prove that an interface is implemented for a specific type, strongly coupled to the interface definition.
rafaqz commented 1 year ago
  1. An interface should provide low/no overhead traits so that it can be checked if it is implemented for a type
rafaqz commented 1 year ago
  1. An interface may also specify which types to inherit from (Maybe this should be 2)
rafaqz commented 1 year ago
  1. An interface may specify the types (and values??) a method must accept and return
stemann commented 1 year ago

4. There should be (semi)automated testing to prove that an interface is implemented for a specific type, strongly coupled to the interface definition.

Can you elaborate on "(semi)automated" (and testing) and "strongly coupled"?

I guess this means something like:

Or maybe a rephrase of what is currently in the README?

Sorry - this got unnecessarily long for a "please elaborate" comment :-)

stemann commented 1 year ago

5. An interface should provide low/no overhead traits so that it can be checked if an interface is implemented for a type

Can you elaborate on the concern here?

This is implementation that supports 4? And 2 (the community using traits already?)

stemann commented 1 year ago

6. (Maybe this should be 2)

We can always reorder in the PR, but also good to suggest ordering.

stemann commented 1 year ago

6. An interface may also specify which types to inherit from.

I.e. the goal is to support hierarchies of interfaces (as mentioned in #6)?

E.g. to support:

@interface AnimalInterface ...
@interface BirdInterface <: AnimalInterface ...
@implements BirdInterface Duck

and thus inheriting AnimalInterface in BirdInterface - and stating that both AnimalInterface and BirdInterface is implemented wrt. Duck.

stemann commented 1 year ago
  1. Interface definition - and interface implementation statement - should support multiple dispatch.

I.e., methods dispatch wrt. multiple arguments, so the interface definitions should support defining methods wrt. tuples of types.

(edit: @rafaqz you mentioned something like that in https://github.com/rafaqz/Interfaces.jl/issues/6#issuecomment-1185393722 - but that comment might be about something else...)

rafaqz commented 1 year ago
  1. I guess its hard to be more specific because there are various ideas floating around, and annoying constraints on optimal designs.

I was trying to capture that the interface definition contains tests. The strong coupling is via being in the same macro so the structure is forced. Previously the @implements macro actually put all the tests in a precompile function and ran it, so there was no ambiguity at all about the interface being tested - it was "automated" testing.

Now what we have is semi-automated, in that you get a function defined that runs tests, but you have to manually run it somewhere in your test suite and we have to trust that everyone does that. This is a compromise for performance, and it may not be possible to do more than this generally.

The interface definition should provide enough information, that it enables the Interfaces package to provide a test method (Interfaces.test), that makes it easy for users to implement tests of their interface implementations? (this is probably too specific for a goal)

This might be the most accurate goal though

The interface definition should provide enough information, that it enables compile-time enforcement/testing?

I don't think the compile time testing part is broadly possible in practice

The interface definition should enable test suites as described in https://invenia.github.io/blog/2020/11/06/interfacetesting/

The invenia blog style is the basis of a lot of this. But it hasn't lead to a consistent recognizable way of reading and running interface tests across the ecosystem. So we are aiming for a little more structure than that.

Or maybe a rephrase of what is currently in the README?

Defining an interface should enable tests.

As mentioned above it used to, but currently it does not automatically enable them, and its an open question if it should. (hmm maybe you meant "provide" here rather than "enable")

Or the long form: Defining an interface and stating that the interface is implemented for a type should enable testing that the latter is the case - by exploiting the information in the interface definition.

As a generic statement this one is pretty good :)

stemann commented 1 year ago

7. An interface may specify the types (and values??) a method must accept and return

I would suggest to leave the "values" part out of this to make it less controversial :-) Maybe put the "interface provides values" in a list of candidate goals being considered.

rafaqz commented 1 year ago

hah sorry I should have broken that up

stemann commented 1 year ago

hah sorry I should have broken that up

Feel free to edit (for the time being) :-)

rafaqz commented 1 year ago

5 This was to make it clear that traits and tests are not the same thing, and probably need to stay decoupled. So its really in opposition to 4. I have just found this to be a common point of confusion.

rafaqz commented 1 year ago
  1. This was simply saying that interfaces are not just about defining methods, and point 1 is incomplete. You can define all the methods in the AbstractArray interface of your own type, but it only follows the interface by also being <: AbstracatArray.
stemann commented 1 year ago
  1. This was to make it clear that traits and tests are not the same thing, and probably need to stay decoupled. So its really in opposition to 4. I have just found this to be a common point of confusion.

Yes - good to get things clarified! 🙏 👍

So this was a response to 5 (not 6)? I.e.

  1. An interface should provide low/no overhead traits so that it can be checked if an interface is implemented for a type

Can you elaborate on the concern here?

This is implementation that supports 4? And 2 (the community using traits already?)

rafaqz commented 1 year ago

yeah, 5 :sweat_smile: