Acho isso divertido mais do que tudo. Eu consertei, mas estou me perguntando sobre a 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
. Por que está reclamando? Parece uma das expressões mais simples possíveis.
O compilador aponta para a 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 não gosto muito porque acho que eles (
se perdem:
var statement = "create table if not exists \(self.tableName()) (\(columns))"
ios
xcode
swift
compiler-errors
functional-programming
Kendrick Taylor
fonte
fonte
var statement = "create table if not exists \(self.tableName()) (\(columns))"
:?+
.Respostas:
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+
e inferir qual versão+
você está usando. Contei pouco menos de 30 sobrecargas para o+
operador. São muitas possibilidades e, quando você+
une 4 ou 5 operações 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 umInt
uso+
, a saída será umInt
, mas há algum trabalho para avaliar as regras para misturar tipos com operadores.E quando você está usando literais, como os
String
literais do seu exemplo, o compilador realiza o trabalho de converter oString
literal em umString
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 o 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.
fonte
Isso é quase o mesmo que a resposta aceita, mas com alguns diálogos adicionais (tive com Rob Napier, suas outras respostas e Matt, Oliver, David do Slack) e links.
Veja os comentários nesta discussão. A essência disso é:
+
está sobrecarregado (a Apple parece ter corrigido isso em alguns casos)O
+
operador está sobrecarregado, a partir de agora 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 verificação para ver se o
lhs
erhs
das+
funções são válidos se forem chama até o núcleo daappend
chamada. Lá você pode ver que existem várias verificações 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 do que"My firstName is" + firstName + LastName
uma vez que a interpolação não possui sobrecargaO 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 longosUso de opcionais (problema contínuo - solução disponível)
Neste projeto muito simples:
O tempo de compilação para as funções é o seguinte:
Observe o quão louca é a duração da compilação
concatenatedOptionals
.Isso pode ser resolvido fazendo:
que compila em
88ms
A causa raiz do problema é que o compilador não identifica o
""
como aString
. É realmenteExpressibleByStringLiteral
O compilador verá
??
e precisará percorrer todos os tipos que estão em conformidade com este protocolo , até encontrar um tipo que possa ser o padrãoString
. Ao usar oemptyString
código codificadoString
, o compilador não precisa mais percorrer todos os tipos conformes deExpressibleByStringLiteral
Para saber como registrar os tempos de compilação, veja aqui ou aqui
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
fonte
Isso é bastante ridículo, não importa o que você diga! :)
Mas isso é passado facilmente
fonte
Eu tive um problema semelhante:
No Xcode 9.3, a linha é assim:
Depois de mudar para algo assim:
tudo deu certo.
Provavelmente tem algo a ver com o compilador Swift tentando inferir o tipo de dados do código ao redor.
fonte