Apa yang Anda tanyakan pada dasarnya adalah perbedaan antara kekuatan komputasi dan apa yang biasa disebut kekuatan ekspresif (atau hanya ekspresif ) dari suatu bahasa (atau sistem perhitungan).
Kekuatan Komputasi
Kekuatan komputasi mengacu pada jenis masalah apa yang dapat dikomputasi oleh bahasa. Kelas daya komputasi yang paling terkenal adalah yang setara dengan Universal Turing Machine . Ada banyak sistem komputasi lain, seperti Random Access Machines , λ-calculus , SK combinator calculus , fungsi μ-rekursif , WHILE
program, dan banyak lainnya. Dan ternyata, semua ini dapat mensimulasikan satu sama lain, yang berarti bahwa mereka semua memiliki kekuatan komputasi yang sama.
Ini memunculkan Tesis Gereja-Turing (dinamai Gereja Alonzo yang menciptakan λ-kalkulus dan Alan Turing yang menciptakan Mesin Universal Turing). Church-Turing-Thesis adalah hipotesis tentang kemampuan komputasi dengan dua aspek:
- semua sistem komputasi yang mampu melakukan komputasi umum sama kuatnya, dan
- seorang manusia yang mengikuti suatu algoritma dapat menghitung dengan tepat fungsi-fungsi yang dapat dikomputasi oleh Mesin Turing (dan karenanya sistem lain mana pun).
Yang kedua lebih penting dalam bidang filsafat pikiran daripada ilmu komputer.
Namun, ada dua hal yang tidak dikatakan oleh Turing-Gereja , yang sangat relevan dengan pertanyaan Anda:
- seberapa efisien berbagai simulasi dan
- seberapa mudah penyandian masalah.
Contoh sederhana untuk (1): pada Mesin Akses Acak, menyalin array membutuhkan waktu sebanding dengan panjang array. Pada Mesin Turing, bagaimanapun, dibutuhkan waktu sebanding dengan kuadrat dari panjang array, karena Mesin Turing tidak memiliki akses memori acak, itu hanya dapat bergerak melintasi pita satu sel pada suatu waktu. Oleh karena itu, perlu bergerak melintasi n elemen dari array n kali untuk menyalinnya. Jadi, model komputasi yang berbeda mungkin memiliki karakteristik kinerja yang berbeda, bahkan dalam kasus asimptotik, di mana kami mencoba untuk abstrak dari detail implementasi.
Contoh untuk (2) berlimpah: λ-kalkulus dan Python adalah Turing-complete. Tetapi apakah Anda lebih suka menulis program dengan Python atau dalam λ-calculus?
Ada juga kerutan ketiga yang saya alami sampai sekarang: semua sistem asli dirancang oleh ahli logika, filsuf, atau ahli matematika, bukan oleh ilmuwan komputer ... hanya karena komputer dan dengan demikian ilmu komputer tidak ada. Ini semua pergi kembali ke awal 1930-an, bahkan sebelum Konrad Zuse 's sangat eksperimen pertama (yang tidak diprogram dan / atau pula Turing-lengkap). Mereka hanya berbicara tentang "fungsi yang dapat dihitung pada bilangan asli".
Sekarang, ternyata, ada banyak hal yang dapat Anda ekspresikan sebagai fungsi pada bilangan asli - setelah semua, komputer modern kita bahkan bertahan dengan lebih sedikit dari itu (pada dasarnya 3-4 fungsi pada angka 0 dan 1, dan hanya itu ), tetapi, misalnya, fungsi apa yang dihitung oleh sistem operasi?
Gagasan I / O ini, efek samping, berinteraksi dengan lingkungan, tidak ditangkap oleh gagasan "fungsi atas bilangan alami". Namun, ini agak penting, karena, seperti yang pernah dikatakan Simon Peyton Jones "Semua fungsi murni tanpa efek samping, membuat CPU Anda panas" , yang dijawab oleh anggota audiens "sebenarnya, itu adalah sisi -Efek juga! "
Edwin Brady , perancang Idris , (hanya setengah) dengan bercanda menggunakan (saya tidak tahu apakah dia yang menciptakannya) istilah "Tetris-complete" untuk menyatakan perbedaan antara "dapat menghitung fungsi yang dapat dihitung pada bilangan asli" dan "dapat digunakan untuk menulis program non-sepele yang berinteraksi dengan lingkungan ". Yang lebih ironis lagi, ia mendemonstrasikan hal ini dengan mengimplementasikan klon Space Invaders di Idris , tetapi ia mengatakan bahwa ia yakin Tetris berkurang menjadi Space Invaders.
Hal lain untuk menunjukkan adalah bahwa tidak hanya Turing-kesetaraan belum tentu cukup untuk berbicara tentang benar-benar menulis "berguna" program, mungkin Otoh juga bahkan tidak necesssary . Misalnya SQL hanya menjadi setara Turing dengan ANSI SQL: 1999 , tetapi masih berguna sebelum itu. Bahkan, beberapa orang mungkin berpendapat bahwa membuatnya setara dengan Turing tidak menambah manfaatnya sama sekali. Ada banyak Bahasa Khusus Domain yang tidak setara dengan Turing. Deskripsi Data Bahasa biasanya tidak (dan tidak seharusnya). Total Bahasa jelas tidak bisa setara dengan Turing, namun Anda masih bisa menulis loop acara, server web, atau sistem operasi di dalamnya. Ada juga bahasa yang setara dengan Turing tetapi di mana ini sebenarnya dianggap sebagai kesalahan.
Jadi, secara keseluruhan, Turing-equivalence tidak terlalu menarik, kecuali jika Anda ingin menganalisis program secara statis.
Ekspresi
Dengan asumsi bahwa sistem komputasi kita cukup kuat secara komputasi untuk menyelesaikan masalah kita sama sekali, apa yang harus kita lakukan selanjutnya, adalah mengekspresikan algoritma kami untuk memecahkan masalah itu dalam semacam notasi formal untuk sistem itu. Dengan kata lain: kita perlu menulis sebuah program dalam beberapa bahasa komputer. Di situlah gagasan ekspresif muncul.
Ini merujuk pada, pada dasarnya, betapa "mudah" atau "menyenangkan" menulis program kami dalam bahasa pemrograman khusus kami. Seperti yang Anda lihat, gagasan ini cukup kabur, subyektif, dan lebih psikologis daripada teknis.
Namun, ada upaya definisi yang lebih tepat. Yang paling terkenal (dan yang paling keras yang saya tahu) adalah oleh Matthias Felleisen di makalahnya Pada Kekuatan Ekspresif Bahasa Pemrograman (dua halaman pertama berisi perkenalan yang lembut, sisa kertasnya lebih tebal).
Intuisi utamanya adalah ini: ketika menerjemahkan suatu program dari bahasa ke bahasa lain, beberapa perubahan yang perlu Anda lakukan terkandung secara lokal (seperti misalnya mengubah FOR
loop menjadi WHILE
loop atau loop ke conditional GOTO
s), dan beberapa memerlukan perubahan ke global struktur program.
Ketika Anda dapat mengganti satu fitur dari satu bahasa dengan fitur yang berbeda dari bahasa yang berbeda hanya dengan transformasi lokal, maka fitur-fitur ini dikatakan tidak berpengaruh pada kekuatan ekspresif. Ini disebut gula sintaksis .
Di sisi lain, jika memerlukan perubahan struktur global program, maka bahasa yang Anda terjemahkan dikatakan tidak dapat mengekspresikan fitur. Dan bahasa tempat Anda menerjemahkan dikatakan lebih ekspresif (berkenaan dengan fitur ini).
Perhatikan bahwa ini memberikan definisi ekspresif yang terukur secara obyektif. Perhatikan juga bahwa gagasan tergantung pada konteks pada fitur, dan itu komparatif. Jadi, jika setiap program dalam bahasa A dapat diterjemahkan ke bahasa B dengan hanya perubahan lokal, dan setidaknya ada satu program dalam bahasa B yang tidak dapat diterjemahkan ke A dengan hanya perubahan lokal, maka bahasa B secara ketat lebih ekspresif daripada bahasa SEBUAH. Namun, skenario yang lebih mungkin adalah bahwa banyak program dalam kedua bahasa dapat diterjemahkan bolak-balik, tetapi ada beberapa program dalam kedua bahasa yang tidak dapat diterjemahkan ke yang lain. Ini berarti bahwa tidak ada bahasa yang lebih ekspresif daripada yang lain, mereka hanya memiliki fitur yang berbeda yang memungkinkan program yang berbeda untuk diekspresikan dengan cara yang berbeda.
Ini memberikan definisi formal tentang apa artinya "lebih ekspresif", tetapi masih tidak menangkap gagasan psikologis di balik fenomena tersebut. Misalnya, gula sintaksis, menurut model ini, tidak meningkatkan kekuatan ekspresif suatu bahasa, karena itu dapat diterjemahkan hanya dengan menggunakan perubahan lokal. Namun, kita tahu dari pengalaman bahwa memiliki FOR
, WHILE
dan IF
tersedia, bahkan jika itu hanya gula sintaksis untuk bersyarat GOTO
membuat mengekspresikan maksud kita lebih mudah .
Faktanya adalah, bahasa yang berbeda memiliki fitur yang berbeda yang membuat mengekspresikan cara berpikir yang berbeda tentang masalah lebih mudah atau lebih sulit. Dan beberapa orang mungkin menemukan satu cara untuk mengekspresikan niat mereka dengan lebih mudah dan yang lain dengan cara yang berbeda.
Sebuah contoh yang saya temukan di tag Ruby pada StackOverflow: banyak pengguna yang mengikuti klaim tag Ruby bahwa loop lebih mudah dipahami daripada rekursi dan rekursi hanya untuk programmer fungsional lanjutan dan loop lebih intuitif untuk pendatang baru, tetapi saya telah melihat beberapa kasus pendatang baru yang secara intuitif menulis kode seperti ini:
def rock_paper_scissors
get_user_input
determine_outcome
print_winner
rock_paper_scissors # start from the top
end
Yang biasanya menyebabkan beberapa orang berkomentar bahwa "ini tidak berhasil" dan "mereka melakukan kesalahan" dan "cara yang benar" adalah ini:
def rock_paper_scissors
loop do
get_user_input
determine_outcome
print_winner
end
end
Jadi, jelas, ada beberapa orang yang rekursi ekornya merupakan cara yang lebih alami untuk mengekspresikan konsep "perulangan" daripada konstruksi perulangan.
Ringkasan
Fakta bahwa dua bahasa setara Turing mengatakan satu dan tepat satu hal: bahwa mereka dapat menghitung set fungsi yang sama pada bilangan asli seperti yang dapat dilakukan oleh Mesin Turing. Itu dia.
Itu tidak mengatakan apa-apa tentang seberapa cepat mereka menghitung fungsi-fungsi itu. Itu tidak mengatakan apa-apa tentang kemudahan mengekspresikan fungsi-fungsi itu. Dan itu tidak mengatakan apa-apa tentang apa lagi yang bisa mereka lakukan selain menghitung fungsi pada bilangan asli (misalnya menautkan ke pustaka C, membaca input dari pengguna, menulis output ke layar).
apakah itu berarti bahwa kelas masalah yang dapat dipecahkan oleh setiap bahasa pemrograman berbeda-beda berdasarkan bahasa, meskipun semua bahasa ini sudah lengkap?
Iya nih.
- Ada masalah yang tidak tercakup oleh istilah "Turing-complete" (yang hanya menyangkut dirinya sendiri dengan fungsi komputasi pada bilangan asli) seperti mencetak ke layar. Dua bahasa dapat menyelesaikan Turing tetapi satu dapat memungkinkan pencetakan ke layar dan yang lainnya tidak.
- Bahkan jika kedua bahasa dapat memecahkan masalah yang sama, itu tidak mengatakan apa-apa tentang betapa rumitnya pengkodean, dan betapa mudahnya mengekspresikan pengodean ini. Misalnya C dapat menyelesaikan setiap masalah yang Haskell bisa, cukup dengan menulis juru bahasa Haskell di C ... tetapi Anda harus menulis juru bahasa Haskell terlebih dahulu untuk menyelesaikan masalah dengan cara ini!