Penulis artikel, yang terjemahannya kami terbitkan hari ini, mengatakan bahwa posting
ini dan komentar tentangnya berfungsi sebagai sumber inspirasi untuk tulisannya. Menurutnya, spesialis IT memiliki kesalahpahaman tentang jenis, menggunakan terminologi yang salah dan, membahas masalah yang berkaitan dengan jenis, sampai pada kesimpulan yang salah. Dia mencatat bahwa dia bukan pembela sistem tipe statis. Satu-satunya hal yang mengganggunya adalah penggunaan istilah yang benar. Ini memungkinkan diskusi yang konstruktif. Penulis mengatakan bahwa ia menulis materi ini secara spontan, tetapi berharap tidak ada kesalahan di dalamnya. Jika dia bingung sesuatu, dia meminta untuk memberi tahu
dia tentang hal itu.

Mari kita mengerti sekali dan untuk semua apa yang menyebabkan kebingungan ketika berbicara tentang sistem tipe.
Pengetikan dinamis dan kurang pengetikan
Beberapa orang berpikir bahwa sistem tipe dinamis sama dengan sistem tipe yang tidak diketik. Kurangnya pengetikan berarti bahwa dalam sistem jenis tertentu tidak masuk akal untuk membedakan antara jenis. Tidak masuk akal untuk membedakan jenis bahkan jika hanya satu jenis hadir di sistem tipe. Sebagai contoh:
- Di assembler, satu-satunya tipe adalah serangkaian bit.
- Dalam kalkulus lambda, satu-satunya tipe adalah fungsi.
Seseorang mungkin mengatakan ini pada kesempatan ini: "Tapi apa bedanya - mengetik dinamis atau kurang mengetik - juga pertanyaan bagi saya." Tapi ini, pada kenyataannya, adalah masalah besar dan penting. Faktanya adalah bahwa jika Anda menyamakan pengetikan dinamis dengan kurangnya pengetikan, itu berarti adopsi otomatis dari fakta bahwa sistem tipe dinamis adalah kebalikan dari sistem tipe statis. Akibatnya, dua kubu programmer yang berlawanan terbentuk - kubu pengetikan dinamis dan kubu pengetikan statis (dan ini, seperti yang akan kita lihat di bagian yang sesuai, salah).
Bahasa yang tidak membatasi rentang nilai variabel disebut bahasa yang tidak diketik: mereka tidak memiliki tipe, atau, apa hal yang sama, mereka hanya memiliki satu tipe universal yang berisi semua nilai.Jenis Sistem, Luca CardelliBahasa pemrograman memiliki satu fitur menarik yang memungkinkan Anda membagi dunia mereka menjadi dua kelompok:
- Bahasa yang tidak diketik - program cukup dijalankan. Ini terjadi dengan cepat, tanpa mencoba memeriksa "keseragaman bentuk".
- Bahasa yang diketik - suatu upaya dilakukan untuk memeriksa "keseragaman bentuk" - baik selama kompilasi atau selama eksekusi program.
"Ketik Sistem untuk Bahasa Pemrograman," Benjamin PearcePengetikan dinamis dan statis
Sistem tipe dinamis adalah sistem di mana tipe diperiksa secara dinamis (selama eksekusi program). Sistem tipe statis adalah sistem di mana tipe diperiksa secara statis (selama kompilasi atau terjemahan kode).
Apakah salah satu dari sistem ini bertolak belakang dengan yang lain? Tidak, tidak. Kedua jenis sistem dapat digunakan dalam bahasa yang sama. Bahkan, sebagian besar sistem tipe statis juga memiliki pemeriksaan tipe dinamis. Sebagai contoh, pertimbangkan validasi operasi input-output (input-output, IO). Bayangkan Anda perlu membaca data yang disediakan oleh pengguna yang harus memasukkan nomor. Anda akan memeriksa, selama eksekusi program, apakah nomor tersebut adalah hasil parsing baris yang sesuai (sebagai hasil parsing, pengecualian dapat dilemparkan atau sesuatu seperti
NaN
akan dikembalikan). Saat Anda memeriksa data yang dimasukkan oleh pengguna, mencari tahu apakah mereka dapat dianggap sebagai angka - Anda melakukan pemeriksaan tipe dinamis.
Akibatnya, kita dapat mencatat tidak adanya konfrontasi antara tipe statis dan dinamis. Anda dapat menggunakan, dalam bahasa yang sama, baik itu dan lainnya.
Selain itu, perlu dicatat bahwa pemeriksaan tipe statis adalah proses yang kompleks. Terkadang sangat sulit untuk secara statis memeriksa beberapa bagian dari suatu program. Akibatnya, alih-alih menerapkan pemeriksaan tipe statis, Anda dapat menggunakan pemeriksaan dinamis.
Dianjurkan untuk mempertimbangkan sistem tipe statis sebagai tipe yang diperiksa secara statis. Sistem tipe dinamis seperti tipe yang diperiksa secara dinamis.
Apakah menggunakan tipe statis berarti mengetahui tipe pada waktu kompilasi?
Pertanyaan yang diajukan dalam judul bagian ini dapat dijawab dengan negatif. Jika Anda membuka kode sumber parser apa pun (termasuk parser JavaScript), Anda dapat melihat bahwa parser mengetahui jenis nilai selama parsing (ini adalah bagian dari proses kompilasi).
let x = "test";
Ternyata parser tahu bahwa
"test"
adalah sebuah string. Apakah ini menjadikan JavaScript bahasa yang diketik statis? Tidak, tidak.
Pengetikan bertahap
Sistem tipe bertahap adalah sistem tipe statis yang memungkinkan Anda melompati pemeriksaan tipe untuk beberapa bagian program. Misalnya, dalam TypeScript, ini diterapkan menggunakan
any
atau
@ts-ignore
.
Di satu sisi, ini membuat sistem tipe kurang aman. Di sisi lain, sistem tipe dengan pengetikan bertahap memungkinkan Anda untuk secara bertahap menambahkan deskripsi tipe ke bahasa dengan pengetikan dinamis.
Sistem tipe yang andal dan tidak dapat diandalkan
Jika Anda menggunakan sistem tipe yang andal (sound type system), program, selama pemeriksaan tipe, tidak akan "disetujui" jika ada kesalahan terkait dengan tipe dalam program ini. Menggunakan sistem tipe tidak sehat mengarah ke kemungkinan kesalahan ketik dalam program. Benar, Anda tidak perlu panik setelah mengetahuinya. Dalam praktiknya, ini mungkin tidak mempengaruhi Anda. Keandalan atau kesehatan adalah properti matematika dari algoritma pengecekan tipe yang perlu bukti. Banyak kompiler yang ada (secara internal, sistem pengecekan tipe) tidak dapat diandalkan.
Jika Anda ingin bekerja dengan sistem tipe yang andal, lihat bahasa pemrograman keluarga ML, yang menggunakan sistem tipe Hindley-Milner.
Selain itu, harus dipahami bahwa sistem tipe yang andal tidak akan melewatkan program yang salah (tidak memberikan hasil tes positif palsu, mengingat program yang salah menjadi benar), tetapi mungkin tidak ketinggalan program yang benar (dapat memberikan hasil tes negatif palsu).
Tipe sistem yang tidak pernah menolak program yang tepat disebut lengkap.
Apakah itu terjadi bahwa sistem tipe dapat diandalkan dan lengkap? Sejauh yang saya tahu, sistem tipe seperti itu tidak ada. Saya tidak sepenuhnya yakin akan hal ini, tetapi bagi saya tampaknya keberadaan sistem tipe seperti itu, jika didasarkan pada teorema ketidaklengkapan Gödel, pada dasarnya tidak mungkin (meskipun saya bisa saja salah).
Mengetik lemah dan kuat
Saya merasa tidak pantas untuk menggunakan istilah "pengetikan lemah" dan "pengetikan kuat". Istilah-istilah ini ambigu, penggunaannya dapat memberikan lebih banyak kebingungan daripada kejelasan. Biarkan saya memberi Anda beberapa kutipan.
Bahasa-bahasa ini dapat disebut, secara kiasan, bahasa-bahasa dengan pengecekan tipe yang lemah (atau bahasa-bahasa yang diketik dengan lemah, sebagaimana biasanya disebut dalam berbagai publikasi). Penggunaan pemeriksaan tipe lemah dalam bahasa berarti bahwa beberapa operasi yang tidak aman terdeteksi secara statis, dan beberapa tidak. "Kelemahan" pemeriksaan tipe dalam bahasa kelas ini sangat bervariasi.Jenis Sistem, Luca CardelliMungkin cara paling umum untuk mengklasifikasikan sistem tipe adalah dengan membaginya menjadi sistem dengan pengetikan "lemah" dan "kuat". Ini hanya dapat disesalkan, karena kata-kata ini tidak membawa arti praktis dalam diri mereka. Dimungkinkan, sampai batas tertentu, untuk membandingkan dua bahasa yang memiliki sistem tipe yang sangat mirip dan memilih salah satu dari mereka yang memiliki sistem tipe yang lebih kuat daripada yang kedua. Dalam kasus lain, istilah "pengetikan kuat" dan "pengetikan lemah" sama sekali tidak berarti.
"Hal-hal yang Harus Diketahui Sebelum Membahas Sistem Tipe," Steve Klabnik
Istilah "pengetikan kuat" dan "pengetikan lemah" sangat ambigu. Berikut ini beberapa contoh penggunaannya:
- Terkadang "pengetikan kuat" dipahami sebagai "pengetikan statis". Tidak sulit untuk membuat "substitusi" seperti itu, tetapi lebih baik, berbicara tentang pengetikan statis, cukup menyebutnya "statis". Faktanya adalah sebagian besar programmer memahami istilah ini dengan jelas.
- Kadang-kadang, ketika mereka mengatakan "mengetik kuat", mereka berarti "tidak adanya konversi tipe implisit". Misalnya, dalam JavaScript, Anda dapat menggunakan ekspresi seperti
"a" - 1
. Ini bisa disebut model "mengetik lemah." Tetapi hampir semua bahasa memberi programmer beberapa peluang untuk konversi tipe implisit, misalnya, mendukung konversi otomatis bilangan bulat ke angka floating-point dalam ekspresi seperti 1 - 1.1
. Dalam praktiknya, sebagian besar profesional yang menggunakan istilah "pengetikan kuat" dengan cara ini membedakan antara konversi jenis "dapat diterima" dan "tidak dapat diterima". Tetapi tidak ada batas yang diterima secara umum antara konversi jenis tersebut. “Akseptabilitas” dan “tidak dapat diterima” dari transformasi adalah penilaian subyektif, tergantung pada pendapat orang tertentu. - Kadang-kadang bahasa dengan "ketikan yang kuat" disebut bahasa-bahasa di mana tidak mungkin untuk menghindari aturan dari sistem tipe yang ada di dalamnya.
- Terkadang "pengetikan kuat" berarti memiliki sistem tipe yang memungkinkan Anda bekerja dengan memori dengan aman. Bahasa C adalah contoh penting dari bahasa yang tidak aman dengan memori. Misalnya, jika
xs
adalah array dari empat angka, C akan menyetujui kode yang menggunakan konstruksi seperti xs[5]
atau xs[1000]
tanpa masalah. Mereka akan memungkinkan Anda untuk mengakses memori yang terletak setelah alamat yang dialokasikan untuk menyimpan konten array xs
.
Jenis-jenisnya, Gary BernardApakah bahasa yang diketik secara statis memerlukan deklarasi jenis?
Bahasa yang diketik secara statis tidak selalu membutuhkan deklarasi jenis. Terkadang sistem tipe dapat menyimpulkan tipe (dengan membuat asumsi berdasarkan struktur kode). Berikut ini sebuah contoh (TypeScript):
const x = "test";
Sistem tipe tahu bahwa
"test"
adalah sebuah string (pengetahuan ini didasarkan pada aturan parsing kode). Tipe sistem juga tahu bahwa
x
adalah konstanta, yaitu, nilai
x
tidak dapat dipindahkan. Sebagai hasilnya, dapat disimpulkan bahwa
x
adalah tipe string.
Berikut ini contoh lain (Aliran):
const add = (x, y) => x / y // ^ [1] . add(1, "2")
Sistem pengecekan tipe melihat bahwa kita memanggil fungsi
add
, memberikan nomor dan string. Ini menganalisis deklarasi fungsi. Sistem pemeriksaan tipe tahu bahwa untuk melakukan operasi divisi, angka harus ada di kanan dan kiri dari operator yang sesuai. Salah satu operan yang terlibat dalam operasi divisi bukanlah angka. Akibatnya, kami diberitahu tentang kesalahan tersebut.
Tidak ada deklarasi tipe di sini, tetapi ini tidak mencegah pemeriksaan tipe statis dari program di atas. Jika Anda menghadapi situasi serupa di dunia nyata, maka, cepat atau lambat, Anda harus mendeklarasikan beberapa tipe. Sistem tipe tidak dapat menyimpulkan sepenuhnya semua tipe. Tetapi Anda perlu memahami bahwa bahasa dapat disebut "statis" bukan karena menggunakan deklarasi tipe, tetapi karena jenis diperiksa sebelum program dimulai.
Apakah TypeScript bahasa yang tidak aman karena kode yang ditulis di dalamnya dikompilasi ke dalam kode JavaScript?
TypeScript adalah bahasa yang tidak sehat. Karenanya, kode yang tertulis di dalamnya dapat berubah menjadi aplikasi yang tidak aman. Tapi ini tidak ada hubungannya dengan apa yang dikompilasikan.
Sebagian besar kompiler desktop mengonversi program ke sesuatu yang mirip bahasa assembly. Dan assembler adalah bahasa yang bahkan lebih tidak aman daripada JS.
Di sini, jika Anda kembali ke gagasan bahwa TS tidak aman karena kompilasi di JS, Anda mungkin mendapatkan pemikiran berikut: "Kode yang dikompilasi dieksekusi di browser, JS adalah bahasa yang tidak aman, dan itu bisa menggantikan
null
ke tempat di mana garis diharapkan ". Pikiran itu masuk akal. Tapi ini, sekali lagi, tidak memberikan alasan untuk menyebut TS bahasa yang tidak aman. Agar TS dapat menjamin keamanan dalam aplikasi, Anda perlu menempatkan "mekanisme pertahanan" di tempat-tempat di mana kode TS berinteraksi dengan dunia luar. Misalnya, Anda perlu memeriksa kebenaran data yang masuk ke program melalui mekanisme input-output. Katakanlah ini dapat memeriksa apa yang dimasukkan pengguna, memeriksa respons server, memeriksa data yang dibaca dari penyimpanan browser, dan sebagainya.
Misalnya, peran "mekanisme pertahanan" seperti itu di Elm dimainkan oleh "
pelabuhan ". Di TS, Anda bisa menggunakan sesuatu seperti io-ts untuk ini.
"Mekanisme pelindung" yang sesuai menciptakan jembatan antara sistem tipe statis dan dinamis.
Berikut ini contoh sederhana:
const makeSureIsNumber = (x: any) => { const result = parseFloat(x); if (isNaN(result)) { throw Error("Not a number"); } return result; } const read = (input: any) => { try { const n = makeSureIsNumber(input); // n, , // // makeSureIsNumber "" , n } catch (e) { } }
Benarkah tipe hanya diperlukan untuk kompiler?
Jenis hanya hack yang diperlukan untuk memberikan petunjuk kepada kompiler.Waut MertensApakah tipe hanya dibutuhkan oleh kompiler? Ini adalah pertanyaan filosofis. Jenis dibutuhkan untuk orang, bukan mobil. Compiler membutuhkan tipe karena mereka adalah program yang ditulis oleh orang.
Fenomena jenis ada karena orang. Jenis tidak ada sampai seseorang merasakan sesuatu dalam bentuk "tipe data". Pikiran manusia membagi entitas yang berbeda ke dalam kategori yang berbeda. Jenis tidak masuk akal tanpa pengamat.
Mari kita mengatur eksperimen pemikiran. Pikirkan game Life. Anda memiliki kisi dua dimensi yang terdiri dari sel kuadrat. Masing-masing sel bisa dalam dua kemungkinan keadaan. Itu bisa "hidup" atau "mati." Setiap sel dapat berinteraksi dengan delapan tetangganya. Ini adalah sel yang membatasinya secara vertikal, horizontal, atau diagonal. Dalam proses menemukan keadaan sistem selanjutnya, aturan berikut ini berlaku:
- Sel "hidup" dengan kurang dari dua tetangga "hidup" "mati", seperti kepadatan populasi yang rendah.
- Sel "hidup" dengan dua atau tiga tetangga "hidup" bertahan dan jatuh ke generasi berikutnya.
- Sel "hidup", dengan lebih dari tiga tetangga "hidup", "mati", seperti kelebihan populasi.
- Sel "mati", yang memiliki tiga tetangga "hidup", menjadi "hidup", seperti dalam reproduksi populasi.
Secara lahiriah, itu tampak seperti bidang, dibagi menjadi sel-sel persegi, yang secara konstan "dihidupkan" dan "dimatikan".
Di sini Anda dapat melihatnya.
Jika Anda mengamati Life selama beberapa waktu, maka struktur stabil seperti "glider" mungkin muncul di lapangan.
GliderLihat dia? Seorang glider bergerak melintasi layar. Benar? Sekarang mari kita sedikit melambat. Apakah glider ini benar-benar ada? Ini hanya kotak individual yang muncul dan menghilang. Tetapi otak kita dapat melihat struktur ini sebagai sesuatu yang ada secara objektif.
Selain itu, kita dapat mengatakan bahwa "peluncur" ada karena kotak tidak independen (mereka bergantung pada tetangga), dan bahkan jika "peluncur" itu sendiri tidak ada, maka ada "peluncur" dalam bentuk ide-ide platonis.
Ringkasan
Pertimbangkan program apa pun yang ditulis dalam bahasa pemrograman yang diketik. Kita bisa mengamati tipenya. Benar? Tetapi program mengkompilasi ke dalam kode mesin. Dalam kode-kode ini, hal yang sama dinyatakan dalam program aslinya (walaupun sulit bagi seseorang untuk membaca representasi program dari mesin). Dari sudut pandang komputer, tidak ada tipe. Dia hanya melihat urutan bit - set nol dan satu (sel "mati" dan "hidup"). Jenis ada untuk orang, bukan untuk mobil.
Pembaca yang budiman! Sistem tipe apa yang Anda anggap ideal untuk pengembangan web?
