2011-03-31 2 views
7

converting Arabic and Roman numerals의 작업에 대해 rosettacode.org에 다음 코드를 게시했습니다.D2 : std.algorithm.indexOf가 더 이상 작동하지 않음

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; 
} 

이전에는 잘 작동했지만 이전에는 컴파일러 오류가 발생했습니다. 설명서 같이 IndexOf에 따르면

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

는 사용되지 않으며 countUntil는 대신에 사용되어야하지만, 나에게 같은 오류를 제공합니다.

답변

6

긴 이야기하지만 짧게 유지하려고합니다 :

std.algorithm.indexOffront, popFront()empty를 정의해야 structural typeinput range를 기대하고있다. 배열의 경우이 메서드는 defined in std.array이고 균일 함수 호출 구문을 통해 작업하므로 fun(someArray)someArray.fun()과 동일하게 작동합니다.

immutable string[]은 입력 범위가 아닙니다. popFront은 배열의 첫 번째 요소를 제거하기 때문에 변경 불가능한 형식에서는 수행 할 수 없습니다. 이것이 작동하는데 사용 된 사실은 버그였습니다.

로시타 코드 항목을 symbols으로 변경하여 immutable(string)[]으로 업데이트했습니다. 여기에서 symbols의 요소는 변경할 수 없지만 배열을 슬라이스하여 다시 할당 할 수 있습니다. 예를 들어 :

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[]immutable(string)[]하지만, 암시 적 기능 템플릿 인스턴스화에 암시 적으로 변환입니다 (종종 IFTI이 표시, 이것이 indexOf 템플릿을 인스턴스화하는 데 사용 어떤 것은)이 시도 똑똑하지 않다.

+0

입니다. 불변의 콜렉션에있는 요소의 색인을 얻는 방법이 있습니까? 아니면 배열을 캡슐화하고 비공개로 만들고 접근자를 만들고 내 자신의 indexOf를 굴려야합니까? – fwend

+0

@fwend : 지금 당장 가장 쉬운 방법은 머리를 변경할 수 있도록 변환하는 것입니다. 예를 들면 :'immutable (string) [] headMutable = symbols;','symbols' 대신에'headMutable'을 사용하여 할 일을하십시오. – dsimcha

+0

이 문제를 해결할 제안이 있습니까? 불변의 배열로'indexOf'를 사용할 수없는 것은 꽤 큰 문제입니다. –

4

나는 이것이 std.algorithm의 버그라고 생각합니다. immutable 한정자를 제거하면 코드는 그대로 작동합니다. I indexOf/countUntilimmutable 어레이에서 작동해야한다고 생각하지만 현재는 그렇지 않습니다.

상수를 (각 선언 앞에 enum으로 앞에 표시) 만들 수 있으며 제대로 작동하는 것 같습니다. Amusingly, this may also be a bug.

+0

불변 블록을 주석 처리했으며 현재 작동하지 않습니다. – fwend

3

파손에 대한 사과; 나는 그것을 소개했다. 나는 dsimcha의 설명 및 제안 된 수정 사항에 동의합니다.

이 간단한 사례를 설명하기 위해 언어를 간단하게 변경하는 것을 고려하고 있습니다. 그것은 한정된 타입의 값을 함수에 전달할 때 자동으로 하나의 한정자 레벨을 껍질을 벗기 게됩니다. 이 규칙에 의해 한정자 (T [])는 (함수에 전달 될 때) 한정자 (T) []가되고 한정자 (T *)는 한정자 (T) *가됩니다. 이것은 당신의보기가 작동하는 것을 허용 할 것입니다. 단점은 함수가 최상위 한정자를 구별 할 수 없지만 어떤 구체적인 사용에도 해를 끼치 지 않는다고 생각합니다.

+0

이것은'class' 유형과'struct'가'ref'에 의해 전달 된 것과 작동합니까? 'immutable'을 떼어 낼 수 없으면, 불변 객체가 갑자기 함수 내부에서 변경 될 수 있습니다. 이 가설적인 규칙은 물고기 같은 냄새가 나고 나중에 미묘한 방법으로 문제를 일으킬만한 종류의 소리가납니다. –

+0

@Peter : 먼저, Michel Fortin이 작성한 실험적 패치로 불변 클래스 개체에 대한 변경 가능한 참조를 소개합니다. 둘째, 사람들은 불변의 배열을 예를 들어 다음과 같이 저장하는 경향이있다. 정적 테이블을 자주 사용하지만 일반적으로 변경할 수없는 일반 범위를 조작하지는 않습니다. 즉, 나는 좀 더 일반적인 규칙이 바람직하다는 데 동의한다. –

관련 문제