D2: std.algorithm.indexOf no longer works

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 worked fine, but now I get a compiler error.

Error: std.algorithm.indexOf pattern (alias pred = "a == b", R1, R2) if (is (typeof (startsWith! (Pred) (haystack, needl e)))) does not match any function announcement template

According to the documentation, indexOf is deprecated and countUntil should be used instead, but it gives me the same error.

+7
source share
3 answers

A long story, but I will try to do it shortly:

std.algorithm.indexOf expects an input range , which is the structural type that front , popFront() and empty should define. For arrays, these methods are defined in std.array and work through the syntax of uniform functions, which allows fun(someArray) to work just like someArray.fun() .

immutable string[] not an input range, since popFront deletes the first element of an array that cannot be executed for an immutable type. The fact that this worked was a mistake.

I updated the Rosetta code entry to change symbols to immutable(string)[] . Here, the elements of symbols are immutable, but the array can be sliced ​​and reassigned. For example:

 void main() { immutable string[] s1 = ["a", "b", "c"]; immutable(string)[] s2 = ["d", "e", "f"]; s2 = s2[1..$]; // This is what std.array.popFront does under the hood. assert(s2 == ["e", "f"]); // Passes. s2[1] = "g"; // Error: Can't modify immutable data. s1 = s1[1..$]; // Error: Can't modify immutable data. s1[1] = "g"; // Error: Can't modify immutable data. } 

immutable string[] implicitly converted to immutable(string)[] , but an implicit instance of a function template (often denoted by IFTI, this is what is used to create an instance of indexOf template) is not intelligent enough, try this.

+6
source

I believe this is a bug in std.algorithm . If you remove the immutable classifier, the code will work as is. I think indexOf / countUntil should work with immutable arrays, but at the moment this is not the case.

You can make them manifest constants (precede each declaration with enum ), and it seems to work. Interestingly, this could also be a mistake .

+4
source

Apologies for the breakdown; I introduced him. I agree with the dsimcha description and the proposed fix.

We are considering a simple language change to account for this simple case. This will automatically separate one qualifier level when passing a qualified type value to a function. Thus, the (currently hypothetical) rule, the qualifier (T []) will become (when passing the function) the qualifier (T) [], and the qualifier (T *) will become the classifier (T) *. This will allow your example to work. The disadvantage is that the function will not be able to distinguish the top-level qualifier, but I believe that this will not harm the specific use.

+3
source

All Articles