I posted the following code on rosettacode.org for the task of converting Arabic and Roman numerals.
import std.regex, std.array, std.algorithm;
immutable {
int[] weights = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
string[] symbols = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX",
"V", "IV", "I"];
}
string toRoman(int n) {
auto app = appender!string;
foreach (i, w; weights) {
while (n >= w) {
app.put(symbols[i]);
n -= w;
}
if (n == 0) break;
}
return app.data;
}
int toArabic(string s) {
int arabic;
foreach (m; match(s, "CM|CD|XC|XL|IX|IV|[MDCLXVI]")) {
arabic += weights[symbols.indexOf(m.hit)];
}
return arabic;
}
It used to work just fine, but now I get a compiler error.
Error: template
std.algorithm.indexOf(alias pred = “a
== b”,R1,R2) if (is(typeof(startsWith!(pred)(haystack,needl
e)))) does not match any function
template declaration
According to the documentation indexOf is deprecated, and countUntil should be used in stead, but it gives me the same error.
Long story but I’ll try to keep it short:
std.algorithm.indexOfexpects an input range, which is a structural type that must definefront,popFront()andempty. For arrays, these methods are defined in std.array and work via uniform function call syntax, which allowsfun(someArray)to work the same assomeArray.fun().immutable string[]is not an input range, sincepopFrontremoves the first element of the array, which cannot be done for an immutable type. The fact that this used to work was a bug.I’ve updated the Rosetta Code entry to change
symbolsto animmutable(string)[]. Here, the elements ofsymbolsare immutable, but the array may be sliced and reassigned. For example:immutable string[]is implicitly convertible toimmutable(string)[]but implicit function template instantiation (often denoted IFTI; this is what’s used to instantiate theindexOftemplate) is not smart enough try this.