Kunci jawaban 12 Latihan Bahasa Egg. Dijalankan bersama kode interpreter Egg dari babnya.
12.1 Array
topScope.array = (...values) => values;
topScope.length = array => array.length;
topScope.element = (array, i) => array[i];Kenapa: array cukup mengembalikan rest argument-nya, yang memang sudah berupa array JavaScript. length dan element tinggal meneruskan ke operasi array biasa. Ini contoh “menumpang” fitur JavaScript: fitur array Egg didukung langsung oleh array JavaScript di baliknya.
→ Soal: 12 Latihan Bahasa Egg > 12.1 Array
12.2 Closure
Jawaban: bentuk khusus diberi scope lokal tempat ia dievaluasi. Fungsi yang dikembalikan fun menyimpan referensi ke argumen scope itu, dan waktu fungsi dipanggil, ia membuat scope lokalnya dengan Object.create(scope). Artinya prototype scope lokal adalah scope tempat fungsi dibuat. Jadi waktu fun(b, ...) bagian dalam dipanggil, ia masih bisa mencari a — karena a ada di scope f yang jadi prototype (leluhur) scope-nya. Itulah closure: fungsi membawa lingkungan tempat ia lahir. Sama persis idenya dengan closure JavaScript di 03 Fungsi > Closure.
→ Soal: 12 Latihan Bahasa Egg > 12.2 Closure
12.3 Komentar
function skipSpace(string) {
let lewat = string.match(/^(\s|#.*)*/);
return string.slice(lewat[0].length);
}Kenapa: pola (\s|#.*)* artinya “(whitespace atau # diikuti sisa baris), diulang berapa pun kali”. Karena . gak cocok baris baru, komentar #... berhenti di ujung barisnya, lalu \s menelan baris barunya dan pola bisa lanjut ke komentar berikutnya — jadi beberapa komentar beruntun tertangani. lewat[0] adalah seluruh rentangan whitespace-dan-komentar di awal, dan kita potong sepanjang itu.
→ Soal: 12 Latihan Bahasa Egg > 12.3 Komentar
12.4 Memperbaiki Scope
specialForms.set = (args, scope) => {
if (args.length != 2 || args[0].type != "word") {
throw new SyntaxError("Salah pakai set");
}
let nama = args[0].name;
let nilai = evaluate(args[1], scope);
for (let s = scope; s; s = Object.getPrototypeOf(s)) {
if (Object.hasOwn(s, nama)) {
s[nama] = nilai;
return nilai;
}
}
throw new ReferenceError(`Set variabel tak dikenal: ${nama}`);
};Kenapa: loop for menaiki rantai prototype — s = scope mulai dari scope lokal, s = Object.getPrototypeOf(s) naik ke scope luar, berhenti saat s jadi null. Object.hasOwn (bukan in) penting: in juga melihat prototype, jadi gak bisa membedakan binding milik scope itu dengan yang diwarisi. Beda dari define yang selalu menulis ke scope lokal, set mencari scope yang benar-benar memiliki binding itu dan menulis di situ; kalau tak ada di mana pun, lempar ReferenceError.