Mimpi pemrograman deklaratif [ditutup]


26

Mengapa mimpi pemrograman deklaratif tidak terwujud? Apa saja hambatan nyata yang menghadang? Sebagai contoh sederhana mengapa saya tidak bisa mengatakannya

sort(A) is defined by sort(A) in perm(A) && asc(sort(A))

dan secara otomatis mendapatkan algoritma pengurutan dari itu. permberarti permutasi dan ascberarti naik.


4
Ngomong-ngomong, contoh spesifik Anda sudah tersedia: gkoberger.github.io/stacksort
Den

3
Pernahkah Anda mendengar tentang Prolog? Carilah "Pemrograman Set Jawaban". Ada banyak sistem yang dibangun berdasarkan logika default.
schlingel

16
Nah, pertanyaan ini mudah dijawab. Mencoba menerapkan sistem seperti itu . Apa yang menghentikan Anda melakukannya dengan sukses? Kemungkinannya bagus bahwa apa pun yang berhenti Anda telah menghentikan orang lain.
Eric Lippert

4
Saya tergoda untuk percaya bahwa pertanyaan ini layak mendapat lebih banyak kredit daripada yang didapatnya. Ketika Anda melihatnya sekilas, Anda mungkin berpikir, Ya, itu sederhana! Anda harus memprogram semua logika di baliknya, dan komputer tidak sepintar itu. ... Tetapi kemudian Anda kembali dan melirik kedua pertanyaan ini, dan Anda berpikir sekali lagi , Ya, itu sederhana, dan Anda harus memprogram semua logika itu - dan komputer tidak selalu merupakan alat yang paling tajam. di dalam gudang, benar - tetapi ada jauh lebih dalam penjelasan itu daripada apa yang hanya terletak di permukaan.
Panzercrisis

3
Deskripsi Anda tentang algoritma pengurutan bersifat deklaratif, ya, tapi tentu saja tidak efisien. Ada n!permutasi dari urutan dan dalam kasus terburuk algoritma Anda harus mencoba semuanya untuk menemukan yang diurutkan. Waktu faktorial sama buruknya dengan algoritma untuk memproses suatu urutan dapat dilakukan.
Benjamin Hodgson

Jawaban:


8

Ada beberapa jawaban yang sangat bagus. Saya akan mencoba berkontribusi dalam diskusi.

Pada topik deklaratif, pemrograman logika dalam Prolog, ada buku bagus "The Craft of Prolog" oleh Richard O'Keefe . Ini adalah tentang menulis program yang efisien menggunakan bahasa pemrograman yang memungkinkan Anda menulis program yang sangat tidak efisien. Dalam buku ini, ketika membahas implementasi efisien dari beberapa algoritma (dalam bab "Metode Pemrograman"), penulis mengambil pendekatan berikut:

  • mendefinisikan masalah dalam bahasa Inggris
  • menulis solusi kerja yang deklaratif mungkin; biasanya, itu berarti apa yang Anda miliki dalam pertanyaan, cukup perbaiki Prolog
  • dari sana, ambil langkah untuk memperbaiki implementasi agar lebih cepat

Pengamatan yang paling mencerahkan (untuk saya) yang saya dapat lakukan sambil bekerja melalui ini:

Ya, versi terakhir dari implementasi jauh lebih efisien daripada spesifikasi "deklaratif" yang dimulai oleh penulis. Itu masih sangat deklaratif, ringkas, dan mudah dimengerti. Apa yang terjadi di antaranya adalah bahwa solusi akhir menangkap sifat-sifat masalah yang tidak diketahui oleh solusi awal.

Dengan kata lain, saat mengimplementasikan solusi, kami telah menggunakan sebanyak mungkin pengetahuan kami tentang masalah yang kami bisa. Membandingkan:

Temukan permutasi daftar sehingga semua elemen dalam urutan menaik

untuk:

Menggabungkan dua daftar yang diurutkan akan menghasilkan daftar yang diurutkan. Karena mungkin ada sublist yang sudah disortir, gunakan ini sebagai titik awal, bukan sub daftar panjang 1.

Selain kecil: definisi seperti yang Anda berikan menarik karena sangat umum. Namun, saya tidak bisa lepas dari perasaan bahwa itu sengaja mengabaikan fakta bahwa permutasi adalah masalah kombinatorial. Ini adalah sesuatu yang sudah kita ketahui ! Ini bukan kritik, hanya pengamatan.

Adapun pertanyaan sebenarnya: bagaimana cara bergerak maju? Nah, salah satu caranya adalah memberikan sebanyak mungkin pengetahuan tentang masalah yang kita nyatakan ke komputer.

Upaya terbaik yang saya tahu untuk benar-benar menyelesaikan masalah disajikan dalam buku-buku yang ditulis bersama oleh Alexander Stepanov, "Elemen Pemrograman" dan "Dari Matematika ke Pemrograman Generik" . Saya sedih tidak sampai pada tugas meringkas (atau bahkan sepenuhnya memahami) segala sesuatu dalam buku-buku ini. Namun, pendekatan yang ada untuk mendefinisikan algoritma perpustakaan dan struktur data yang efisien (atau bahkan optimal), di bawah ketentuan bahwa semua properti input yang relevan diketahui sebelumnya. Hasil akhirnya adalah:

  • Setiap transformasi yang terdefinisi dengan baik adalah penyempurnaan dari kendala yang sudah ada (properti yang diketahui);
  • Kami membiarkan komputer memutuskan transformasi mana yang optimal berdasarkan kendala yang ada.

Mengenai mengapa hal itu belum terjadi, yah, ilmu komputer adalah bidang yang benar-benar muda, dan kami masih berusaha untuk benar-benar menghargai kebaruan sebagian besar darinya.

PS

Untuk memberi Anda gambaran tentang apa yang saya maksud dengan "memperbaiki implementasi": ambil contoh masalah mudah untuk mendapatkan elemen terakhir dari daftar, di Prolog. Solusi deklaratif kanonik adalah dengan mengatakan:

last(List, Last) :-
    append(_, [Last], List).

Di sini, makna deklaratif dari append/3adalah:

List1AndList2adalah gabungan dari List1danList2

Karena dalam argumen kedua untuk append/3kita memiliki daftar dengan hanya satu elemen, dan argumen pertama diabaikan (garis bawah), kita mendapatkan pemisahan dari daftar asli yang membuang bagian depan daftar ( List1dalam konteks append/3) dan menuntut agar bagian belakang ( List2dalam konteks append/3) memang daftar dengan hanya satu elemen: jadi, itu adalah elemen terakhir.

The aktual implementasi disediakan oleh SWI-Prolog , bagaimanapun, mengatakan:

last([X|Xs], Last) :-
    last_(Xs, X, Last).

last_([], Last, Last).
last_([X|Xs], _, Last) :-
    last_(Xs, X, Last).

Ini masih deklaratif dengan baik. Baca dari atas ke bawah, katanya:

Elemen terakhir dari daftar hanya masuk akal untuk daftar setidaknya satu elemen. Elemen terakhir untuk sepasang ekor dan kepala daftar adalah: kepala, ketika ekor kosong, atau yang terakhir dari ekor tidak kosong.

Alasan mengapa implementasi ini disediakan adalah untuk mengatasi masalah-masalah praktis seputar model pelaksanaan Prolog. Idealnya, itu seharusnya tidak membuat perbedaan implementasi yang digunakan. Demikian pula, kita dapat mengatakan:

last(List, Last) :-
    reverse(List, [Last|_]).

Elemen terakhir dari daftar adalah elemen pertama dari daftar terbalik.

Jika Anda ingin mengisi diskusi tidak meyakinkan tentang apa yang baik, Prolog deklaratif, cukup tanyakan beberapa pertanyaan dan jawaban di tag Prolog pada Stack Overflow .


2
+1 untuk menunjukkan bagaimana desain deklaratif dapat berkembang dari abstraksi sederhana menjadi implementasi yang lebih konkrit melalui proses desain berulang.
itsbruce

1
@ Boris Ini jawaban yang bagus. Buku itu duduk di rak buku saya. Mungkin sudah saatnya saya membukanya.
davidk01

1
@ davidk01 Salah satu buku terbaik di luar sana. Ini mengasumsikan bahwa Anda cukup nyaman dengan Prolog dan pemrograman secara umum, tetapi pendekatan yang diperlukan untuk pemrograman bersifat pragmatis dan sangat menyeluruh.
XXX

2
@Boris Saya tahu contohnya tidak rumit tetapi produktivitas proses desain berulang - kekuatan nyata dari bahasa deklaratif - dan itu nilai yang sangat praktis, sangat penting. Bahasa deklaratif menawarkan pendekatan yang jelas, konsisten, rekursif untuk perbaikan iteratifnya. Bahasa imperatif tidak.
itsbruce

1
+1 untuk "dapatkan isi diskusi tidak meyakinkan tentang apa yang baik, Prolog deklaratif" ... sangat benar bahwa kami cenderung tidak setuju!
Daniel Lyons

50

Bahasa logis sudah melakukan ini. Anda dapat mendefinisikan jenis dengan cara yang sama seperti yang Anda lakukan.

Masalah utama adalah kinerja. Komputer mungkin hebat dalam menghitung banyak hal, tetapi pada dasarnya mereka bodoh. Setiap keputusan "pintar" yang dibuat komputer diprogram ke dalamnya oleh seorang programmer. Dan keputusan ini biasanya digambarkan bukan dengan bagaimana hasil akhirnya terlihat, tetapi bagaimana cara mencapai, langkah demi langkah, hasil akhir ini.

Bayangkan kisah seorang Golem . Jika Anda mencoba memberinya perintah abstrak, maka yang terbaik, dia akan melakukannya secara tidak efisien dan paling buruk, akan melukai dirinya sendiri, Anda atau orang lain. Tetapi jika Anda mendeskripsikan apa yang Anda inginkan dalam perincian sebesar mungkin, Anda dijamin akan menyelesaikan tugas dengan efektif dan efisien.

Merupakan tugas programmer untuk memutuskan level abstraksi apa yang akan digunakan. Untuk aplikasi yang Anda buat, apakah Anda akan naik level tinggi dan mendeskripsikannya secara abstrak dan membuat kinerja menjadi rendah atau kotor, menghabiskan waktu 10x lebih banyak untuk itu, tetapi mendapatkan algoritma yang 1000x lebih berkinerja tinggi?


6
Mungkin membantu untuk mengetahui bahwa kata Golem גולם sebenarnya berarti "bahan baku" yaitu keadaan paling mendasar di mana mesin / entitas dapat berada.
dotancohen

2
Bahasa deklaratif pada dasarnya tidak menjadi penghalang bagi tingkat abstraksi yang lebih rendah. Haskell dan Standard ML keduanya, dengan cara yang berbeda, memungkinkan Anda untuk membuat pernyataan deklaratif sederhana tentang jenis / fungsi di satu tempat, menyediakan serangkaian implementasi fungsi konkret dan spesifik di tempat yang terpisah dan cara untuk mencocokkan jenis dengan implementasi di tempat lain. Sementara itu, praktik terbaik dalam bahasa OO / Imperatif sekarang sangat banyak tentang memulai tinggi / sederhana dan kemudian menambahkan detail implementasi. Perbedaannya adalah bahwa abstraksi tinggi lebih mudah di FP, level rendah lebih mudah imperatif.
itsbruce

2
Harus mengatakan bahwa itu juga mungkin, dalam kedua bahasa yang disebutkan, untuk menyelesaikan pilihan implementasi spesifik secara otomatis berdasarkan pada properti dari tipe daripada pencocokan hard-coding yang spesifik, yang cukup banyak memberikan apa yang diinginkan OP. Di Haskell, ketik kelas akan menjadi alat utama untuk ini. Dalam ML Standar, functors.
itsbruce

22
@BAR Golem! = Golum Golem berasal dari cerita rakyat Yahudi
Euforia

10
Pilihan saya dari jawaban ini adalah menulis אמת di laptop saya.
Dan J

45

Selain poin Euphoric yang sangat baik , saya ingin menambahkan bahwa kita sudah menggunakan bahasa deklaratif di banyak tempat di mana mereka bekerja dengan baik, yaitu menggambarkan keadaan yang tidak mungkin berubah atau meminta sesuatu yang mana komputer sebenarnya dapat menghasilkan kode efisien dengan dirinya sendiri:

  • HTML menyatakan apa isi dari suatu halaman web.

  • CSS menyatakan seperti apa bentuk berbagai elemen dalam halaman web.

  • Setiap basis data relasional memiliki bahasa definisi data yang menyatakan apa struktur basis data itu.

  • SQL jauh lebih dekat dengan deklaratif daripada keharusan, karena Anda memberi tahu apa yang ingin Anda lihat dan perencana kueri database mencari tahu bagaimana sebenarnya mewujudkannya.

  • Orang bisa berpendapat bahwa sebagian besar file konfigurasi (.vimrc, .profile, .bashrc, .gitconfig) menggunakan bahasa khusus domain yang sebagian besar bersifat deklaratif


3
Saya akan menyebut GNU Make, XSLT, Angular.js sebagai hal yang banyak digunakan yang juga bersifat deklaratif (meskipun angular mungkin sedikit mendorong definisi).
Mark K Cowan

Biarkan saya menambahkan ekspresi reguler ke daftar itu.
Schwern

7
Orang-orang cenderung lupa bahwa bahasa deklaratif adalah umum . Mereka biasanya tidak menggunakan bahasa lengkap. Tambahkan regex ke daftar itu.
slebetman

Agak bertele-tele, tapi tetap saja: Tidak setiap database memiliki DDL, pikirkan saja sejumlah besar basis data NoSQL schemaless. Setiap relasional database yang mungkin, tapi tidak setiap basis data.
Pasang kembali Monica - dirkk

1
@dirkk Tidak memikirkan itu. Memperbaiki jawabanku.
Ixrec

17

Abstraksi bocor

Anda dapat menerapkan sistem deklaratif di mana Anda menyatakan apa yang Anda inginkan, dan kompilator atau penerjemah menemukan urutan eksekusi. Manfaat teoretisnya adalah membebaskan Anda dari keharusan memikirkan 'bagaimana', dan Anda tidak perlu merinci implementasi ini. Namun, dalam praktiknya untuk komputasi tujuan umum Anda masih harus berpikir tentang 'bagaimana' dan menulis semua jenis trik sambil tetap mengingat bagaimana ini akan diterapkan, karena jika tidak kompiler dapat (dan sering akan) memilih implementasi yang akan sangat, sangat, sangat lambat (mis. operasi n! di mana n sudah cukup).

Dalam contoh khusus Anda, Anda akan mendapatkan A algoritma sorting - itu tidak berarti bahwa Anda akan mendapatkan yang baik atau bahkan satu agak digunakan. Definisi yang Anda berikan, jika diterapkan secara harfiah (sebagai kompiler kemungkinan akan) menghasilkan http://en.wikipedia.org/wiki/Bogosort yang tidak dapat digunakan untuk kumpulan data yang lebih besar - secara teknis benar, tetapi membutuhkan keabadian untuk mengurutkan seribu angka .

Untuk beberapa domain terbatas, Anda dapat menulis sistem yang hampir selalu berhasil dalam menentukan implementasi yang baik, misalnya, SQL. Untuk komputasi tujuan umum yang tidak bekerja dengan baik - Anda dapat menulis sistem di, katakanlah, Prolog tetapi Anda harus memvisualisasikan bagaimana sebenarnya deklarasi Anda akan dikonversi menjadi perintah eksekusi yang penting pada akhirnya, dan yang kehilangan banyak deklaratif yang diharapkan manfaat pemrograman.


Meskipun apa yang Anda katakan pada dasarnya benar, kinerja yang buruk bukan merupakan tanda abstraksi yang bocor kecuali antarmuka / kontrak memberi Anda jaminan misalnya tentang waktu eksekusi.
valenterri

3
Peters tidak mengatakan bahwa kinerja buruk adalah tanda abstraksi yang bocor, @valenterry. Jika ada, ia mengatakan sebaliknya: bahwa untuk mencapai kinerja yang baik, detail implementasi terpaksa bocor.
itsbruce

2
Saya pikir itu menyesatkan untuk mengatakan bahwa abstraksi bocor hanya karena Anda perlu memahami implementasi untuk memahami bagaimana itu mempengaruhi kinerja. Tujuan abstraksi bukan untuk melindungi Anda dari keharusan memikirkan kinerja.
Doval

1
@ jamesqf Dalam pemrograman deklaratif, Anda hanya akan menyatakan bahwa ada sesuatu yang diurutkan. Anda dapat mendeklarasikan urutan sortir terikat ke beberapa variabel / properti. Dan kemudian itu akan terjadi. Tidak perlu memanggil sortir secara eksplisit setiap kali data baru ditambahkan atau mengurutkan perubahan pesanan.
hyde

1
@ jamesqf Anda tidak dapat benar-benar melihat intinya tanpa benar-benar mencoba sendiri (Saya akan merekomendasikan QML dari Qt untuk bermain dengan ide-ide deklaratif). Bayangkan seseorang yang hanya tahu pemrograman imperatif, dan mereka mencoba memahami titik OOP atau pemrograman fungsional tanpa benar-benar mencobanya.
hyde

11

Desidabilitas komputasi adalah alasan terpenting mengapa pemrograman deklaratif belum terbukti semudah kelihatannya.

Banyak masalah yang relatif mudah dinyatakan telah terbukti tidak dapat diputuskan atau memiliki kompleksitas NP-complete untuk dipecahkan. Ini sering terjadi ketika kita memperhitungkan kelas dan klasifikasi negatif, kemampuan menghitung dan rekursi.

Saya ingin mencontohkan ini dengan beberapa domain yang terkenal.

Keputusan tentang kelas CSS mana yang akan digunakan membutuhkan pengetahuan dan pertimbangan semua aturan CSS. Menambahkan aturan baru mungkin membatalkan semua keputusan lain. Kelas CSS negatif sengaja tidak ditambahkan ke bahasa, karena masalah NP-complete, tetapi kurangnya kelas negatif mempersulit keputusan desain CSS.

Di dalam pengoptimal kueri (SQL), ada masalah tidak jelas dalam memutuskan untuk bergabung, indeks mana yang digunakan dan memori mana yang dialokasikan untuk hasil sementara mana. Ini adalah masalah NP-complete yang diketahui dan menyulitkan desain-database dan formulasi kueri. Untuk memformulasikannya secara berbeda: saat mendesain basis data atau kueri, perancang perlu mengetahui tindakan dan urutan tindakan yang cenderung dilakukan oleh pengoptimal kueri. Seorang insinyur berpengalaman membutuhkan pengetahuan tentang heuristik yang digunakan oleh vendor database utama.

File konfigurasi bersifat deklaratif, tetapi konfigurasi tertentu sulit untuk dideklarasikan. Misalnya, untuk mengkonfigurasi fitur dengan benar, seseorang perlu mempertimbangkan versi akun, penyebaran (dan riwayat penerapan), kemungkinan penggantian manual dan kemungkinan konflik dengan pengaturan lain. Untuk memvalidasi konfigurasi dengan benar mungkin menjadi masalah NP-complete.

Hasilnya adalah bahwa komplikasi ini mengejutkan pemula, mereka merusak 'keindahan' pemrograman deklaratif dan menyebabkan beberapa insinyur mencari solusi lain. Migrasi insinyur yang tidak berpengalaman dari SQL ke NoSQL mungkin telah dipicu oleh kompleksitas yang mendasari database relasional.


2
"Kelas CSS negatif sengaja tidak ditambahkan ke bahasa, karena masalah NP-complete" - dapatkah Anda menguraikan?
John Dvorak

Ini sedikit latihan, tetapi dengan pemilih CSS negatif adalah mungkin untuk menulis ulang ini menjadi masalah 3SAT (dengan klausa terakhir adalah DOM), yang akan membutuhkan mencoba semua kombinasi yang mungkin, untuk melihat apakah cocok.
Dibbeke

1
Selain kecil. Di CSS 3 dan 4, penyeleksi negatif diizinkan, tetapi: tidak pseudo-kelas mungkin tidak bersarang.
Dibbeke

2

Kami memiliki perbedaan dalam declarativeness bahasa pemrograman yang digunakan dengan baik dalam verifikasi logika digital.

Biasanya logika digital dijelaskan pada level transfer register (RTL) di mana level logika sinyal antara register didefinisikan. Untuk memeriksa bahwa kami semakin menambahkan properti yang didefinisikan dengan cara yang lebih abstrak dan deklaratif.

Salah satu bahasa yang lebih deklaratif / himpunan bagian bahasa disebut PSL untuk Bahasa Spesifikasi Properti. Saat menguji model RTL dari pengali di mana, misalnya semua operasi logika shift dan penambahan beberapa clock cycle perlu ditentukan; Anda dapat menulis properti dengan cara assert that when enable is high, this output will equal the multiplication of these two inputs after no more than 8 clock cycles. Deskripsi PSL kemudian dapat diperiksa bersama-sama dengan RTL dalam simulasi, atau PSL dapat secara resmi terbukti tahan untuk deskripsi RTL.

Model PSL yang lebih deklaratif memaksa seseorang untuk menggambarkan perilaku yang sama dengan deskripsi RTL tetapi dengan cara yang cukup berbeda yang dapat secara otomatis diperiksa terhadap RTL untuk melihat apakah mereka setuju.


1

Sebagian besar masalahnya adalah bagaimana Anda memodelkan data; dan pemrograman deklaratif tidak membantu di sini. Dalam bahasa imperatif Anda sudah memiliki banyak perpustakaan yang melakukan banyak hal untuk Anda, jadi Anda hanya perlu tahu harus menelepon apa. Dengan cara tertentu orang mungkin mempertimbangkan pemrograman deklaratif ini (mungkin contoh terbaik untuk ini adalah Stream API di Java 8 ). Setelah ini, abstraksi sudah diselesaikan dan pemrograman deklaratif tidak diperlukan.

Juga, seperti yang telah dikatakan, bahasa pemrograman logika sudah melakukan apa yang Anda inginkan. Orang mungkin mengatakan masalahnya adalah kinerja, tetapi dengan perangkat keras dan penelitian saat ini di bidang ini, hal-hal dapat ditingkatkan untuk siap digunakan untuk produksi; sebenarnya Prolog digunakan untuk hal-hal AI, tapi saya percaya hanya oleh akademisi.

Perlu dicatat bahwa ini berlaku untuk bahasa pemrograman untuk tujuan umum. Untuk bahasa spesifik domain, bahasa deklaratif jauh lebih baik; SQL mungkin adalah contoh terbaik.


3
Pemodelan data? Anda memilih imperatif hal terburuk. Bahasa fungsional deklaratif seperti Haskell dan ML unggul dalam pemodelan data. Tipe data aljabar dan tipe data rekursif, misalnya, biasanya dapat didefinisikan secara komprehensif dalam satu atau dua baris. Tentu, Anda masih memiliki fungsi untuk menulis tetapi kodenya mengikuti dari definisi tipe dan dibatasi olehnya. Perbandingan yang aneh untuk dibuat.
itsbruce

1
@itsbruce Masalahnya adalah kebanyakan data nyata tidak mudah dipetakan ke ADT; pikirkan bagaimana kebanyakan database bekerja. Sebagai Prolog - Erlang, Anda benar, mereka adalah bahasa yang berbeda. Saya menyebutkan bahwa satu berfungsi sementara yang lain logis tetapi lebih baik jika saya menghapus seluruh perbandingan.
m3th0dman

1
@ m3th0dman Basis data hanya satu ton tupel / catatan. Haskell agak lumpuh di sana, karena tidak memiliki catatan, tetapi memang memiliki tupel, dan ML memiliki keduanya. Dan dalam kasus Haskell, jumlah boilerplate yang diperlukan untuk mendeklarasikan datatype pseudo-record baru masih jauh lebih kecil daripada yang diperlukan untuk membuat struktur palsu dalam rata-rata bahasa OOP yang diketik secara statis. Bisakah Anda menguraikan bagaimana sebagian besar data tidak mudah dipetakan ke ADT?
Doval

1
@ m3th0dman Ah, itu sebabnya skema database didefinisikan dalam bahasa imperatif yang cocok untuk tugas tersebut. Oh, tidak, itu akan menjadi DDL deklaratif. Faktanya, keseluruhan proses pemodelan data relevan dengan aplikasi yang akan bekerja dengannya, aliran data dan struktur, bukan bahasa yang mengimplementasikan aplikasi. Kadang-kadang terdistorsi agar sesuai dengan fitur OO bahasa dan apa yang didukung ORM-nya tapi itu biasanya hal yang buruk, bukan fitur. Bahasa deklaratif lebih cocok untuk mengekspresikan model data konseptual / logis.
itsbruce

1
@itsbruce Saya tidak mengatakan bahwa paradigma prosedural lebih baik daripada paradigma deklaratif dalam mendefinisikan data; Saya mengatakan bahwa paradigma deklaratif tidak lebih baik (atau lebih buruk) daripada paradigma prosedural (untuk bahasa tujuan umum). Adapun memanipulasi data, bagian deklaratif dari SQL tidak cukup untuk aplikasi kehidupan nyata; kalau tidak, tidak ada yang akan menemukan dan menggunakan ekstensi prosedural. Mengenai artikel itu, saya tidak setuju dengan itu dari abstrak di mana ia bertentangan dengan Brooks; dia membangun ide-idenya dari proyek nyata sementara orang-orang itu tidak membangun sesuatu yang luar biasa untuk membuktikan teori mereka.
m3th0dman

0

Akan terlihat seperti ini .. {(apa pun => membaca file & panggil url) | panggil url & baca file} Namun, ini adalah tindakan yang harus dilakukan, dan keadaan sistem berubah sebagai hasilnya, tetapi itu tidak jelas dari sumbernya.

Deklaratif dapat menggambarkan mesin negara yang terbatas dan transisinya. FSM seperti kebalikan dari deklaratif tanpa tindakan, bahkan jika satu-satunya tindakan adalah mengubah negara ke negara berikutnya.

Keuntungan menggunakan metode ini adalah bahwa transisi dan tindakan dapat ditentukan oleh predikat yang berlaku untuk banyak transisi, bukan hanya satu.

Saya tahu ini terdengar agak aneh, tetapi pada tahun 2008 saya menulis program generator yang menggunakan metode ini, dan C ++ yang dihasilkan adalah 2 hingga 15 kali lebih banyak dari sumbernya. Saya sekarang memiliki lebih dari 75.000 baris C ++ dari 20.000 baris input. Dua hal sesuai dengan ini: konsistensi dan kelengkapan.

Konsistensi: Tidak ada dua predikat yang dapat menjadi benar pada saat yang sama dapat menyiratkan tindakan yang tidak konsisten, karena keduanya x = 8 dan x = 9, atau keadaan berikutnya yang berbeda.

Kelengkapan: Logika untuk setiap transisi negara ditentukan. Ini mungkin sulit untuk memeriksa sistem dengan substrat N, dengan status> 2 ** N, tetapi ada metode kombinatorial yang menarik yang dapat memverifikasi semuanya. Pada tahun 1962 saya menulis fase 1 semacam sistem untuk mesin 7070, menggunakan semacam ini pembuatan kode kondisional dan debug kombinatorial. Dari 8.000 baris dalam semacam itu, jumlah bug dari hari rilis pertama selamanya adalah nol!

Fase dua semacam itu, 12.000 baris, memiliki lebih dari 60 kesalahan dalam dua bulan pertama. Ada banyak lagi yang bisa dikatakan tentang ini, tetapi berhasil. Jika pabrikan mobil menggunakan metode ini untuk memeriksa firmware, kami tidak akan melihat kegagalan yang kami lihat sekarang.


1
Ini benar-benar tidak menjawab pertanyaan awal. Bagaimana faktor konsistensi dan kelengkapan menjadi fakta bahwa sebagian besar pemrograman masih bersifat prosedural, bukan deklaratif?
Jay Elston

Paragraf pembuka Anda tampaknya menjadi jawaban untuk suatu titik dalam programer jawaban arnaud.stackexchange.com/a/275839/67057 , bukan untuk pertanyaan itu sendiri. Itu seharusnya komentar di sana (di layar saya, jawaban Anda tidak lagi di bawahnya, untuk satu hal). Saya pikir sisa jawaban Anda adalah ilustrasi tentang bagaimana sejumlah kecil kode deklaratif dapat menghasilkan sejumlah besar kode imperatif yang setara tetapi tidak jelas. Jawaban Anda perlu dirapihkan, terutama terkait dengan poin-poin penting.
itsbruce

-3

Tidak semuanya bisa direpresentasikan secara deklaratif.

Seringkali, Anda secara eksplisit ingin mengontrol aliran eksekusi

Sebagai contoh mengikuti pseudo-code: if whatever read a file call an URL else call an URL write a file Bagaimana Anda mewakilinya secara deklaratif?

Tentu, mungkin ada beberapa cara eksotis untuk melakukannya. Seperti monad . Tetapi ini biasanya lebih rumit, rumit dan jauh lebih tidak intuitif daripada bagian prosedural mereka.

Semuanya bermuara pada kenyataan bahwa "berinteraksi" dengan lingkungan / sistem Anda tidak bersifat deklaratif. Segala sesuatu yang berkaitan dengan I / O pada dasarnya prosedural. Anda harus tahu persis kapan dan apa yang harus terjadi, dan dalam urutan apa.

Deklaratif bagus untuk segala sesuatu yang murni terkait dengan perhitungan. Seperti fungsi raksasa, Anda memasukkan X dan Anda mendapatkan Y. Itu bagus. Contoh untuk ini adalah HTML, input adalah teks, outputnya adalah apa yang Anda lihat di browser Anda.


2
Saya tidak membeli ini. Mengapa teladan Anda tidak deklaratif? Apakah ini if/ else, dalam hal apa alternatif deklaratif akan terlihat? Ini jelas bukan bagian read/ write/ call, karena mereka adalah daftar nilai deklaratif yang bagus (jika Anda menyiratkan mereka dibungkus {...; ...}, mengapa tidak menyiratkan mereka dibungkus [..., ...]?) Tentu saja, daftar hanyalah monoids gratis; banyak orang lain juga akan melakukannya. Saya tidak mengerti mengapa monad relevan di sini; mereka hanya API. Haskell beralih dari stream -> monads untuk membantu komposisi manual, tetapi bahasa logika dapat menyusun daftar secara otomatis.
Warbo

2
-1 untuk Monads saja. 1. Mereka tidak benar-benar eksotis (daftar dan set adalah Monads dan semua orang menggunakannya). 2. Mereka tidak ada hubungannya dengan memaksa hal-hal yang harus dilakukan dalam urutan tertentu (Haskell melakukan notasi penampilan imperatif tapi tidak). Bahasa deklaratif / fungsional menentukan hubungan dan dependensi. Jika fungsi X membutuhkan input Y, Y akan dihasilkan sebelum X. Dapatkan dependensi yang benar dan urutan kejadian yang tepat akan menentukan sendiri. Banyak interaksi didorong oleh peristiwa , bukan dalam satu rangkaian urutan. Bahasa deklaratif tidak membuat reaksi terhadap peristiwa lebih sulit.
itsbruce

Kemalasan menyulitkan beberapa hal tetapi kemalasan bukan bagian dari definisi bahasa Deklaratif, yang sebagian besar tidak menggunakannya. Dan pada mereka yang melakukannya, cara untuk menjamin evaluasi tidak ada hubungannya dengan monad. Untuk contoh di mana bahasa deklaratif digunakan secara eksklusif untuk interaksi daripada perhitungan abstrak, tidak menentukan urutan tetapi memastikan bahwa hal yang benar terjadi secara berurutan, tidak terlihat lagi selain Puppet DSL. Yang memiliki bonus bahwa hanya hal-hal yang perlu terjadi - bukan sesuatu yang imperatif membuat bahasa mudah.
itsbruce

1
Selain @itsbruce contoh pemrograman reaktif adalah mempertimbangkan deklaratif dan tentang interaksi dengan lingkungan.
Maciej Piechotka
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.