ios - how - the swift programming language pdf




Erro do compilador Swift: “Expressão muito complexa” em uma concatenação de string (3)

Acho isso divertido mais do que tudo. Eu consertei, mas estou pensando na causa. Aqui está o erro: DataManager.swift:51:90: Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions DataManager.swift:51:90: Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions . Por que está reclamando? Parece uma das expressões mais simples possíveis.

O compilador aponta para as columns + ");"; seção

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

a correção é:

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

isso também funciona (via @efischency), mas eu não gosto muito porque acho que o ( se perca:

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


Eu tive um problema semelhante:

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

No Xcode 9.3, a linha é assim:

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

Depois de mudar para algo assim:

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

tudo deu certo.

Provavelmente tem algo a ver com o compilador Swift tentando inferir o tipo de dados do código ao redor.


Isso é quase o mesmo que a resposta aceita, mas com alguns diálogos adicionais (tive com Rob Napier, suas outras respostas e outro amigo de um encontro da Cocoahead) e links.

Veja os comentários this discussão. A essência disso é:

O operador + está sobrecarregado, a partir de agora ele possui 27 funções diferentes; portanto, se você estiver concatenando 4 strings, ou seja, você tem 3 + operadores, o compilador deve verificar entre 27 operadores a cada vez, ou seja, 27 ^ 3 vezes. Mas não é isso.

Há também uma check para ver se os lhs e rhs das funções + são válidos se forem chamados para o núcleo do append chamado. Lá você pode ver que existem várias checks intensivas que podem ocorrer. Se a sequência for armazenada de forma não contígua, o que parece ser o caso se a sequência com a qual você está lidando for realmente conectada ao NSString. O Swift precisa montar novamente todos os buffers da matriz de bytes em um único buffer contíguo, o que requer a criação de novos buffers ao longo do caminho. e, eventualmente, você obtém um buffer que contém a string que você está tentando concatenar juntos.

Em poucas palavras, existem três grupos de verificações do compilador que o atrasarão, ou seja, cada subexpressão deve ser reconsiderada à luz de tudo o que possa retornar . Como resultado, concatenar seqüências de caracteres com interpolação, ou seja, usar " My fullName is \(firstName) \(LastName)" é muito melhor que "My firstName is" + firstName + LastName pois a interpolação não possui sobrecarga

O Swift 3 fez algumas melhorias. Para obter mais informações, leia Como mesclar várias matrizes sem diminuir a velocidade do compilador? . No entanto, o operador + ainda está sobrecarregado e é melhor usar a interpolação de strings para strings mais longos

Outras respostas semelhantes de Rob Napier no SO:

Por que a adição de strings leva tanto tempo para construir?

Como mesclar várias matrizes sem diminuir a velocidade do compilador?

Swift Array contém a função que aumenta o tempo de construção


Não sou especialista em compiladores - não sei se essa resposta "mudará a maneira como você pensa de maneira significativa", mas meu entendimento do problema é o seguinte:

Tem a ver com inferência de tipo. Cada vez que você usa o operador + , o Swift precisa pesquisar todas as sobrecargas possíveis para + e inferir qual versão do + você está usando. Contei pouco menos de 30 sobrecargas para o operador + . São muitas possibilidades e, quando você agrupa operações 4 ou 5 + e pede ao compilador para inferir todos os argumentos, você está pedindo muito mais do que parece à primeira vista.

Essa inferência pode ser complicada - por exemplo, se você adicionar um UInt8 e um Int usando + , a saída será um Int , mas há algum trabalho para avaliar as regras para misturar tipos com operadores.

E quando você está usando literais, como os literais String no seu exemplo, o compilador faz o trabalho de converter o literal String em uma String e, em seguida, realiza o trabalho de inferir os argumentos e os tipos de retorno para o operador + , etc.

Se uma expressão é suficientemente complexa - ou seja, requer que o compilador faça muitas inferências sobre os argumentos e os operadores - ela sai e informa que foi encerrada.

Ter o compilador encerrado quando uma expressão atingir um certo nível de complexidade é intencional. A alternativa é deixar o compilador tentar fazê-lo e ver se pode, mas isso é arriscado - o compilador pode continuar tentando para sempre, atolar ou simplesmente travar. Portanto, meu entendimento é que existe um limite estático para a complexidade de uma expressão que o compilador não irá além.

Meu entendimento é que a equipe Swift está trabalhando em otimizações de compilador que tornarão esses erros menos comuns. Você pode aprender um pouco sobre isso nos fóruns de desenvolvedores da Apple, clicando neste link .

Nos fóruns de desenvolvimento, Chris Lattner pediu às pessoas para arquivar esses erros como relatórios de radar, porque eles estão trabalhando ativamente para corrigi-los.

É assim que eu entendo depois de ler várias postagens aqui e no fórum do Dev sobre isso, mas meu entendimento dos compiladores é ingênuo e espero que alguém com um conhecimento mais profundo de como eles lidam com essas tarefas expanda o que eu escrevi aqui.





functional-programming