Swift 编译器错误:“表达式太复杂"在字符串连接上 [英] Swift Compiler Error: "Expression too complex" on a string concatenation

查看:33
本文介绍了Swift 编译器错误:“表达式太复杂"在字符串连接上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得这比什么都有趣.我已经解决了,但我想知道原因.这是错误:DataManager.swift:51:90:表达式太复杂,无法在合理的时间内解决;考虑将表达式分解为不同的子表达式.它为什么抱怨?这似乎是最简单的表达方式之一.

编译器指向columns + ");";部分

func tableName() ->字符串{返回(用户");}func createTableStatement(schema: [String]) ->细绳 {var 架构 = 架构;schema.append("id 字符串");schema.append("创建的整数");schema.append("更新整数");schema.append("model blob");var 列:String = ",".join(schema);var statement = "如果不存在则创建表" + self.tableName() + "(" + columns + ");";返回(声明);}

解决方法是:

var statement = "如果不存在则创建表" + self.tableName();语句 += "(" + 列 + ");";

这也有效(通过@efischency)但我不太喜欢它,因为我认为 ( 迷路了:

var statement = "如果不存在则创建表(self.tableName()) ((columns))"

解决方案

我不是编译器专家 - 我不知道这个答案是否会以一种有意义的方式改变你的思考方式",但我对编译器的理解问题是这样的:

它与类型推断有关.每次使用 + 运算符时,Swift 都必须搜索 + 的所有可能重载并推断您使用的是哪个版本的 +.我为 + 运算符计算了不到 30 个重载.这是很多可能性,当您将 4 或 5 个 + 操作链接在一起并要求编译器推断所有参数时,您所要求的比乍一看的要多得多.>

该推理可能会变得复杂 - 例如,如果您使用 + 添加一个 UInt8 和一个 Int,输出将是一个 Int,但有一些工作需要评估混合类型与运算符的规则.

当您使用文字时,例如示例中的 String 文字,编译器会执行将 String 文字转换为 String,然后为+操作符等做推断参数和返回类型的工作.

如果一个表达式足够复杂——也就是说,它需要编译器对参数和运算符进行过多的推断——它会退出并告诉你它退出了.

一旦表达式达到一定的复杂程度,就让编译器退出是有意的.另一种方法是让编译器尝试去做,看看它是否可以,但这是有风险的——编译器可能会一直尝试下去,陷入困境,或者只是崩溃.所以我的理解是,表达式的复杂度有一个静态阈值,编译器不会超过.

我的理解是 Swift 团队正在致力于编译器优化,以减少这些错误的发生.您可以通过点击此链接在 Apple 开发者论坛上了解一些相关信息.

在开发论坛上,Chris Lattner 要求人们将这些错误作为雷达报告提交,因为他们正在积极致力于修复这些错误.

在阅读了此处和 Dev 论坛上有关它的许多帖子后,我就是这样理解的,但是我对编译器的理解很幼稚,我希望对如何处理这些任务有更深入了解的人会扩展关于我在这里写的内容.

I find this amusing more than anything. I've fixed it, but I'm wondering about the cause. Here is the error: DataManager.swift:51:90: Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions. Why is it complaining? It seems like one of the most simple expressions possible.

The compiler points to the columns + ");"; section

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

the fix is:

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

this also works (via @efischency) but I don't like it as much because I think the ( get lost:

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

解决方案

I am not an expert on compilers - I don't know if this answer will "change how you think in a meaningful way," but my understanding of the problem is this:

It has to do with type inference. Each time you use the + operator, Swift has to search through all of the possible overloads for + and infer which version of + you are using. I counted just under 30 overloads for the + operator. That's a lot of possibilities, and when you chain 4 or 5 + operations together and ask the compiler to infer all of the arguments, you are asking a lot more than it might appear at first glance.

That inference can get complicated - for example, if you add a UInt8 and an Int using +, the output will be an Int, but there's some work that goes into evaluating the rules for mixing types with operators.

And when you are using literals, like the String literals in your example, the compiler doing the work of converting the String literal to a String, and then doing the work of infering the argument and return types for the + operator, etc.

If an expression is sufficiently complex - i.e., it requires the compiler to make too many inferences about the arguments and the operators - it quits and tells you that it quit.

Having the compiler quit once an expression reaches a certain level of complexity is intentional. The alternative is to let the compiler try and do it, and see if it can, but that is risky - the compiler could go on trying forever, bog down, or just crash. So my understanding is that there is a static threshold for the complexity of an expression that the compiler will not go beyond.

My understanding is that the Swift team is working on compiler optimizations that will make these errors less common. You can learn a little bit about it on the Apple Developer forums by clicking on this link.

On the Dev forums, Chris Lattner has asked people to file these errors as radar reports, because they are actively working on fixing them.

That is how I understand it after reading a number of posts here and on the Dev forum about it, but my understanding of compilers is naive, and I am hoping that someone with a deeper knowledge of how they handle these tasks will expand on what I have written here.

这篇关于Swift 编译器错误:“表达式太复杂"在字符串连接上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆