Istilah "orthogonality" adalah istilah awam untuk gagasan matematika yang tepat: istilah bahasa membentuk aljabar awal (lihat di Wikipedia).
Ini pada dasarnya berarti "ada korespondensi 1-1 antara sintaks dan makna". Ini berarti: ada persis satu cara untuk mengekspresikan sesuatu, dan, jika Anda dapat menaruh ekspresi di tempat tertentu, maka Anda dapat menempatkan ekspresi lain di sana juga.
Cara lain untuk berpikir tentang "ortogonal" adalah bahwa sintaksanya mematuhi prinsip substitusi. Misalnya jika Anda memiliki pernyataan dengan slot untuk ekspresi, maka ekspresi apa pun dapat diletakkan di sana dan hasilnya masih merupakan program yang valid secara sintaksis. Selanjutnya, jika Anda mengganti
Saya ingin menekankan bahwa "makna" tidak menyiratkan hasil komputasi. Jelas, 1 + 2 dan 2 + 1 sama dengan 3. Namun ketentuannya berbeda, dan menyiratkan perhitungan yang berbeda walaupun memiliki hasil yang sama. Artinya berbeda, sama seperti dua algoritma berbeda.
Anda mungkin pernah mendengar "pohon sintaksis abstrak" (AST). Kata "abstrak" di sini berarti tepat "ortogonal". Secara teknis kebanyakan AST sebenarnya tidak abstrak!
Mungkin Anda pernah mendengar tentang bahasa pemrograman "C"? Notasi tipe C tidak abstrak. Mempertimbangkan:
int f(int);
Jadi di sini adalah tipe deklarasi fungsi kembali int
. Jenis pointer ke fungsi ini diberikan oleh:
int (*)(int)
Catatan, Anda tidak dapat menulis jenis fungsinya! Notasi tipe C menyebalkan! Itu tidak abstrak. Itu bukan ortogonal. Sekarang, misalkan kita ingin membuat fungsi yang menerima tipe di atas, bukan int:
int (*) ( int (*)(int) )
Semua baik-baik saja .. tapi .. bagaimana jika kita ingin mengembalikannya sebagai gantinya:
int (*)(int) (*) (int)
Aduh! Tidak valid Mari kita tambahkan parens:
(int (*)(int)) (*) (int)
Aduh! Itu juga tidak berhasil. Kita harus melakukan ini (itu satu-satunya cara!):
typedef int (intintfunc*) (int);
intintfunc (*)(int)
Sekarang tidak masalah, tetapi harus menggunakan typedef di sini buruk. C menyebalkan. Itu tidak abstrak. Itu bukan ortogonal. Inilah cara Anda melakukan ini dalam ML, yaitu:
int -> (int -> int)
Kami mengutuk C di tingkat sintaksis.
Ok, sekarang mari kita belasan C ++. Kami dapat memperbaiki kebodohan di atas dengan templat dan mendapatkan notasi seperti ML (kurang lebih):
fun<int, int>
fun< fun<int,int>, int>
tetapi sistem tipe aktual pada dasarnya cacat oleh referensi: jika T
suatu tipe, maka apakah T&
suatu tipe? Jawabannya adalah waffly: pada tingkat sintaksis, jika Anda memiliki tipe U = T &, maka U & diizinkan tetapi itu hanya berarti T &: referensi ke referensi adalah referensi asli. Ini menyebalkan! Ini melanggar persyaratan keunikan secara semantik. Lebih buruk: T & & tidak diizinkan secara sintaksis: ini melanggar prinsip substitusi. Jadi referensi C ++ memecah ortogonalitas dalam dua cara berbeda, tergantung pada waktu pengikatan (analisis parsing atau tipe). Jika Anda ingin memahami bagaimana melakukan ini dengan benar .. tidak ada masalah dengan petunjuk!
Hampir tidak ada bahasa nyata yang ortogonal. Bahkan Skema, yang berpura-pura memiliki kejelasan ekspresi, tidak. Namun banyak bahasa yang baik dapat dinilai memiliki "cukup dekat dengan basis fitur ortogonal" dan itu adalah rekomendasi yang baik untuk sebuah bahasa, diterapkan baik pada sintaksis maupun semantik yang mendasarinya.