Pertama saya ingin mengatakan Java adalah satu-satunya bahasa yang pernah saya gunakan, jadi mohon maafkan ketidaktahuan saya tentang hal ini.
Bahasa yang diketik secara dinamis memungkinkan Anda untuk memberikan nilai apa pun dalam variabel apa pun. Jadi misalnya Anda bisa menulis fungsi berikut (psuedocode):
void makeItBark(dog){
dog.bark();
}
Dan Anda dapat memberikan nilai apa pun di dalamnya. Selama nilainya memiliki bark()
metode, kode akan berjalan. Jika tidak, pengecualian runtime atau sesuatu yang serupa dilemparkan. (Tolong perbaiki saya jika saya salah tentang ini).
Tampaknya, ini memberi Anda fleksibilitas.
Namun, saya melakukan beberapa bacaan tentang bahasa dinamis, dan apa yang orang katakan adalah bahwa ketika merancang atau menulis kode dalam bahasa dinamis, Anda berpikir tentang jenis dan memperhitungkannya, seperti halnya Anda menggunakan bahasa yang diketik secara statis.
Jadi misalnya ketika menulis makeItBark()
fungsi, Anda bermaksud untuk hanya menerima 'hal-hal yang dapat menggonggong', dan Anda masih perlu memastikan Anda hanya memasukkan hal-hal semacam itu ke dalamnya. Satu-satunya perbedaan adalah bahwa sekarang kompiler tidak akan memberi tahu Anda ketika Anda melakukan kesalahan.
Tentu, ada satu keuntungan dari pendekatan ini yaitu dalam bahasa statis, untuk mencapai 'fungsi ini menerima apa pun yang bisa menggonggong', Anda harus mengimplementasikan Barker
antarmuka eksplisit . Namun, ini sepertinya keuntungan kecil.
Apakah saya melewatkan sesuatu? Apa yang sebenarnya saya peroleh dengan menggunakan bahasa yang diketik secara dinamis?
sumber
makeItBark(collections.namedtuple("Dog", "bark")(lambda x: "woof woof"))
. Argumen itu bahkan bukan kelas , itu adalah anonim bernama tuple. Mengetik bebek ("jika dikuak seperti ...") memungkinkan Anda melakukan antarmuka ad hoc dengan dasarnya tidak ada batasan dan tidak ada overhead sintaksis. Anda dapat melakukan ini dalam bahasa seperti Java, tetapi Anda berakhir dengan banyak refleksi yang berantakan. Jika fungsi di Java memerlukan ArrayList dan Anda ingin memberikannya jenis koleksi lain, Anda SOL. Dengan python yang bahkan tidak bisa muncul.bark()
metode, dengan kompiler mengeluh ketika Anda memasukkan sesuatu yang salah tetapi tanpa harus benar-benar mendeklarasikan antarmuka yang berisi kulit kayu ().getMember
fungsi kustom ,makeItBark
meledak karena Anda memanggildog.bark
alih-alihdog.getMember("bark")
. Apa yang membuat kode berfungsi adalah bahwa setiap orang secara implisit setuju untuk menggunakan tipe objek asli Python.Just because I wrote makeItBark with my own types in mind doesn't mean you can't use yours, wheras in a static language it probably /does/ mean that.
Seperti yang ditunjukkan dalam jawaban saya, ini tidak terjadi secara umum . Itulah yang terjadi pada Java dan C #, tetapi bahasa-bahasa tersebut memiliki sistem tipe dan modul yang lumpuh sehingga mereka tidak mewakili apa yang dapat dilakukan pengetikan statis. Saya dapat menulis generik sempurnamakeItBark
dalam beberapa bahasa yang diketik secara statis, bahkan yang non-fungsional seperti C ++ atau D.Jawaban:
Bahasa yang diketik secara dinamis tidak diketik
Membandingkan sistem tipe , tidak ada keuntungan dalam pengetikan dinamis. Pengetikan dinamis adalah kasus khusus pengetikan statis - pengetikan statis di mana setiap variabel memiliki tipe yang sama. Anda bisa mencapai hal yang sama di Java (minus conciseness) dengan membuat setiap variabel bertipe
Object
, dan memiliki nilai "objek" bertipeMap<String, Object>
:Jadi, bahkan tanpa refleksi, Anda dapat mencapai efek yang sama di hampir semua bahasa yang diketik secara statis, selain kemudahan sintaksis. Anda tidak mendapatkan kekuatan ekspresif tambahan apa pun; sebaliknya, Anda memiliki kekuatan yang kurang ekspresif karena dalam bahasa yang diketik secara dinamis, Anda ditolak kemampuan untuk membatasi variabel ke jenis tertentu.
Membuat kulit bebek dalam bahasa yang diketik secara statis
Selain itu, bahasa yang diketik secara statis yang baik akan memungkinkan Anda untuk menulis kode yang berfungsi dengan semua jenis yang memiliki
bark
operasi. Di Haskell, ini adalah kelas tipe:Ini menyatakan kendala bahwa untuk beberapa jenis
a
dianggap Barkable, harus adabark
fungsi yang mengambil nilai jenis itu dan tidak mengembalikan apa pun.Anda kemudian dapat menulis fungsi umum dalam
Barkable
batasan:Ini mengatakan bahwa
makeItBark
akan bekerja untuk semua jenisBarkable
persyaratan yang memuaskan . Ini mungkin tampak mirip denganinterface
di Java atau C # tetapi memiliki satu keuntungan besar - tipe tidak harus menentukan di depan kelas tipe apa yang mereka puaskan. Saya dapat mengatakan bahwa tipeDuck
ituBarkable
kapan saja, bahkan jikaDuck
tipe pihak ketiga saya tidak menulis. Sebenarnya, tidak masalah jika penulisDuck
tidak menulis suatubark
fungsi - saya bisa menyediakannya setelah fakta ketika saya memberi tahu bahasa yangDuck
memuaskanBarkable
:Ini mengatakan bahwa
Duck
s dapat menggonggong, dan fungsi kulit mereka diimplementasikan dengan meninju bebek sebelum membuatnya dukun. Dengan cara itu, kita bisa memanggilmakeItBark
bebek.Standard ML
danOCaml
bahkan lebih fleksibel karena Anda dapat memenuhi kelas tipe yang sama dalam lebih dari satu cara. Dalam bahasa-bahasa ini saya dapat mengatakan bahwa bilangan bulat dapat dipesan menggunakan pemesanan konvensional dan kemudian berbalik dan mengatakan mereka juga dapat dipesan oleh keterbelahan (misalnya10 > 5
karena 10 dapat dibagi 5). Di Haskell, Anda hanya dapat membuat instance kelas tipe satu kali. (Ini memungkinkan Haskell untuk secara otomatis tahu bahwa itu ok untuk memanggilbark
pada bebek, dalam SML atau OCaml Anda harus eksplisit tentang yangbark
berfungsi Anda inginkan, karena mungkin ada lebih dari satu.)Keringkasan yg padat isinya
Tentu saja, ada perbedaan sintaksis. Kode Python yang Anda sajikan jauh lebih ringkas daripada yang setara dengan Java yang saya tulis. Dalam praktiknya, keringkasan itu adalah bagian besar dari daya pikat bahasa yang diketik secara dinamis. Tetapi inferensi tipe memungkinkan Anda untuk menulis kode yang sama ringkasnya dalam bahasa yang diketik secara statis, dengan membebaskan Anda dari keharusan untuk secara eksplisit menulis jenis setiap variabel. Bahasa yang diketik secara statis juga dapat memberikan dukungan asli untuk pengetikan dinamis, menghilangkan verbositas dari semua casting dan manipulasi peta (misalnya C # 's
dynamic
).Program yang benar tetapi salah ketik
Agar adil, pengetikan statis harus mengesampingkan beberapa program yang secara teknis benar meskipun pemeriksa tipe tidak dapat memverifikasinya. Sebagai contoh:
Sebagian besar bahasa yang diketik secara statis akan menolak
if
pernyataan ini , meskipun cabang lain tidak akan pernah muncul. Dalam praktiknya sepertinya tidak ada yang menggunakan jenis kode ini - apa pun yang terlalu pintar untuk pemeriksa tipe mungkin akan membuat pengelola kode masa depan Anda mengutuk Anda dan kerabat Anda berikutnya. Contohnya, seseorang berhasil menerjemahkan 4 proyek Python open source ke Haskell yang berarti mereka tidak melakukan apa pun yang tidak bisa dikompilasi oleh bahasa yang diketik secara statis. Terlebih lagi, kompiler menemukan beberapa bug terkait tipe yang tidak ditangkap oleh unit test.Argumen terkuat yang pernah saya lihat untuk pengetikan dinamis adalah makro Lisp, karena mereka memungkinkan Anda untuk memperpanjang sintaks bahasa secara sewenang-wenang. Namun, Typed Racket adalah dialek Lisp yang diketik secara statis yang memiliki makro, jadi sepertinya pengetikan statis dan makro tidak saling eksklusif, meskipun mungkin lebih sulit untuk diterapkan secara bersamaan.
Apel dan Jeruk
Akhirnya, jangan lupa bahwa ada perbedaan yang lebih besar dalam bahasa daripada hanya sistem tipenya. Sebelum ke Java 8, melakukan segala jenis pemrograman fungsional di Jawa praktis tidak mungkin; lambda sederhana akan membutuhkan 4 baris kode kelas anonim boilerplate. Java juga tidak memiliki dukungan untuk kumpulan literal (mis
[1, 2, 3]
.). Mungkin juga ada perbedaan dalam kualitas dan ketersediaan tooling (IDE, debugger), perpustakaan, dan dukungan komunitas. Ketika seseorang mengklaim lebih produktif dalam Python atau Ruby daripada Java, perbedaan fitur itu perlu diperhitungkan. Ada perbedaan antara membandingkan bahasa dengan semua baterai yang disertakan , inti bahasa dan sistem tipe .sumber
Ini adalah masalah yang sulit, dan cukup subyektif. (Dan pertanyaan Anda mungkin ditutup sebagai berbasis opini, tetapi itu tidak berarti itu adalah pertanyaan yang buruk - sebaliknya, bahkan memikirkan pertanyaan meta-bahasa semacam itu adalah pertanda baik - itu hanya tidak cocok dengan format Q&A dari forum ini.)
Inilah pandangan saya tentang hal itu: Inti dari bahasa tingkat tinggi adalah untuk membatasi apa yang dapat dilakukan oleh seorang programmer dengan komputer. Ini mengejutkan bagi banyak orang, karena mereka percaya tujuannya adalah untuk memberi pengguna lebih banyak kekuatan dan mencapai lebih banyak . Tetapi karena semua yang Anda tulis dalam Prolog, C ++ atau Daftar akhirnya dieksekusi sebagai kode mesin, sebenarnya tidak mungkin untuk memberi programmer lebih banyak kekuatan daripada bahasa assembly yang sudah disediakan.
Maksud dari bahasa tingkat tinggi adalah untuk membantu programmer memahami kode yang mereka buat sendiri dengan lebih baik, dan untuk membuatnya lebih efisien dalam melakukan hal yang sama. Nama subrutin lebih mudah diingat daripada alamat heksadesimal. Penghitung argumen otomatis lebih mudah digunakan daripada urutan panggilan di sini Anda harus mendapatkan jumlah argumen tepat sendiri, tanpa bantuan. Sistem tipe melangkah lebih jauh dan membatasi jenis argumen yang dapat Anda berikan di tempat tertentu.
Di sinilah persepsi orang berbeda. Beberapa orang (saya termasuk di antara mereka) berpikir bahwa selama rutin pengecekan kata sandi Anda akan mengharapkan tepat dua argumen, dan selalu berupa string yang diikuti oleh id numerik, akan sangat berguna untuk mendeklarasikan ini dalam kode dan secara otomatis diingatkan jika Anda kemudian lupa untuk mengikuti aturan itu. Mengalihdayakan pembukuan skala kecil ke kompiler membantu membebaskan pikiran Anda untuk masalah tingkat yang lebih tinggi dan membuat Anda lebih baik dalam merancang dan merancang sistem Anda. Oleh karena itu, sistem tipe adalah kemenangan besar: mereka membiarkan komputer melakukan apa yang baik, dan manusia melakukan apa yang mereka kuasai.
Yang lain melihat dengan sangat berbeda. Mereka tidak suka diberitahu oleh kompiler apa yang harus dilakukan. Mereka tidak menyukai upaya di muka ekstra untuk memutuskan deklarasi tipe dan mengetiknya. Mereka lebih suka gaya pemrograman eksplorasi di mana Anda menulis kode bisnis yang sebenarnya tanpa memiliki rencana yang akan memberi tahu Anda secara tepat jenis dan argumen yang digunakan di mana. Dan untuk gaya pemrograman yang mereka gunakan, itu mungkin benar.
Saya terlalu menyederhanakan di sini, tentu saja. Pengecekan tipe tidak terikat dengan deklarasi tipe eksplisit; ada juga tipe inferensi. Pemrograman dengan rutinitas yang benar-benar mengambil argumen dari berbagai jenis memang memungkinkan hal-hal yang sangat berbeda dan sangat kuat yang seharusnya tidak mungkin, hanya saja banyak orang tidak cukup perhatian dan konsisten untuk menggunakan kelonggaran seperti itu dengan sukses.
Pada akhirnya, fakta bahwa bahasa-bahasa yang berbeda tersebut sangat populer dan tidak menunjukkan tanda-tanda kematian menunjukkan kepada Anda bahwa orang-orang melakukan pemrograman yang sangat berbeda. Saya pikir fitur bahasa pemrograman sebagian besar tentang faktor manusia - yang mendukung proses pengambilan keputusan manusia lebih baik - dan selama orang bekerja dengan sangat berbeda, pasar akan memberikan solusi yang sangat berbeda secara bersamaan.
sumber
Kode yang ditulis menggunakan bahasa dinamis tidak digabungkan ke sistem tipe statis. Oleh karena itu, kurangnya kopling ini merupakan keuntungan dibandingkan dengan sistem tipe statis yang buruk / tidak memadai (meskipun mungkin merupakan pencucian atau kerugian dibandingkan dengan sistem tipe statis yang bagus).
Selanjutnya, untuk bahasa yang dinamis, sistem tipe statis tidak harus dirancang, diimplementasikan, diuji, dan dipelihara. Ini bisa membuat implementasi lebih sederhana dibandingkan dengan bahasa dengan sistem tipe statis.
sumber