Pertanyaan Perilaku aneh untuk enum rekursif di Swift (Beta 7)


enum Tree{
    case Leaf(String)
    case Node(Tree)
} //compiler not happy!!

enum Tree{
    case Leaf(String)
    case Node([Tree])
} //compiler is happy in (arguably) a more complex recursive scenario?

Bagaimana cara kerja kompiler Swift untuk skenario kedua (yang lebih kompleks) dan bukan yang pertama?


4
2017-09-03 20:58


asal


Jawaban:


Tipe nilai (enum) tidak dapat memuat dirinya sebagai anggota langsung, karena tidak peduli seberapa besar struktur data, ia tidak dapat menahan dirinya sendiri. Rupanya data terkait kasus enum dianggap anggota langsung enum, sehingga data yang terkait tidak dapat menjadi jenis enum itu sendiri. (Sebenarnya, saya berharap bahwa mereka akan membuat kerja enum rekursif; itu akan sangat bagus untuk struktur data fungsional.)

Namun, jika Anda memiliki tingkat tipuan, tidak apa-apa. Misalnya, data yang terkait dapat berupa objek (contoh kelas), dan kelas tersebut dapat memiliki anggota yang merupakan enum. Karena jenis kelas adalah tipe referensi, itu hanya sebuah pointer dan tidak secara langsung berisi objek (dan dengan demikian enum), jadi itu baik-baik saja.

Jawaban atas pertanyaan Anda adalah: [Tree] tidak mengandung Tree langsung sebagai anggota. Bidang-bidang Array bersifat pribadi, tetapi umumnya kami dapat menyimpulkan bahwa penyimpanan untuk elemen array tidak disimpan dalam Array struct secara langsung, karena struct ini memiliki ukuran yang tetap untuk yang diberikan Array<T>, tetapi array dapat memiliki jumlah elemen yang tidak terbatas.


3
2017-09-04 04:25



Perlu dicatat bahwa Swift 2 beta 2 dan lebih lanjut memiliki indirect kata kunci untuk enum rekursif - itu berarti

enum Tree<T> {
    case Leaf(T)
    indirect case Node(Tree)
}

adalah konstruk bahasa yang valid yang tidak memecah pencocokan pola di Swift 2.

TL; DR keputusan: "[…] kami memutuskan bahwa solusi yang tepat adalah tidak mendukung rekursi umum yang tidak jelas melalui enums, dan mengharuskan programmer untuk memediasi yang secara eksplisit dengan tidak langsung."



10
2018-06-10 21:30



Chris Lattner (perancang Swift) kata di forum Apple Developer itu autoclosure 

telah muncul sebagai cara untuk nilai ekspresi "kotak" dalam referensi (mis.   bekerja di sekitar batasan dengan enum rekursif).

Namun, kode berikut (yang berfungsi di Swift 1.1) tidak berfungsi di Swift 1.2 yang disertakan dengan Xcode Beta Versi 6.3 (6D520o). Pesan kesalahannya adalah "Atribut hanya dapat diterapkan pada deklarasi, bukan jenis", namun jika ini dimaksudkan, saya tidak tahu bagaimana cara mendamaikannya dengan pernyataan Lattner tentang perilaku yang dibicarakannya dalam kutipan sebelumnya sebagai "berguna hal, dan kami belum menghapusnya dengan Swift 1.2. "

enum BinaryTree {
    case Leaf(String)
    case Node(@autoclosure () -> BinaryTree, @autoclosure () -> BinaryTree)
}

let l1 = BinaryTree.Leaf("A")
let l2 = BinaryTree.Leaf("B")
let l3 = BinaryTree.Leaf("C")
let l4 = BinaryTree.Leaf("D")
let n1 = BinaryTree.Node(l1, l2)
let n2 = BinaryTree.Node(l3, l4)
let t = BinaryTree.Node(n1, n2)

1
2018-02-13 19:05