2015-04-17 17 views
113

Tôi thấy điều này thú vị hơn bất cứ thứ gì. Tôi đã sửa nó, nhưng tôi tự hỏi về nguyên nhân. Đây là lỗi: DataManager.swift:51:90: Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions. Tại sao nó phàn nàn? Nó có vẻ giống như một trong những biểu thức đơn giản nhất có thể.Lỗi trình biên dịch Swift: "Biểu thức quá phức tạp" trên một chuỗi nối

Những điểm biên dịch đến phần 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); 
} 

việc sửa chữa là:

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

này cũng làm việc (thông qua @efischency) nhưng tôi không thích nó càng nhiều bởi vì tôi nghĩ rằng ( bị mất:

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

+9

Bạn có thấy nếu làm việc này: 'var tuyên bố = "tạo bảng nếu không tồn tại \ (self.tableName()) (\ (cột)) "'? – efischency

+5

Nội suy chuỗi, theo khuyến cáo của @efischency, thường là một lựa chọn tốt hơn so với nối thủ công với '+'. – mattt

+5

Chắc chắn, nhưng đó không phải là vấn đề. Tôi không quan tâm nếu đó là "đề nghị" cách hay không, tôi chỉ muốn biết tại sao trình biên dịch cuộn cảm trên đó. Tôi có một giải pháp hoạt động, nó không phải là về sửa chữa lỗi, nó là về sự hiểu biết lỗi. –

Trả lời

141

Tôi không phải là chuyên gia về trình biên dịch - Tôi không biết câu trả lời này có "thay đổi cách bạn suy nghĩ theo cách có ý nghĩa hay không", nhưng sự hiểu biết của tôi về vấn đề là:

Nó phải làm với suy luận kiểu. Mỗi khi bạn sử dụng toán tử +, Swift đã tìm kiếm thông qua tất cả các quá tải có thể cho + và suy ra phiên bản + bạn đang sử dụng. Tôi chỉ đếm dưới 30 tình trạng quá tải cho nhà điều hành +. Đó là rất nhiều khả năng, và khi bạn chuỗi 4 hoặc 5 + hoạt động cùng nhau và yêu cầu trình biên dịch để suy ra tất cả các đối số, bạn đang yêu cầu nhiều hơn nó có thể xuất hiện ở cái nhìn đầu tiên.

suy luận đó có thể trở nên phức tạp - ví dụ, nếu bạn thêm một UInt8 và một Int sử dụng +, sản lượng sẽ là một Int, nhưng có một số công việc mà đi vào đánh giá các quy tắc để pha trộn các loại với các nhà khai thác.

Và khi bạn đang sử dụng literals, giống như String literals trong ví dụ của bạn, trình biên dịch làm công việc chuyển đổi các String đen đến một String, và sau đó làm công việc của infering đối số và kiểu trả về cho các nhà điều hành +, ...

Nếu một biểu thức đủ phức tạp - nghĩa là, nó yêu cầu trình biên dịch tạo ra quá nhiều suy luận về các đối số và toán tử - nó thoát và cho bạn biết rằng nó thoát.

Có trình biên dịch bỏ từng là một biểu đạt đến một mức độ nhất định của sự phức tạp là có chủ ý. Cách khác là để cho trình biên dịch thử và làm điều đó, và xem nếu nó có thể, nhưng đó là rủi ro - trình biên dịch có thể tiếp tục cố gắng mãi mãi, bog xuống, hoặc chỉ sụp đổ. Vì vậy, sự hiểu biết của tôi là có một ngưỡng tĩnh cho sự phức tạp của một biểu thức mà trình biên dịch sẽ không đi xa hơn.

sự hiểu biết của tôi là đội Swift đang nghiên cứu tối ưu hóa trình biên dịch sẽ làm cho các lỗi này ít phổ biến hơn. You can learn a little bit about it on the Apple Developer forums by clicking on this link.

Trên các diễn đàn Dev, Chris Lattner đã yêu cầu người nộp các lỗi như các báo cáo radar, bởi vì họ đang tích cực làm việc trên sửa chữa chúng. Đó là làm thế nào tôi hiểu nó sau khi đọc một số bài viết ở đây và trên diễn đàn Dev về nó, nhưng sự hiểu biết của tôi về trình biên dịch là ngây thơ, và tôi hy vọng rằng ai đó có kiến ​​thức sâu hơn về cách họ xử lý các nhiệm vụ này sẽ như thế nào mở rộng những gì tôi đã viết ở đây.

+0

Tôi đã tìm ra điều gì đó cho hiệu ứng đó, nhưng đó là một câu trả lời hữu ích không kém. Cảm ơn bạn đã trả lời. Bạn đã đếm số + toán tử bằng tay hay là có một số cách khéo léo mà tôi không biết? –

+0

Tôi vừa xem qua nó trên SwiftDoc.org và đếm chúng bằng tay. Đây là trang tôi đang nói về: http://swiftdoc.org/operator/pls/ –

+13

Đây là một lỗi, bất kể họ sẽ gọi nó như thế. Các trình biên dịch ngôn ngữ khác không có vấn đề với mã tương tự với những gì đã được đăng. Đề nghị người dùng cuối nên sửa nó là ngớ ngẩn. – John

25

Điều này gần như giống như câu trả lời được chấp nhận nhưng với một số cuộc đối thoại bổ sung (tôi đã có Rob Napier và một người bạn khác từ cuộc họp mặt Cocoahead) và liên kết.

Xem nhận xét trong cuộc thảo luận this. Các ý chính của nó là:

các + operator là nặng nề quá tải, tính đến bây giờ nó có 27 chức năng khác nhau vì vậy nếu bạn đang concatenating 4 chuỗi tức là bạn có 3 + khai thác trình biên dịch đã séc giữa 27 nhà khai thác mỗi lần, đó là 27^3 lần. Nhưng đó không phải là nó.

Ngoài ra còn có một check để xem nếu lhsrhs của + chức năng đều có giá trị nếu chúng nó gọi qua để cốt lõi append gọi. Ở đó bạn có thể thấy có một số lượng checks có thể xảy ra. Nếu chuỗi được lưu trữ không liên tục, có vẻ như trường hợp nếu chuỗi bạn đang xử lý thực sự được bắc cầu đến NSString. Swift sau đó phải tập hợp lại tất cả các bộ đệm mảng byte thành một bộ đệm liền kề và yêu cầu tạo các bộ đệm mới trên đường đi. và sau đó bạn sẽ nhận được một bộ đệm chứa chuỗi bạn đang cố gắng ghép nối với nhau.

Tóm lại có 3 cụm kiểm tra trình biên dịch sẽ làm chậm bạn xuống và do đó concatenating dây với suy tức là sử dụng " My fullName is \(firstName) \(LastName)" là tốt hơn nhiều so "My firstName is" + firstName + LastName kể từ khi suy không có bất kỳ quá tải

Swift 3 đã thực hiện một số cải tiến. Để biết thêm thông tin đọc How to merge multiple Arrays without slowing the compiler down?

0

Tôi có vấn đề tương tự:

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

Trong Xcode 9,3 dòng đi như thế này:

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

Sau khi thay đổi nó thành một cái gì đó như thế này:

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

mọi thứ đã diễn ra.

Có lẽ nó có liên quan đến trình biên dịch Swift cố gắng loại bỏ kiểu dữ liệu từ mã xung quanh.

0

Điều này khá lố bịch cho dù bạn nói gì đi chăng nữa! :) enter image description here

Nhưng điều này được thông qua một cách dễ dàng,

return "\(year) \(month) \(dayString) \(hour) \(min) \(weekDay)" 
Các vấn đề liên quan