Я нахожу это забавным больше всего на свете. Я исправил это, но я задаюсь вопросом о причине. Здесь ошибка: 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))"
ios
xcode
swift
compiler-errors
functional-programming
Кендрик Тейлор
источник
источник
var statement = "create table if not exists \(self.tableName()) (\(columns))"
?+
.Ответы:
Я не эксперт по компиляторам - я не знаю, изменит ли этот ответ «значимое изменение вашего мышления», но мое понимание проблемы таково:
Это связано с выводом типа. Каждый раз, когда вы используете
+
оператор, Swift должен искать все возможные перегрузки+
и определять, какую версию+
вы используете. Я насчитал чуть менее 30 перегрузок для+
оператора. Это много возможностей, и когда вы+
объединяете 4 или 5 операций вместе и просите компилятор вывести все аргументы, вы запрашиваете гораздо больше, чем может показаться на первый взгляд.Этот вывод может усложниться - например, если вы добавите a
UInt8
иInt
использование+
, выходной результат будет aInt
, но есть некоторая работа по оценке правил смешивания типов с операторами.И когда вы используете литералы, такие как
String
литералы в вашем примере, компилятор выполняет преобразованиеString
литерала в aString
, а затем выводит аргументы и возвращаемые типы для+
оператора и т. Д.Если выражение достаточно сложное, т. Е. Требует, чтобы компилятор сделал слишком много выводов об аргументах и операторах, оно завершает работу и сообщает, что оно завершается.
Завершение работы компилятора, когда выражение достигает определенного уровня сложности, является намеренным. Альтернатива состоит в том, чтобы позволить компилятору попробовать и сделать это, и посмотреть, может ли это, но это рискованно - компилятор может продолжать пытаться вечно, зависать или просто падать. Поэтому я понимаю, что для сложности выражения существует статический порог, который компилятор не выйдет за пределы.
Насколько я понимаю, команда Swift работает над оптимизацией компилятора, которая сделает эти ошибки менее распространенными. Вы можете немного узнать об этом на форумах Apple Developer, нажав на эту ссылку .
На форумах Dev Крис Латтнер просил людей регистрировать эти ошибки как отчеты радаров, потому что они активно работают над их исправлением.
Вот как я понимаю это после прочтения ряда постов здесь и на форуме разработчиков об этом, но мое понимание компиляторов наивно, и я надеюсь, что кто-то с более глубоким знанием того, как они справляются с этими задачами, расширит то, что я написал здесь.
источник
Это почти то же самое, что принятый ответ, но с некоторым дополнительным диалогом (я имел с Робом Нейпиром, его другими ответами и Мэттом, Оливером, Дэвидом из Slack) и ссылками.
Смотрите комментарии в этой дискуссии. Суть этого:
+
сильно перегружен (в некоторых случаях Apple исправила это)+
Оператор сильно перегружен, как сейчас она имеет 27 различных функций , так что если вы конкатенация 4 строки , то есть у вас есть 3+
операторов, компилятор должен проверить между 27 операторами , каждый раз, так что 27 ^ 3 раза. Но это не так.Существует также проверка , чтобы увидеть , если
lhs
иrhs
из+
функций являются действительными , если они вызываются через к сердечникуappend
называется. Там вы можете увидеть несколько интенсивных проверок, которые могут произойти. Если строка хранится несмежно, что имеет место, если строка, с которой вы имеете дело, фактически соединена с NSString. Затем Swift должен собрать все буферы байтового массива в единый непрерывный буфер, который требует создания новых буферов. и затем вы в конечном итоге получите один буфер, содержащий строку, которую вы пытаетесь объединить вместе.В двух словах, есть 3 кластера проверок компилятора, которые замедляют работу, т. Е. Каждое подвыражение должно быть пересмотрено в свете всего, что оно может вернуть . В результате объединение строк с интерполяцией, т. Е. Использование
" My fullName is \(firstName) \(LastName)"
намного лучше, чем,"My firstName is" + firstName + LastName
поскольку интерполяция не имеет перегрузкиSwift 3 внесла некоторые улучшения. Для получения дополнительной информации прочитайте Как объединить несколько массивов без замедления компилятора? , Тем не менее,
+
оператор по-прежнему перегружен, и для более длинных строк лучше использовать интерполяцию строк.Использование опций (текущая проблема - решение доступно)
В этом очень простом проекте:
Время компиляции для функций таково:
Обратите внимание, насколько сумасшедшей является высокая продолжительность компиляции
concatenatedOptionals
.Это можно решить, выполнив:
который компилируется в
88ms
Основной причиной проблемы является то, что компилятор не идентифицирует
""
какString
. Это на самом делеExpressibleByStringLiteral
Компилятор увидит
??
и должен будет перебрать все типы, которые соответствуют этому протоколу , пока не найдет тип, который может быть значением по умолчаниюString
. ИспользуяemptyString
жестко запрограммированный кодString
, компилятору больше не нужно перебирать все соответствующие типыExpressibleByStringLiteral
Чтобы узнать, как регистрировать время компиляции, смотрите здесь или здесь
Другие подобные ответы Роба Нейпира на SO:
Почему сложение строк занимает так много времени?
Как объединить несколько массивов, не замедляя компилятор?
Swift Array содержит функцию, увеличивающую время сборки
источник
Это довольно нелепо, независимо от того, что вы говорите! :)
Но это легко проходит
источник
У меня была похожая проблема:
В Xcode 9.3 строка выглядит так:
После изменения в что-то вроде этого:
все получилось.
Возможно, это как-то связано с компилятором Swift, который пытается вывести тип данных из кода.
источник