Komentar pertama pada artikel yang indah
Visi Subjektif Bahasa Pemrograman Ideal ternyata menjadi referensi ke
bahasa pemrograman Zig . Tentu saja, menjadi menarik jenis bahasa apa yang mengklaim sebagai ceruk C ++, D dan Rust. Saya melihat - bahasanya tampak cantik dan agak menarik. Sintaks seperti si, pendekatan orisinal untuk penanganan kesalahan, coroutine bawaan. Artikel ini adalah ikhtisar singkat dari
dokumentasi resmi yang diselingi dengan pemikiran dan kesan mereka sendiri dari menjalankan contoh kode.
Memulai
Instalasi kompiler cukup sederhana, untuk Windows - cukup unzip paket distribusi ke beberapa folder. Kami membuat file teks hello.zig di folder yang sama, masukkan kode dari dokumentasi di sana dan simpan. Perakitan dilakukan dengan perintah
zig build-exe hello.zig
setelah itu hello.exe muncul di direktori yang sama.
Selain perakitan, mode pengujian unit tersedia, untuk ini, blok uji digunakan dalam kode, dan perakitan dan peluncuran tes dilakukan oleh perintah
zig test hello.zig
Keanehan pertama
Kompiler tidak mendukung jeda baris Windows (\ r \ n). Tentu saja, fakta bahwa line break di setiap sistem (Win, Nix, Mac) adalah beberapa dari mereka sendiri adalah keliaran dan peninggalan masa lalu. Tetapi tidak ada yang harus dilakukan, jadi pilih saja, misalnya, di Notepad ++ format yang Anda inginkan untuk kompiler.
Keanehan kedua yang saya alami secara tidak sengaja - tab tidak didukung dalam kode! Hanya spasi. Tapi itu terjadi :)
Namun, ini ditulis dengan jujur ​​dalam dokumentasi - kebenaran sudah ada di akhir.
Komentar
Keanehan lain adalah Zig tidak mendukung komentar multi-baris. Saya ingat bahwa semuanya dilakukan dengan benar dalam turbo pascal kuno - komentar multi-baris bersarang didukung. Rupanya, sejak itu tidak ada pengembang bahasa yang menguasai hal sederhana ini :)
Tetapi ada komentar dokumenter. Mulai dengan ///. Harus di tempat-tempat tertentu - di depan objek yang sesuai (variabel, fungsi, kelas ...). Jika mereka berada di tempat lain - kesalahan kompilasi. Tidak buruk.
Deklarasi variabel
Dilakukan dengan gaya modis sekarang (dan secara ideologis benar), ketika kata kunci (const atau var) ditulis terlebih dahulu, kemudian namanya, kemudian secara opsional jenisnya, dan kemudian nilai awal. Yaitu inferensi tipe otomatis tersedia. Variabel harus diinisialisasi - jika Anda tidak menentukan nilai awal, akan ada kesalahan kompilasi. Namun, nilai undefined khusus disediakan, yang dapat secara eksplisit digunakan untuk menentukan variabel yang tidak diinisialisasi.
var i:i32 = undefined;
Output konsol
Untuk percobaan, kita perlu output ke konsol - dalam semua contoh, ini adalah metode yang digunakan. Di bidang plug-in
const warn = std.debug.warn;
dan kodenya ditulis seperti ini:
warn("{}\n{}\n", false, "hi");
Kompiler memiliki beberapa bug, yang dengan jujur ​​dilaporkan ketika mencoba untuk mengeluarkan bilangan bulat atau angka floating-point dengan cara ini:
error: compiler bug: integer dan float literals dalam fungsi var args harus dicor. github.com/ziglang/zig/issues/557
Tipe data
Tipe primitif
Nama tipe rupanya diambil dari Rust (i8, u8, ... i128, u128), ada juga tipe khusus untuk kompatibilitas biner C, 4 tipe tipe floating-point (f16, f32, f64, f128). Ada tipe bool. Ada jenis nol panjang batal dan noreturn khusus, yang akan saya bahas nanti.
Anda juga bisa membuat tipe integer dengan panjang berapa pun dalam bit dari 1 hingga 65535. Nama tipe dimulai dengan huruf i atau u, dan kemudian panjang dalam bit ditulis.
// ! var j:i65535 = 0x0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF;
Namun, saya tidak bisa mendapatkan nilai ini ke konsol - kesalahan terjadi pada LLVM selama proses kompilasi.
Secara umum, ini adalah solusi yang menarik, meskipun ambigu (IMHO: mendukung literal angka yang persis panjang pada tingkat kompiler adalah benar, tetapi jenis penamaan dengan cara ini tidak terlalu baik, lebih baik melakukannya dengan jujur ​​melalui tipe templat). Dan mengapa batas 65535? Perpustakaan seperti GMP tampaknya tidak memaksakan pembatasan seperti itu?
Literal string
Ini adalah array karakter (tanpa akhir nol di akhir). Untuk literal dengan nol penghentian, awalan 'c' digunakan.
const normal_bytes = "hello"; const null_terminated_bytes = c"hello";
Seperti kebanyakan bahasa, Zig mendukung urutan pelarian standar dan menyisipkan karakter Unicode melalui kode mereka (\ uNNNN, \ UNNNNNNN di mana N adalah digit heksadesimal).
Literal multi-garis dibentuk menggunakan dua garis miring terbalik pada awal setiap baris. Tidak ada tanda kutip diperlukan. Artinya, beberapa upaya untuk membuat string mentah, tetapi IMHO tidak berhasil - keuntungan dari string mentah adalah Anda dapat menyisipkan bagian teks apa pun dari mana pun dalam kode - dan idealnya tidak mengubah apa pun, tetapi di sini Anda harus menambahkan \\ pada awal setiap baris.
const multiline = \\#include <stdio.h> \\ \\int main(int argc, char **argv) { \\ printf("hello world\n"); \\ return 0; \\} ;
Literal integer
Semuanya dalam bahasa si-like. Saya sangat senang bahwa untuk literal literal, awalan 0o digunakan, dan bukan hanya nol, seperti dalam C. Literal biner dengan awalan 0b juga didukung. Literal titik-mengambang dapat berbentuk heksadesimal (seperti yang dilakukan pada
ekstensi GCC ).
Operasi
Tentu saja, ada operasi aritmatika standar, logis dan bitwise C. Operasi singkat didukung (+ = dll.). Alih-alih && dan || kata kunci dan dan atau digunakan. Hal yang menarik adalah bahwa operasi dengan semantik sampul yang dijamin juga didukung. Mereka terlihat seperti ini:
a +% b a +%= b
Dalam kasus ini, operasi aritmatika biasa tidak menjamin luapan dan hasilnya selama luapan dianggap tidak terdefinisi (dan kesalahan kompilasi dihasilkan untuk konstanta). IMHO ini agak aneh, tetapi tampaknya itu dibuat dari beberapa pertimbangan kompatibilitas dengan semantik bahasa C.
Array
Literal array terlihat seperti ini:
const msg = []u8{ 'h', 'e', 'l', 'l', 'o' }; const arr = []i32{ 1, 2, 3, 4 };
String adalah array karakter, seperti dalam C. Indeksasi klasik dengan tanda kurung. Operasi penambahan (penggabungan) dan multiplikasi array disediakan. Ini adalah hal yang sangat menarik, dan jika semuanya jelas dengan penggabungan, maka penggandaan - saya terus menunggu sampai seseorang mengimplementasikan ini, dan sekarang saya menunggu :) Di Assembler (!) Ada operasi dup seperti yang memungkinkan Anda untuk menghasilkan data duplikat. Sekarang di Zig:
const one = []i32{ 1, 2, 3, 4 }; const two = []i32{ 5, 6, 7, 8 }; const c = one ++ two; // { 1,2,3,4,5,6,7,8 } const pattern = "ab" ** 3; // "ababab"
Pointer
Sintaksnya mirip dengan C.
var x: i32 = 1234; // const x_ptr = &x; //
Untuk dereferencing (mengambil nilai dengan pointer), operasi postfix yang tidak biasa digunakan:
x_ptr.* == 5678; x_ptr.* += 1;
Tipe pointer secara eksplisit diatur dengan menetapkan tanda bintang di depan nama tipe
const x_ptr : *i32 = &x;
Irisan (irisan)
Struktur data yang dibangun ke dalam bahasa yang memungkinkan Anda untuk referensi array atau bagian dari itu. Berisi pointer ke elemen pertama dan jumlah elemen. Ini terlihat seperti ini:
var array = []i32{ 1, 2, 3, 4 }; const slice = array[0..array.len];
Tampaknya diambil dari Go, tidak yakin. Dan saya juga tidak yakin apakah itu layak disematkan dalam bahasa, sementara implementasi dalam bahasa OOP seperti itu sangat mendasar.
Struktur
Cara yang menarik untuk mendeklarasikan struktur: konstanta dideklarasikan, tipe yang secara otomatis ditampilkan sebagai "tipe" (tipe), dan itu yang digunakan sebagai nama struktur. Dan struktur itu sendiri (struct) adalah "tanpa nama."
const Point = struct { x: f32, y: f32, };
Tidak mungkin untuk menentukan nama dengan cara yang biasa dalam bahasa seperti C, namun, kompilator menampilkan nama tipe sesuai dengan aturan tertentu - khususnya, dalam kasus yang dipertimbangkan di atas, itu akan bertepatan dengan nama konstanta "type".
Secara umum, bahasa tidak menjamin urutan bidang dan perataannya dalam memori. Jika jaminan diperlukan, maka struktur "paket" harus digunakan.
const Point2 = packed struct { x: f32, y: f32, };
Inisialisasi - dengan gaya desainer Sishny:
const p = Point { .x = 0.12, .y = 0.34, };
Struktur mungkin memiliki metode. Namun, menempatkan metode dalam struktur hanya menggunakan struktur sebagai namespace; tidak seperti C ++, tidak ada implisit parameter ini dilewatkan.
Transfer
Secara umum, sama seperti di C / C ++. Ada beberapa cara built-in yang nyaman untuk mengakses meta-informasi, misalnya, jumlah bidang dan namanya, diimplementasikan oleh makro sintaks yang dibangun ke dalam bahasa (yang disebut fungsi builtin dalam dokumentasi).
Untuk "kompatibilitas biner dengan C" beberapa enum eksternal disediakan.
Untuk menunjukkan jenis yang harus mendasari pencacahan, konstruksi bentuk
packed enum(u8)
di mana u8 adalah tipe dasar.
Enum dapat memiliki metode yang mirip dengan struktur (yaitu menggunakan nama enumerasi sebagai namespace).
Serikat pekerja
Seperti yang saya pahami, penyatuan dalam Zig adalah tipe-aljabar, yaitu berisi bidang tag tersembunyi yang menentukan bidang serikat mana yang "aktif". "Aktivasi" dari bidang lain dilakukan dengan penugasan ulang keseluruhan dari seluruh asosiasi. Contoh dokumentasi
const assert = @import("std").debug.assert; const mem = @import("std").mem; const Payload = union { Int: i64, Float: f64, Bool: bool, }; test "simple union" { var payload = Payload {.Int = 1234}; // payload.Float = 12.34; // ! assert(payload.Int == 1234); // payload = Payload {.Float = 12.34}; assert(payload.Float == 12.34); }
Serikat pekerja juga dapat secara eksplisit menggunakan enumerasi untuk tag.
// Unions can be given an enum tag type: const ComplexTypeTag = enum { Ok, NotOk }; const ComplexType = union(ComplexTypeTag) { Ok: u8, NotOk: void, };
Serikat pekerja, seperti enumerasi dan struktur, juga dapat menyediakan ruang nama mereka sendiri untuk metode.
Jenis opsional
Zig memiliki dukungan opsional bawaan. Tanda tanya ditambahkan sebelum nama jenis:
const normal_int: i32 = 1234; // normal integer const optional_int: ?i32 = 5678; // optional integer
Menariknya, Zig menerapkan satu hal tentang kemungkinan yang saya duga, tetapi tidak yakin apakah itu benar atau tidak. Pointer dibuat kompatibel dengan opsi tanpa menambahkan bidang tersembunyi tambahan ("tag"), yang menyimpan tanda validitas nilai; dan null digunakan sebagai nilai yang tidak valid. Dengan demikian, tipe referensi yang diwakili dalam Zig oleh pointer bahkan tidak memerlukan memori tambahan untuk "opsional". Pada saat yang sama, menetapkan nilai nol ke pointer reguler dilarang.
Jenis Kesalahan
Mereka mirip dengan tipe opsional, tetapi bukannya tag Boolean ("benar-benar tidak valid"), elemen enumerasi yang sesuai dengan kode kesalahan digunakan. Sintaksnya mirip dengan opsi, tanda seru ditambahkan alih-alih tanda tanya. Jadi, tipe-tipe ini dapat digunakan, misalnya, untuk kembali dari fungsi: baik objek-hasil dari operasi yang berhasil dari fungsi dikembalikan, atau kesalahan dengan kode yang sesuai dikembalikan. Jenis kesalahan adalah bagian penting dari sistem penanganan kesalahan bahasa Zig, untuk lebih jelasnya lihat bagian Penanganan Kesalahan.
Ketik batal
Variabel seperti void dan operasi dengan mereka dimungkinkan di Zig
var x: void = {}; var y: void = {}; x = y;
tidak ada kode yang dihasilkan untuk operasi tersebut; tipe ini sangat berguna untuk metaprogramming.
Ada juga tipe c_void untuk kompatibilitas C.
Kontrol Operator dan Fungsi
Ini termasuk: blok, saklar, sementara, untuk, jika, jika tidak, istirahat, terus Untuk mengelompokkan kode, tanda kurung keriting standar digunakan. Hanya blok, seperti dalam C / C ++, digunakan untuk membatasi ruang lingkup variabel. Blok dapat dianggap sebagai ekspresi. Tidak ada kebersamaan dalam bahasa tersebut, tetapi ada label yang dapat digunakan dengan pernyataan break dan continue. Secara default, operator ini bekerja dengan loop, namun, jika sebuah blok memiliki label, maka Anda dapat menggunakannya.
var y: i32 = 123; const x = blk: { y += 1; break :blk y; // blk y };
Pernyataan sakelar berbeda dari operator dalam hal ia tidak memiliki “kesalahan”, yaitu hanya satu kondisi (kasing) yang dieksekusi dan sakelar keluar. Sintaksnya lebih ringkas: alih-alih case, panah "=>" digunakan. Switch juga dapat dianggap sebagai ekspresi.
Pernyataan while dan if pada umumnya sama dengan semua bahasa mirip-C. Pernyataan for lebih seperti foreach. Semuanya dapat dianggap sebagai ekspresi. Dari fitur-fitur baru, sementara dan untuk, serta jika, dapat memiliki blok lain yang dijalankan jika tidak ada iterasi loop.
Dan inilah saatnya untuk berbicara tentang satu fitur umum untuk sakelar, sementara, yang dalam beberapa hal dipinjam dari konsep foreach loop - variabel "menangkap". Ini terlihat seperti ini:
while (eventuallyNullSequence()) |value| { sum1 += value; } if (opt_arg) |value| { assert(value == 0); } for (items[0..1]) |value| { sum += value; }
Di sini, argumen while adalah "sumber" data tertentu, yang dapat opsional, untuk, array atau irisan, dan variabel yang terletak di antara dua garis vertikal berisi nilai "diperluas" - yaitu, elemen saat ini dari array atau slice (atau pointer ke sana), nilai internal dari tipe opsional (atau pointer ke sana).
Tunda dan sesuaikan pernyataan
Pernyataan eksekusi yang ditangguhkan dipinjam dari Go. Cara kerjanya sama - argumen operator ini dieksekusi ketika meninggalkan ruang lingkup di mana operator digunakan. Selain itu, operator errdefer disediakan, yang dipicu jika jenis kesalahan dengan kode kesalahan aktif dikembalikan dari fungsi. Ini adalah bagian dari sistem penanganan kesalahan Zig asli.
Operator yang tidak terjangkau
Unsur pemrograman kontrak. Kata kunci khusus, yang diletakkan di tempat manajemen tidak boleh datang dalam keadaan apa pun. Jika tiba di sana, maka dalam mode Debug dan ReleaseSafe, panik dihasilkan, dan dalam ReleaseFast optimizer mengeluarkan cabang-cabang ini sepenuhnya.
noreturn
Secara teknis, ini adalah tipe yang kompatibel dalam ekspresi dengan tipe lainnya. Ini dimungkinkan karena kenyataan bahwa objek jenis ini tidak akan pernah kembali. Karena operator adalah ekspresi dalam Zig, tipe khusus diperlukan untuk ekspresi yang tidak akan pernah dievaluasi. Ini terjadi ketika sisi kanan ekspresi secara irrevocably mentransfer kontrol ke suatu tempat di luar. Untuk pernyataan seperti itu rusak, lanjutkan, kembali, loop yang tak terhingga, dan fungsi yang tak pernah kembali kontrol. Sebagai perbandingan, panggilan ke fungsi biasa (kontrol kembali) bukan operator noreturn, karena meskipun kontrol ditransfer ke luar, itu akan dikembalikan ke titik panggilan cepat atau lambat.
Dengan demikian, ekspresi berikut menjadi mungkin:
fn foo(condition: bool, b: u32) void { const a = if (condition) b else return; @panic("do something with a"); }
Variabel a mendapatkan nilai yang dikembalikan oleh pernyataan if / else. Untuk ini, bagian-bagian (baik jika dan yang lain) harus mengembalikan ekspresi dengan tipe yang sama. Bagian if mengembalikan bool, bagian lain adalah tipe noreturn, yang secara teknis kompatibel dengan tipe apa pun, sebagai hasilnya, kode dikompilasi tanpa kesalahan.
Fungsi
Sintaksnya klasik untuk bahasa jenis ini:
fn add(a: i8, b: i8) i8 { return a + b; }
Secara umum, fungsinya terlihat cukup standar. Sejauh ini saya belum melihat tanda-tanda fungsi kelas satu, tetapi kenalan saya dengan bahasa ini sangat dangkal, saya bisa saja salah. Meskipun mungkin ini belum dilakukan.
Fitur lain yang menarik adalah bahwa di Zig, mengabaikan nilai yang dikembalikan hanya dapat dilakukan secara eksplisit menggunakan garis bawah _
_ = foo();
Ada refleksi yang memungkinkan Anda mendapatkan berbagai informasi tentang fungsi tersebut
const assert = @import("std").debug.assert; test "fn reflection" { assert(@typeOf(assert).ReturnType == void); // assert(@typeOf(assert).is_var_args == false); // }
Eksekusi kode pada waktu kompilasi
Zig menyediakan fitur yang kuat - mengeksekusi kode yang ditulis dalam zig pada waktu kompilasi. Agar kode dapat dieksekusi pada waktu kompilasi, cukup bungkus dalam blok dengan kata kunci comptime. Fungsi yang sama dapat dipanggil baik pada waktu kompilasi maupun pada saat run, yang memungkinkan Anda untuk menulis kode universal. Tentu saja, ada beberapa batasan terkait dengan konteks kode yang berbeda. Misalnya, dalam dokumentasi dalam banyak contoh, waktu kompilasi digunakan untuk memeriksa waktu kompilasi:
// array literal const message = []u8{ 'h', 'e', 'l', 'l', 'o' }; // get the size of an array comptime { assert(message.len == 5); }
Tapi tentu saja kekuatan operator ini jauh dari diungkapkan sepenuhnya di sini. Jadi, dalam deskripsi bahasa, contoh klasik dari penggunaan efektif sintaksis makro diberikan - implementasi fungsi yang mirip dengan printf, tetapi mem-parsing format string dan melakukan semua pengecekan tipe argumen yang diperlukan pada tahap kompilasi.
Juga, kata waktu kompilasi digunakan untuk menunjukkan parameter fungsi waktu kompilasi, yang mirip dengan fungsi templat C ++.
fn max(comptime T: type, a: T, b: T) T { return if (a > b) a else b; }
Menangani kesalahan
Zig menemukan sistem penanganan kesalahan asli yang tidak seperti bahasa lain. Ini bisa disebut "pengecualian eksplisit" (dalam bahasa ini, explicitness umumnya adalah salah satu idiom). Ini juga terlihat seperti kode pengembalian Go, tetapi kerjanya berbeda.
Sistem pemrosesan kesalahan Zig didasarkan pada penghitungan khusus untuk mengimplementasikan kode kesalahan khusus (kesalahan) dan dibangun berdasarkan “tipe kesalahan” (jumlah-jenis aljabar, menggabungkan tipe fungsi yang dikembalikan dan kode kesalahan).
Penghitungan kesalahan dideklarasikan dengan cara yang sama seperti penghitungan biasa:
const FileOpenError = error { AccessDenied, OutOfMemory, FileNotFound, }; const AllocationError = error { OutOfMemory, };
Namun, semua kode kesalahan menerima nilai lebih besar dari nol; juga, jika Anda mendeklarasikan kode dengan nama yang sama dalam dua enumerasi, ia akan menerima nilai yang sama. Namun, konversi implisit antara enumerasi kesalahan yang berbeda dilarang.
Kata kunci anyerror berarti enumerasi yang mencakup semua kode kesalahan.
Seperti jenis opsional, bahasa mendukung pembuatan jenis kesalahan menggunakan sintaksis khusus. Tipe! U64 adalah bentuk disingkat dari anyerror! U64, yang pada gilirannya berarti penyatuan (opsi), yang meliputi tipe u64 dan ketik anyerror (seperti yang saya pahami, kode 0 dicadangkan untuk menunjukkan tidak adanya kesalahan dan validitas bidang data, sisa kode adalah sebenarnya kode kesalahan).
Kata kunci tangkapan memungkinkan Anda menangkap kesalahan dan mengubahnya menjadi nilai default:
const number = parseU64(str, 10) catch 13;
Jadi, jika kesalahan terjadi pada fungsi parseU64 mengembalikan tipe! U64, maka catch akan "mencegat" dan mengembalikan nilai default 13.
Kata kunci percobaan memungkinkan Anda untuk "meneruskan" kesalahan ke tingkat atas (yaitu, ke tingkat fungsi panggilan). Lihat kode
fn doAThing(str: []u8) !void { const number = try parseU64(str, 10); // ... }
setara dengan ini:
fn doAThing(str: []u8) !void { const number = parseU64(str, 10) catch |err| return err; // ... }
Berikut ini terjadi: parseU64 dipanggil, jika kesalahan dikembalikan dari itu - dicegat oleh pernyataan tangkapan, di mana kode kesalahan diekstraksi menggunakan sintaks "capture", ditempatkan dalam variabel err, yang dikembalikan via! Batal ke fungsi pemanggilan.
Operator Errdefer yang dijelaskan sebelumnya juga mengacu pada penanganan kesalahan. Kode argumen errdefer dijalankan hanya jika fungsi mengembalikan kesalahan.
Beberapa kemungkinan lainnya. Menggunakan || Anda dapat menggabungkan set kesalahan
const A = error{ NotDir, PathNotFound, }; const B = error{ OutOfMemory, PathNotFound, }; const C = A || B;
Zig juga menyediakan fitur seperti penelusuran kesalahan. Ini adalah sesuatu yang mirip dengan jejak tumpukan, tetapi berisi informasi terperinci tentang kesalahan apa yang terjadi dan bagaimana ia menyebar di sepanjang rantai coba dari tempat kejadian ke fungsi utama program.
Dengan demikian, sistem penanganan kesalahan di Zig adalah solusi yang sangat asli, yang tidak terlihat seperti pengecualian di C ++ atau kode pengembalian di Go. Kita dapat mengatakan bahwa solusi semacam itu memiliki harga tertentu - tambahan 4 byte, yang harus dikembalikan bersama dengan setiap nilai yang dikembalikan; keuntungan yang jelas adalah visibilitas absolut dan transparansi. Tidak seperti C ++, di sini fungsinya tidak dapat membuang pengecualian yang tidak diketahui dari suatu tempat di kedalaman rantai panggilan. Semua fungsi yang dikembalikan - ia mengembalikan secara eksplisit dan hanya secara eksplisit.Coroutine
Zig memiliki coroutine bawaan. Ini adalah fungsi yang dibuat dengan kata kunci async, dengan bantuan fungsi pengalokasi dan deallocator ditransfer (seperti yang saya pahami, untuk tumpukan tambahan). test "create a coroutine and cancel it" { const p = try async<std.debug.global_allocator> simpleAsyncFn(); comptime assert(@typeOf(p) == promise->void); cancel p; assert(x == 2); } async<*std.mem.Allocator> fn simpleAsyncFn() void { x += 1; }
async mengembalikan objek khusus bertipe janji-> T (di mana T adalah tipe pengembalian fungsi). Dengan menggunakan objek ini, Anda dapat mengontrol coroutine.Level terendah termasuk kata kunci yang ditangguhkan, dilanjutkan, dan dibatalkan. Menggunakan penangguhan, eksekusi coroutine dihentikan sementara dan diteruskan ke program panggilan. Sintaks dari blok suspend dimungkinkan, semua yang ada di dalam blok dieksekusi sampai coroutine benar-benar ditangguhkan.resume mengambil argumen tipe janji-> T dan melanjutkan mengeksekusi coroutine dari tempat itu ditangguhkan.membatalkan membebaskan memori coroutine.Gambar ini menunjukkan transfer kontrol antara program utama (dalam bentuk tes) dan coroutine. Semuanya cukup sederhana:
Fitur kedua (level yang lebih tinggi) adalah penggunaan menunggu. Ini adalah satu-satunya hal yang, terus terang, saya tidak mengerti (sayangnya, dokumentasi masih sangat langka). Berikut adalah diagram transfer kontrol aktual dari contoh yang sedikit dimodifikasi dari dokumentasi, mungkin ini akan menjelaskan sesuatu kepada Anda:
Fungsi bawaan
fungsi bawaan - seperangkat fungsi yang cukup besar yang dibangun ke dalam bahasa dan tidak memerlukan koneksi modul apa pun. Mungkin lebih tepat untuk menyebut beberapa dari mereka "makro sintaksis bawaan", karena kemampuan banyak yang jauh melampaui fungsi. builtin menyediakan akses ke alat refleksi (sizeOf, tagName, TagType, typeInfo, typeName, typeOf), dengan modul bantuannya (impor) terhubung. Lainnya lebih seperti C / C ++ built-in klasik - mereka menerapkan konversi tipe tingkat rendah, berbagai operasi seperti sqrt, popCount, slhExact, dll. Sangat mungkin bahwa daftar fungsi-fungsi bawaan akan berubah ketika bahasa berkembang.Kesimpulannya
Sangat menyenangkan bahwa proyek seperti itu muncul dan berkembang. Meskipun bahasa C nyaman, ringkas dan akrab bagi banyak orang, itu masih ketinggalan zaman dan karena alasan arsitektur tidak dapat mendukung banyak konsep pemrograman modern. C ++ sedang berkembang, tetapi dirancang ulang secara obyektif, menjadi semakin sulit dengan setiap versi baru, dan untuk alasan arsitektur yang sama dan karena kebutuhan untuk kompatibilitas ke belakang, tidak ada yang dapat dilakukan tentang hal itu. Karat memang menarik, tetapi dengan ambang masuk yang sangat tinggi, yang tidak selalu bisa dibenarkan. D adalah upaya yang baik, tetapi ada beberapa kelemahan kecil, tampaknya bahasa awalnya dibuat lebih mungkin di bawah pengaruh Jawa, dan fitur-fitur berikutnya entah bagaimana entah bagaimana diperkenalkan sebagaimana mestinya. Jelas, Zig adalah upaya lain. Bahasanya menarik, dan menarik untuk melihat apa yang keluar dari situ.