andyferris / Dictionaries.jl

An alternative interface for dictionaries in Julia, for improved productivity and performance
Other
278 stars 28 forks source link

Should `issettable` be allowed to be defined on a type? #76

Open quinnj opened 2 years ago

quinnj commented 2 years ago

While reviewing the interfaces here with @nickrobinson251, we found it curious that issettable is only expected to be defined on an instance instead of as a "trait" that can be defined on the type. From the docs, it says that if mutability is supported, then issettable should return true, and setindex! should be defined. It seems like the majority of implementations would be able to define issettable statically on a type once, instead of on instances.

One pattern we've followed in the Tables.jl interface for these kind of type traits is to allow defining the trait function on either instances or types, with the encouragement to define on the type where possible. But users/callers of the trait, should always call on the instance, while having a generic fallback like issettable(x::T) where {T} = issettable(T). That allows the compiler to correctly statically infer traits where possible, and rely on runtime checking when necessary.

Just curious how intentional the current issettable design was and if so, what the context is around the decision.

andyferris commented 2 years ago

I guess this was a bit of an experiment in a value-driven interface. Traits functions that take values and return values. Also, it's theoretically possible to have types that are "freezable" at run-time, for example. We could use Settable() and Immutable() singleton values instead of true and false to a similar effect. (I don't even really like the term "settable" that much).

The only place I use seem to need to use type-domain logic is in similar_type, empty_type, etc, and even there it feels "yucky"...

That allows the compiler to correctly statically infer traits where possible, and rely on runtime checking when necessary.

Constant propagation seems to work everywhere I've checked. Have you had any issues?

I don't know - what are your thoughts?

andyferris commented 2 years ago

Also, it's theoretically possible to have types that are "freezable" at run-time, for example.

For context, copy-on-write indices would work well with indices and how similar doesn't copy them. I was thinking a bit about this at the time. Currently what's there is quite unsafe when mixing functional style and mutating indices (i.e. inserting or deleting from dictionaries). Fixing this "properly" is waiting on freeze/thaw on Array to land in Julia (if that is indeed still the plan).

andyferris commented 2 years ago

Did you guys have any further thoughts? Are you aware of some good scenarios for defining and/or using it at the type level?

quinnj commented 2 years ago

Yeah, the main motivation for opening the issue was our joint work on a new Interfaces.jl package, which is focused on supporting static interfaces in Julia for now (and not in any dispatchable way, but more as a developer and documentation aid). But the "static" requirement means that for conditional requirements like setindex! based on issettable, it needs to be able to be defined on types instead of instances. You can see some examples of how the package works in the current tests: https://github.com/quinnj/Interfaces.jl/blob/main/test/runtests.jl