On 2/6/20 7:16 AM, mark wrote:
I am starting on porting Python's difflib's sequence matcher to D.
I want to have a class that will accept two ranges whose elements are of
the same type and whose elements can be compared for equality.
How do I make a class declaration that specifies a (forward) range type
and an equality-supporting element type?
Here's what doesn't work:
class Diff(T, E) {
T a; // T should be a forward range of E elements
T b; // E elements must support == and !=
// This is a hash key=E element, value=slice of size_t
size_t[][E] b2j;
this(T a, T b) {
this.a = a;
this.b = b;
chainB();
}
void chainB() {
foreach (i, element; b)
b2j[element] ~= i;
// TODO
}
}
unittest {
import std.stdio: writeln;
writeln("unittest for the diffrange library.");
auto a = ["Tulips are yellow,", "Violets are blue,",
"Agar is sweet,", "As are you."];
auto b = ["Roses are red,", "Violets are blue,",
"Sugar is sweet,", "And so are you."];
auto diff = Diff(a, b);
}
1. If one template parameter depends 100% on the other, it doesn't need
to be a parameter. i.e. I would do:
class Diff(T) {
alias E = ElementType!T;
...
}
2. Class constructors do not support IFTI. You have to explicitly
instantiate. To use IFTI, you need to create a factory function. i.e. to
make the code above work, your ctor call should be Diff!(typeof(a))
(assuming you take the advice in 1).
But you can instead write a function to use IFTI:
auto makeDiff(T)(T r1, T r2) { return Diff!T(r1, r2); }
...
auto diff = makeDiff(a, b);
3. You should declare constraints signifying what types are valid. i.e.:
class Diff(T) if (
isForwardRange!T // it's a forward range
&& is(typeof(T.init.front == T.init.front)) // elements are comparable
)
Might be good to put this constraint on the factory function too.
Note: is(typeof(...)) basically checks if the thing inside the typeof
compiles.
-Steve