Saya menemukan ini lucu lebih dari apa pun. Saya sudah memperbaikinya, tapi saya bertanya-tanya tentang penyebabnya. Berikut adalah kesalahan: DataManager.swift:51:90: Expression was too complex to be solved in reasonable time; consider breaking up the expression into distinct sub-expressions
. Mengapa itu mengeluh? Sepertinya salah satu ungkapan paling sederhana yang mungkin.
Kompilator menunjuk ke columns + ");";
bagian
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);
}
Cara mengatasinya adalah:
var statement = "create table if not exists " + self.tableName();
statement += "(" + columns + ");";
ini juga berfungsi (via @fischency) tetapi saya tidak terlalu menyukainya karena saya pikir yang (
hilang:
var statement = "create table if not exists \(self.tableName()) (\(columns))"
ios
xcode
swift
compiler-errors
functional-programming
Kendrick Taylor
sumber
sumber
var statement = "create table if not exists \(self.tableName()) (\(columns))"
:?+
.Jawaban:
Saya bukan ahli kompiler - saya tidak tahu apakah jawaban ini akan "mengubah cara Anda berpikir dengan cara yang bermakna," tetapi pemahaman saya tentang masalahnya adalah ini:
Ini ada hubungannya dengan inferensi tipe. Setiap kali Anda menggunakan
+
operator, Swift harus mencari semua kemungkinan kelebihan+
dan menyimpulkan versi yang+
Anda gunakan. Saya menghitung di bawah 30 kelebihan untuk+
operator. Itu banyak kemungkinan, dan ketika Anda rantai 4 atau 5+
operasi bersama dan meminta kompiler untuk menyimpulkan semua argumen, Anda meminta lebih banyak daripada yang mungkin muncul pada pandangan pertama.Kesimpulan itu bisa menjadi rumit - misalnya, jika Anda menambahkan
UInt8
danInt
menggunakan+
, hasilnya akan menjadiInt
, tetapi ada beberapa pekerjaan yang digunakan untuk mengevaluasi aturan untuk mencampur jenis dengan operator.Dan ketika Anda menggunakan literal, seperti
String
literal dalam contoh Anda, kompiler melakukan pekerjaan mengubahString
literal menjadi aString
, dan kemudian melakukan pekerjaan menyimpulkan argumen dan mengembalikan tipe untuk+
operator, dll.Jika sebuah ekspresi cukup kompleks - yaitu, ia membutuhkan kompiler untuk membuat terlalu banyak kesimpulan tentang argumen dan operator - itu berhenti dan memberitahu Anda bahwa itu berhenti.
Membuat kompiler berhenti setelah ekspresi mencapai tingkat kompleksitas tertentu disengaja. Alternatifnya adalah membiarkan kompiler mencoba dan melakukannya, dan melihat apakah itu bisa, tetapi itu berisiko - kompiler dapat terus mencoba selamanya, macet, atau hanya crash. Jadi pemahaman saya adalah bahwa ada ambang statis untuk kompleksitas ekspresi yang tidak akan dikompilasi oleh kompiler.
Pemahaman saya adalah bahwa tim Swift sedang mengerjakan optimisasi kompiler yang akan membuat kesalahan ini lebih jarang terjadi. Anda dapat belajar sedikit tentang hal itu di forum Apple Developer dengan mengklik link ini .
Di forum Dev, Chris Lattner telah meminta orang untuk melaporkan kesalahan ini sebagai laporan radar, karena mereka secara aktif bekerja untuk memperbaikinya.
Itulah bagaimana saya memahaminya setelah membaca sejumlah posting di sini dan di forum Dev tentang hal itu, tetapi pemahaman saya tentang kompiler adalah naif, dan saya berharap bahwa seseorang dengan pengetahuan yang lebih dalam tentang bagaimana mereka menangani tugas-tugas ini akan memperluas apa yang saya telah menulis di sini.
sumber
Ini hampir sama dengan jawaban yang diterima tetapi dengan beberapa dialog tambahan (saya miliki dengan Rob Napier, jawaban lainnya dan Matt, Oliver, David dari Slack) dan tautan.
Lihat komentar dalam diskusi ini . Intinya adalah:
+
sangat kelebihan beban (Apple tampaknya telah memperbaiki ini untuk beberapa kasus)The
+
Operator ini sangat kelebihan beban, seperti yang sekarang memiliki 27 fungsi yang berbeda jadi jika Anda concatenating 4 senar yaitu Anda memiliki 3+
operator compiler harus memeriksa antara 27 operator setiap kali, jadi itu 27 ^ 3 kali. Tapi bukan itu.Ada juga cek untuk melihat apakah
lhs
danrhs
dari+
fungsi keduanya berlaku jika mereka itu panggilan melalui ke intiappend
disebut. Di sana Anda dapat melihat ada sejumlah pemeriksaan agak intensif yang dapat terjadi. Jika string disimpan secara tidak bersamaan, yang tampaknya menjadi kasus jika string yang Anda hadapi sebenarnya dijembatani ke NSString. Swift kemudian harus merakit kembali semua buffer array byte menjadi buffer yang berdekatan dan yang membutuhkan membuat buffer baru di sepanjang jalan. dan akhirnya Anda mendapatkan satu buffer yang berisi string yang Anda coba gabungkan bersama.Singkatnya ada 3 kelompok pemeriksaan kompiler yang akan memperlambat Anda yaitu masing-masing sub-ekspresi harus dipertimbangkan kembali mengingat segala hal yang mungkin kembali . Alhasil string yang disatukan dengan interpolasi yaitu menggunakan
" My fullName is \(firstName) \(LastName)"
jauh lebih baik daripada"My firstName is" + firstName + LastName
karena interpolasi tidak memiliki kelebihanSwift 3 telah membuat beberapa peningkatan. Untuk informasi lebih lanjut, baca Bagaimana cara menggabungkan banyak Array tanpa memperlambat kompiler? . Meskipun demikian
+
operator masih kelebihan beban dan lebih baik menggunakan interpolasi string untuk string yang lebih lamaPenggunaan opsional (masalah berkelanjutan - solusi tersedia)
Dalam proyek yang sangat sederhana ini:
Waktu kompilasi untuk fungsi adalah sebagai berikut:
Perhatikan betapa gila durasi kompilasi
concatenatedOptionals
ini.Ini dapat diselesaikan dengan melakukan:
yang mengkompilasi di
88ms
Akar penyebab masalah adalah bahwa kompiler tidak mengidentifikasi
""
sebagai aString
. SebenarnyaExpressibleByStringLiteral
Compiler akan melihat
??
dan harus mengulang semua tipe yang sesuai dengan protokol ini , sampai ia menemukan tipe yang dapat menjadi defaultString
. Dengan MenggunakanemptyString
hardcodedString
, kompiler tidak perlu lagi mengulang semua tipe yang sesuaiExpressibleByStringLiteral
Untuk mempelajari cara mencatat waktu kompilasi, lihat di sini atau di sini
Jawaban serupa lainnya oleh Rob Napier di SO:
Mengapa penambahan string membutuhkan waktu lama untuk dibangun?
Bagaimana cara menggabungkan banyak Array tanpa memperlambat kompiler?
Swift Array berisi fungsi membuat waktu build menjadi panjang
sumber
Ini sangat konyol tidak peduli apa yang Anda katakan! :)
Tapi ini bisa dilewati dengan mudah
sumber
Saya memiliki masalah serupa:
Dalam Xcode 9.3 baris berbunyi seperti ini:
Setelah mengubahnya menjadi seperti ini:
semuanya berhasil.
Mungkin ada hubungannya dengan kompiler Swift yang mencoba menyimpulkan tipe data dari kode sekitar.
sumber