斯威夫特编译器错误:在一个字符串连接“表达式太复杂”斯威夫特编译器错误:在一个字符串连接“表达式太复

2019-05-10 12:09发布

我觉得比什么这个有趣的多。 我已经解决了,但我想了解一下原因。 以下是错误: 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 。 为什么抱怨? 这似乎是可能的最简单的表现之一。

编译器指向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))"

Answer 1:

我不是编译器专家 - 我不知道这个答案会“改变你怎么想以有意义的方式,”但我对这个问题的理解是这样的:

它与类型推断做。 每次使用的时间+操作,SWIFT已通过所有可能的重载搜索+和推断哪个版本+您正在使用。 我数了数,不到30个重载的+操作。 这是一个很大的可能性,当你用链条4个或5 +行动起来,并要求编译器来推断所有的参数,你问了很多比它初看上去一目了然。

这种推断可能很复杂-比如,如果添加UInt8Int使用+ ,输出将是一个Int ,但有一些进入评估的规则与运营商的混合类型的工作。

当您使用文字,就像String在您的示例文本,编译器做转换工作String字面的String ,然后做infering论证的工作,返回类型为+运营商等

如果一个表达式是非常复杂 - 也就是说,它需要编译器对这些参数,并且运营商太多的推论 - 它退出,告诉你它退出。

已经戒烟编译器一旦达到表达复杂的一定水平是故意的。 另一种方法是让编译器尝试做,看看是可以的,但是这是有风险的 - 编译器可以去尝试永远陷入瘫痪,或只是崩溃。 所以我的理解是,没有为编译器将无法超越的表达的复杂静态阈值。

我的理解是,斯威夫特团队正在编译器优化,这将使这些错误不太常见。 您可以通过点击此链接,了解它在苹果开发者论坛上一点点 。

在开发论坛,克里斯·拉特纳已经请人提交这些错误雷达报告,因为他们正在积极的将它们固定工作。

这是我的理解在这里读了一些帖子后,在对开发论坛这件事,但我的编译器的理解是不懂事,我希望有人与他们如何处理这些任务将扩大在更深入地了解我在这里写的。



Answer 2:

这是公认的答案,但增加了一些对话(我曾与罗布纳皮尔,他的其他的答案,并从Cocoahead聚会的另一位朋友)和链接几乎相同。

看到在评论这一讨论。 它的主要内容是:

+运营商的负荷过重,截至目前有27个不同的功能,所以如果你是串联4串,即你有3个+运营商的编译器,每次27个运营商之间的检查 ,所以这是27 ^ 3倍。 但是,这不是它。

还有一个检查 ,看看是否lhsrhs+功能,如果他们是它调用通过核心的两个有效的append调用。 在那里,你可以看到有一些稍微密集的检查可能发生。 如果字符串存储非连续,如果你正在处理字符串实际上是桥接的NSString这似乎是这样的。 迅速于是具有到所有的字节数组缓冲器重新装配成单一的连续缓冲器,并且需要创建沿途新的缓冲区。 然后你最终得到一个包含你正在试图串连在一起字符串一个缓冲区。

概括地说有编译器检查,这将减慢你的速度,即每个子表达式在一切可能返回的光重新考虑的3个集群。 其结果是连接在一起而插串即使用" My fullName is \(firstName) \(LastName)"是不是要好得多"My firstName is" + firstName + LastName ,因为插具有任何超载

斯威夫特3做了一些改进。 欲了解更多信息,请阅读如何合并多个阵列不会降低编译下来?


其它类似的答案由罗布·纳皮尔对SO:

为什么字符串除了需要很长时间来打造?

如何合并多个阵列不会降低编译下来?

斯威夫特数组包含功能,使建立时间长



Answer 3:

这是挺可笑的,无论你说什么! :)

不过这样会轻松通过

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


Answer 4:

我有类似的问题:

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 Compiler Error: “Expression too complex” on a string concatenation