rafaqz / Interfaces.jl

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

Syntax/scope of interface definitions and implementations #9

Closed stemann closed 4 months ago

stemann commented 1 year ago

Any thoughts on the syntax proposed in (the prior) https://github.com/quinnj/Interfaces.jl ?

E.g.,

abstract type Indexable end

@interface Indexable begin
    getindex(::Indexable, i)
    setindex!(::Indexable, v, i)
    firstindex(::Indexable)
    lastindex(::Indexable)
end

@test Interfaces.implements(Array, Indexable, [Base])

It is clear that the mandatory/optional tests in your interface definitions goes further than just ensuring that proper methods are defined - with the proper argument/return types.

Updated: Also:

rafaqz commented 1 year ago

It doesn't even have a readme so not really.

The reason for mandatory/optional is that interfaces are often complicated. A widely used package like StaticArrays.jl could not use Indexible in your example on SArray, because it has no setindex!. So there is no point putting setindex! and getindex in the same flat interface like that. But they do belong together somehow or other, and we don't want to define an interface for all possible combinations of method definitions. So we need to be able to specify what we implement and what we skip.

But, I can't even remember why Duck() is needed. If you can reorganise things so it isn't, go for it. This was just an idea over a weekend that got a bunch of stars but no feedback or users as far as I known, so I kind of moved on to more pressing concerns.

stemann commented 1 year ago

OK.

Good points.

Regarding the Duck()'s, it seems - after a first glance at the code - that the test_objects could be dropped from the @implements definitions - and instead be required for the implements method calls (as in Interfaces.implements(Animals.AnimalInterface, Chicken()))

rafaqz commented 1 year ago

Sure, that does seem cleaner. A PR would be nice :)

rafaqz commented 1 year ago

Hm actually maybe put them in the test method call? implements really needs to work on types.

stemann commented 1 year ago

OK - from here on, let this issue be solely about the first question - the merits of the quinnj syntax, cf. https://github.com/rafaqz/Interfaces.jl/pull/10#issuecomment-1568470383

What do you think of the idea about having two ways of defining an interface? One with the "method signatures" syntax from quinnj, and one with the predicate syntax in v0.1.0 of this package?

Obviously, having two ways of doing one thing sounds alarming, but perhaps the method signatures syntax is more natural/appealing for people used to, e.g., a C# interface.

I'm thinking the macro could reasonably easy figure out which syntax is used and just define the predicates that correspond to testing the method signatures.

rafaqz commented 1 year ago

Yeah... its a little complicated to do both!

I used the function predicate approach because it can do pretty much anything, but that does come at the expense of style.

So this idea is about making the syntax slick? That is of course a valid goal.

If you can actually define a macro that does both, we can asses if it feels right to use it?

rafaqz commented 4 months ago

Closing this, from extensive use it doesn't look like the syntax needs to be any simpler