IT박스

신속한 컴파일러 오류 : 문자열 연결에서“표현이 너무 복잡합니다”

itboxs 2020. 6. 22. 08:07
반응형

신속한 컴파일러 오류 : 문자열 연결에서“표현이 너무 복잡합니다”


나는 이것이 무엇보다 재미있는 것을 발견합니다. 문제를 해결했지만 원인이 궁금합니다. 오류는 다음과 같습니다 DataManager.swift:51:90: Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions.. 왜 불평합니까? 가능한 가장 간단한 표현 중 하나 인 것 같습니다.

컴파일러는 columns + ");";섹션을 가리 킵니다.

func tableName() -> String { return("users"); } 

func createTableStatement(schema: [String]) -> String {

    var schema = schema;

    schema.append("id string");
    schema.append("created integer");
    schema.append("updated integer");
    schema.append("model blob");

    var columns: String = ",".join(schema);

    var statement = "create table if not exists " + self.tableName() + "(" + columns + ");";

    return(statement);
}

수정 사항은 다음과 같습니다.

var statement = "create table if not exists " + self.tableName();
statement += "(" + columns + ");";

이것은 (@efischency를 통해) 작동하지만 (잃어버린 것으로 생각하기 때문에 좋아하지 않습니다 .

var statement = "create table if not exists \(self.tableName()) (\(columns))"


나는 컴파일러 전문가가 아닙니다-이 답변이 "의미있는 방식으로 생각하는 방식을 바꿀 것"인지 모르겠지만 문제에 대한 나의 이해는 다음과 같습니다.

형식 유추와 관련이 있습니다. +연산자 를 사용할 때마다 Swift는 가능한 모든 과부하를 검색 하여 사용 +중인 버전을 추론 +해야합니다. +운영자에게 과부하가 30 회 미만인 것으로 계산했습니다 . 그것은 많은 가능성이며, 4 또는 5 개의 +연산을 함께 묶고 컴파일러가 모든 인수를 유추하도록 요청하면 언뜻보기에 더 많은 것을 요구합니다.

이러한 추론은 복잡해질 수 있습니다. 예를 들어 a UInt8Intusing 을 추가 +하면 출력이 Int되지만 유형을 연산자와 혼합하는 규칙을 평가하는 작업이 있습니다.

그리고 String예제에서 리터럴과 같은 리터럴을 사용할 때 컴파일러는 String리터럴을 로 변환 String하는 작업을 수행 한 다음 +연산자 의 인수 및 반환 유형을 유추하는 작업을 수행합니다 .

식이 충분히 복잡한 경우 (즉, 컴파일러가 인수 및 연산자에 대해 너무 많은 추론을 요구해야 함) 종료하고 종료한다고 알려줍니다.

식이 특정 수준의 복잡성에 도달하면 컴파일러를 종료하는 것은 의도적 인 것입니다. 대안은 컴파일러가 시도하고 수행하도록하고 가능한지 확인하는 것입니다. 그러나 위험합니다. 컴파일러는 영원히 시도하거나, 멈출 수 있으며, 충돌 할 수 있습니다. 그래서 내 이해는 컴파일러가 넘어 설 수없는 표현의 복잡성에 대한 정적 임계 값이 있다는 것입니다.

내 이해는 Swift 팀이 이러한 오류를 덜 일반적으로 만드는 컴파일러 최적화 작업을하고 있다는 것입니다. 이 링크를 클릭하면 Apple 개발자 포럼에서 약간 배울 수 있습니다 .

개발자 포럼에서 Chris Lattner는 이러한 오류를 적극적으로 해결하기 위해이 오류를 레이더 보고서로 제출하도록 요청했습니다.

그것이 여기와 Dev 포럼에서 많은 게시물을 읽은 후에 그것을 이해하는 방법이지만 컴파일러에 대한 나의 이해는 순진하며, 그들이이 작업을 처리하는 방법에 대한 더 깊은 지식을 가진 사람이 내가 무엇을 확장 할 수 있기를 바랍니다. 여기에 썼습니다.


이것은 수락 된 답변과 거의 동일하지만 대화가 추가되었습니다 (Rob Napier, 그의 다른 답변 및 Cocoahead 모임의 다른 친구와 함께했습니다) 및 링크.

토론 의 의견을 참조하십시오 . 그것의 요지는 :

+연산자는 당신이 4 문자열 즉 합치되도록 경우 27 개 다른 기능을 가지고 현재로서는 크게는 3 개가, 과부하 +컴파일러가하는 사업자 확인 즉 27 ^ 3 번, 그래서 27 개 사업자마다 사이를. 그러나 그것은 아닙니다.

도있다 체크 있는지 lhsrhs+기능들이는 핵심에 통해 호출하는 경우 모두 유효 append라고는. 거기에서 발생할 수있는 다소 집중적 인 검사많이 있습니다. 문자열이 비 연속적으로 저장되어 있다면, 다루고있는 문자열이 실제로 NSString에 연결되어있는 것처럼 보입니다. 그런 다음 Swift는 모든 바이트 배열 버퍼를 하나의 연속 된 버퍼로 다시 어셈블해야하며 그 과정에서 새 버퍼를 만들어야합니다. 그런 다음 결국 연결하려고하는 문자열이 포함 된 하나의 버퍼를 얻습니다.

간단히 말해 3 개의 컴파일러 검사 클러스터가있어 속도를 늦출 수 있습니다. 즉, 각 하위 표현식은 반환 있는 모든 것을 고려하여 다시 고려해야 합니다. 결과적으로 보간으로 문자열을 연결하는 것, 즉 보간에 과부하 가 없기 때문에 사용하는 " My fullName is \(firstName) \(LastName)"것이 훨씬 낫습니다."My firstName is" + firstName + LastName

Swift 3일부 개선되었습니다. 자세한 내용 은 컴파일러 속도를 늦추지 않고 여러 배열을 병합하는 방법을 참조하십시오 . . 그럼에도 불구하고 +연산자는 여전히 과부하 상태이며 더 긴 문자열에는 문자열 보간을 사용하는 것이 좋습니다


SO에 Rob Napier의 다른 유사한 답변 :

왜 문자열 추가에 시간이 오래 걸립니까?

컴파일러 속도를 늦추지 않고 여러 배열을 병합하는 방법은 무엇입니까?

스위프트 어레이는 빌드 시간을 길게하는 기능을 포함합니다.


당신이 무슨 말을하든 이것은 우스운 일입니다! :)

여기에 이미지 설명을 입력하십시오

그러나 이것은 쉽게 전달됩니다.

return "\(year) \(month) \(dayString) \(hour) \(min) \(weekDay)"

비슷한 문제가있었습니다.

expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions

Xcode 9.3 줄에서 다음과 같습니다.

let media = entities.filter { (entity) -> Bool in

다음과 같이 변경 한 후 :

let media = entities.filter { (entity: Entity) -> Bool in

모든 것이 잘되었습니다.

아마도 Swift 컴파일러와 코드 관련 데이터 유형을 유추하려고하는 것과 관련이 있습니다.

참고 URL : https://stackoverflow.com/questions/29707622/swift-compiler-error-expression-too-complex-on-a-string-concatenation

반응형