Replies: 2 comments
-
In light of #17, this proposal will need modification. Rather than our analogue of I wonder whether it'd be desirable/useful to retain something similar to the distinction we now have between |
Beta Was this translation helpful? Give feedback.
-
I have an implementation of this approach in my [patch.crates-io]
copse = { git = "https://github.com/eggyal/copse", branch = "contextual_cmp" } Would love to have some feedback on this approach, especially with respect to ergonomics; I've actually been pleasantly surprised how the boilerplate has reduced versus the status quo, so right now I'm leaning towards accepting this change. But I can also see that it could be more confusing to grok, and particularly frustrating if impls all have to be provided without the I haven't yet documented any of the new items, but I have updated all existing documentation including the |
Beta Was this translation helpful? Give feedback.
-
Since first publishing copse just a few weeks ago, there's been quite a bit of API churn—I hope it hasn't caused too much headache for many/any users? I rushed to publish too quickly. Apologies.
I am however now pretty comfortable with the v0.4 API and don't expect it to change significantly... except perhaps to accommodate the following idea.
I've been toying with
TotalOrder
trait into four separate ones to reflect the standard library'sOrd
,PartialOrd
,Eq
andPartialEq
traits;Borrow
trait instead of theSortableBy
trait, thereby providing much greater fidelity with the standard library collections.I expect that, were this to happen, the arising four comparison traits (together with the default
OrdTotalOrder
implementation) and one borrow trait would be extracted into a separate library crate upon which copse would depend: let's call itstateful-cmp
for now.However, whilst this idea has some considerable architectural appeal, I am concerned about the ergonomics:
Users of copse would need to implement, for each total order that they define, all four comparison traits. The standard library has the same problem here, albeit in most cases it can be trivially accomplished by the provided
derive
macros; in our case the comparison is necessarily something non-standard (depending on runtime state) and so while a macro approach to implementing these traits is of course feasible, the invocation format will necessarily be something a little more bespoke/unfamiliar.Furthermore there would need to be suitable implementations of our
Borrow
analogue. What would that analogue look like? The standard library'sBorrow
trait serves two purposes: to provide a method that converts&self
into&Borrowed
; and to assert thatBorrowed
preserves comparison (and hashing) behaviour with respect toSelf
.For maximum fidelity with the standard library, our analogue would have to be parameterised by the total order for which it asserts comparisons will be preserved—hence we would end up with different implementations of our
Borrow
analogue for each total order: whilst a macro could again reduce the boilerplate/ergonomic burden here, we could still feasibly end up with different conversions from&self
into&Borrowed
in each case, and I'm not sure there's any justification for that?The alternative is to split from our analogue of the
Borrow
trait its assertion of comparison preservation, so that it becomes more akin to the standard library'sAsRef
trait albeit with a reflexive blanket implementation (indeed we could just use the standard library'sBorrow
trait if it is acceptable to limit our notion of "borrowing" to types that meet its requirements). That assertion would then be made by some other trait, perhaps a mere marker subtrait liketrait ComparisonPreserved<Borrowed, TotalOrder>: Borrow<Borrowed> {}
.Either way, we would still have the same issue in providing blanket implementations as we currently have with
SortableBy
: we can either provide a blanket reflexive implementation for all total orders, or we can provide a blanket implementation of all standard libraryBorrow
s for the defaultOrdTotalOrder
. Again, macros could help somewhat to reduce the boilerplate.Overall this idea seems to come at the cost of not inconsiderable boilerplate, potentially eased by macros that in turn increase cognitive load. I'm not at present convinced that the benefit outweighs these issues, though I'd be delighted to hear thoughts?
Perhaps the most persuasive argument for this idea is that such a
stateful-cmp
crate could be of wider use outside of copse.Beta Was this translation helpful? Give feedback.
All reactions