Apakah Lisp masih memiliki fitur khusus yang TIDAK diadopsi oleh bahasa pemrograman lain?

35

Apakah Lisp masih memiliki fitur khusus yang TIDAK diadopsi oleh bahasa pemrograman lain?

Dengan Lisp, maksud saya semua bahasa pemrograman Lisp secara keseluruhan. Saya telah diberitahu betapa menakjubkannya Lisp dan tahu bahwa banyak bahasa telah terinspirasi oleh Lisp. Tetapi apakah Lisp masih memiliki fitur desain eksklusif yang tidak dapat dilakukan dalam bahasa lain?

Alasan saya mengajukan pertanyaan adalah bahwa baru-baru ini, sebagai programmer amatir, saya mulai belajar Clojure hanya untuk bersenang-senang, dan hasilnya adalah saya menemukan banyak posting dan komentar terkait Lisp, hanya mengatakan satu hal: "Lisp unik ", tetapi bahasa pemrograman modern lainnya telah mengadopsi dan mencuri banyak ide dari Lisp, seperti persyaratan, rekursi, dan fungsi sebagai warga negara kelas satu. Dan bahkan metaprogramming dapat dilakukan oleh banyak bahasa.

Apakah saya kehilangan sesuatu dan apakah "Lisp masih berbeda"?

Atau saya beruntung karena bahasa modern lain telah mencuri semua bagian yang bagus dari Lisp sehingga tidak perlu menggali ke dalam kurung dunia Lisp , dan "Lisp berbeda".

iceX
sumber
3
Berbagi penelitian Anda membantu semua orang. Beri tahu kami apa yang telah Anda coba dan mengapa itu tidak memenuhi kebutuhan Anda. Ini menunjukkan bahwa Anda telah meluangkan waktu untuk mencoba membantu diri sendiri, itu menyelamatkan kami dari mengulangi jawaban yang jelas, dan yang paling utama itu membantu Anda mendapatkan jawaban yang lebih spesifik dan relevan. Lihat juga Cara Meminta
nyamuk
3
@gnat Thx untuk saran, dan saya telah memperbarui pertanyaan saya :)
iceX
10
Satu masalah adalah bahwa, begitu suatu bahasa memiliki subset tertentu dari fitur Lisp (misalnya, ekspresi-S dan makro), orang-orang mengklaim itu adalah Lisp. Yang tentu saja memiliki konsekuensi bahwa (menurut orang-orang ini) tidak ada bahasa non-Lisp dapat memiliki fitur ini.
9
Saya kira tidak ada bahasa lain di mana kurung bulat adalah satu-satunya bentuk pengelompokan untuk semuanya :-)
Doc Brown
Gangguan sebagai sebuah keluarga mungkin tidak terlalu unik, tetapi banyak dialek cadel (Racket, CL, Scheme, Clojure) masih menawarkan banyak fitur yang berguna / unik.
Daniel Gratzer

Jawaban:

28

Referensi kanonik untuk jenis pertanyaan ini adalah Apa yang Membuat Lisp Paul Graham Berbeda . Dua fitur utama yang tersisa dari Lisp yang tidak tersedia secara luas, menurut artikel ini pada saat penulisan, adalah:

8. Notasi untuk kode menggunakan pohon simbol.

9. Seluruh bahasa selalu tersedia. Tidak ada perbedaan nyata antara waktu baca, waktu kompilasi, dan runtime. Anda dapat mengkompilasi atau menjalankan kode saat membaca, membaca atau menjalankan kode saat kompilasi, dan membaca atau mengkompilasi kode saat runtime.

Komentar membahas setiap titik dan nama bahasa populer di mana fitur itu tersedia.

8, yang (dengan 9) adalah apa yang membuat Lisp macro dimungkinkan, sejauh ini masih unik untuk Lisp, mungkin karena (a) ia membutuhkan parens-parens itu, atau sesuatu yang sama buruknya, dan (b) jika Anda menambahkan kenaikan daya terakhir , Anda tidak lagi dapat mengklaim telah menemukan bahasa baru, tetapi hanya merancang dialek baru Lisp; -)

Perhatikan bahwa artikel ini terakhir kali direvisi pada tahun 2002, dan dalam 11 tahun terakhir telah ada berbagai bahasa baru, beberapa di antaranya dapat menggabungkan semua fitur Lisp ini ke dalam desain mereka.

Greg Hewgill
sumber
2
Fitur-fitur itu tidak unik untuk Lisp (dan varian yang diturunkan langsung), dan belum pernah cukup lama.
Donal Fellows
21
@iceX: Perbedaan antara JavaScript dan bahasa seperti Lisp, Smalltalk, Self, Newspeak, APL, Factor, Forth, dll. adalah bahwa di JavaScript, program "mati". Itu adalah file teks. Anda mematikan program yang sedang berjalan, mengedit file teks, lalu memulai salinan program yang sama sekali baru. Di lingkungan lain (yang disebut lingkungan "hidup"), Anda tidak pernah menghentikan program yang sedang berjalan, program yang sedang berjalan itu sendiri adalah sekumpulan objek dalam memori yang Anda manipulasi dengan cara yang sama seperti Anda memanipulasi objek lain, ketika sedang berjalan . (Catatan: ini tidak berlaku untuk Clojure, tetapi kebanyakan Lisps yang lebih tua melakukannya dengan cara ini.)
Jörg W Mittag
2
@ JörgWMittag Wow ... Jadi, bahasa pemrograman seperti Clojure, Clojurescript, lispyscript sebenarnya bukan "real lisp" karena mereka tidak dapat mengubah kode mereka seperti yang dilakukan Lisp sekolah lama, seperti halnya Common Lisp. Tapi ... jika mereka tidak bisa mengubahnya ... mengapa repot-repot menggunakan ekspresi S yang saya pikir adalah untuk tujuan manipulasi kode ... (merasa seperti saya baru saja jatuh ke dalam lubang kelinci yang dalam dan gelap)
iceX
4
@iceX: Banyak bahasa memiliki evalatau serupa, dan beberapa dapat melakukan metaprogramming, misalnya Haskell's Template Haskell. Hal unik (yang bisa dibilang) tentang Lisp adalah bahwa representasi untuk data, kode, dan meta-kode sama - tidak hanya dalam sintaksis, tetapi sebenarnya adalah hal yang sama.
tdammers
2
@iceX Eval hanya satu bagian saja, tetapi tidak semuanya. Di Lisp Anda dapat mengeksekusi kode pada waktu kompilasi. Anda dapat mengeksekusi kode pada waktu baca. Ya clojure mendukung semua dinamika Lisp, ia memiliki makro, makro pembaca dan eval, serta kemampuan untuk melampirkan REPL ke program yang sedang berjalan untuk memodifikasinya dengan cepat.
stonemetal
15

Pertanyaannya adalah yang sulit dijawab, karena seseorang harus mengetahui semua bahasa untuk mengetahui bahwa tidak ada yang lain yang memiliki fitur tertentu di Lisp, jadi yang berikut ini didasarkan pada bahasa yang saya alami.

Dari atas kepala saya, kondisi adalah sesuatu yang belum saya lihat dalam bahasa lain. Pikirkan 'pengecualian', tetapi di mana tumpukan panggilan tidak dibatalkan, dan di mana penelepon dapat mengirim nilai pemulihan ke situs pengecualian, tetapi tanpa mengganggu tumpukan panggilan di antara penangan dan sumber pengecualian. Agar adil, ini sebenarnya hanyalah aplikasi khusus kelanjutan, jadi Ruby dan Skema (setidaknya) dapat melakukan ini.

Sistem makro Lisp diuntungkan dari keteraturan / homoiklikositas, tetapi Scala berencana untuk memasukkannya sebagai fitur stabil di 2.12 dan Template Haskell mengklaim fitur serupa. Saya berpendapat bahwa mereka akan lebih kompleks secara sintaksis daripada dengan Lisp, tetapi pembuatan kode waktu kompilasi ada di sana.

Kalau dipikir-pikir itu, meskipun, membangun lurus bentuk hanya satu jenis makro yang tersedia di Lisp: Saya belum melihat setara dengan kompiler atau makro pembaca di tempat lain.

Kemampuan beberapa dialek (misalnya SBCL ) untuk menyimpan gambar proses yang lengkap dan dapat dilanjutkan kembali itu keren, tetapi sekali lagi itu tidak unik: Smalltalk telah melakukan itu selama beberapa dekade.

Banyak bahasa lain memungkinkan penetapan destruksi ketika mengembalikan array, tetapi pendekatan # 'values ​​dan #' multiple-value-bind / let-values ​​tampaknya masih spesifik untuk Common Lisp dan Skema (yang masih bisa melakukan destruksi 'reguler' juga ). 'Wantarray' Perl memungkinkan suatu fungsi untuk menentukan apakah itu dipanggil dalam konteks skalar, daftar, atau batal sehingga dapat menyesuaikan nilai kembalinya dengan cara yang mirip (-ish), tetapi saya belum melihat 'benar' beberapa nilai pengembalian di luar Skema / CL.

Dalam hal fitur bahasa, mungkin tidak banyak yang bisa dilakukan Lisp yang bahasa lain tidak bisa (Turing kelengkapannya seperti apa adanya). Apa itu adalah , bagaimanapun, adalah bahasa di mana kode tersebut dinyatakan dalam struktur data sendiri, membuat Big Idea ™ -yang kode data sesuatu yang relatif mudah untuk bekerja dengan.

Danny Woods
sumber
3
Makro scala jauh kurang kuat daripada makro Lisp, serta makro TH, makro higienis Skema, dll. Sistem yang sama kuatnya dapat ditemukan di MetaLua dan Converge.
SK-logic
4

Setelah begitu banyak dekade, saya tidak berpikir ada sesuatu yang eksklusif untuk Lisp. Tetapi bahkan hari ini, ada banyak hal menarik yang sulit ditemukan di luar Lisps. Beberapa hal yang terlintas dalam pikiran:

  • Sistem objek berkualitas tinggi dengan protokol meta canggih (yaitu CLOS) tidak populer dari jarak jauh.
  • multi-metode muncul dari waktu ke waktu di suatu tempat, tetapi kebanyakan orang tidak pernah mendengarnya.
  • Seperti yang telah ditunjukkan orang lain, sistem kondisinya cukup canggih dibandingkan dengan mekanisme penanganan pengecualian yang populer.
  • Representasi ringkas dari semantik bahasa (eval), suatu pendekatan yang memberdayakan untuk mendefinisikan bahasa seseorang dan membuatnya tersedia untuk adaptasi mendalam secara langsung (lihat SICP ) - fungsi "eval" dari bahasa populer saat ini tidak memiliki sifat yang sama.

Akhirnya, ada banyak lagi yang bisa dipelajari dari Lisp yang bukan tentang bahasa itu sendiri tetapi menjadi bagian dari sejarah Lisp dan tersesat dalam waktu. Misalnya Interlisp, Genera Simbolik, dll ... jika Anda tidak pernah menggunakan Genera, lihat utas comp.lang.lisp ini di mana Kent Pitman menjelaskan bagaimana "Emacs hanyalah bayangan pucat dari Zmacs Genera" - yang semuanya diaktifkan oleh memiliki sistem Lisp yang kuat yang merupakan bagian dari Zmacs, yang dijalankan pada Mesin Lisp.

Thiago Silva
sumber
Saya belum pernah melihat penjelasan yang baik tentang multimethod yang membedakannya dari metode kelebihan beban , fitur standar di hampir setiap bahasa imperatif modern, kecuali oleh fakta bahwa pengiriman multimethod diselesaikan secara dinamis saat runtime dan karenanya jauh lebih lambat daripada menggunakan metode kelebihan beban, yang diselesaikan pada waktu kompilasi.
Mason Wheeler
Mereka memiliki perbedaan penting. Jika Anda kesulitan menemukan sumber daya tentang itu, Anda selalu dapat membuat pertanyaan baru di sini ..
Thiago Silva
Julia memiliki banyak metode, dan polimorfisme parametrik Haskell adalah sejenis metode ganda. Ada banyak cara untuk mensimulasikan banyak metode dalam banyak bahasa. Sistem kondisi adalah sesuatu yang benar-benar saya inginkan terutama (edit dan lanjutkan, meskipun saya sudah melihatnya untuk C # debuggers).
aoeu256
4

Itu belum tentu fitur tunggal . Seluruh tampilan dan nuansa, dan bagaimana set fitur tertentu bekerja bersama.

JavaScript atau Java memiliki banyak fitur Lisp (mesin virtual, kompiler / evaluator, pengumpulan sampah, dll.). Tetapi JavaScript misalnya tidak memiliki bagian pemrograman simbolis, tidak memiliki kemampuan matematika (secara internal ia hanya mengapung), tidak memiliki penanganan kesalahan, dan sebagainya.

Banyak sistem Common Lisp dioptimalkan untuk cara pengembangan di mana seseorang memperluas perangkat lunak baru secara bertahap, dengan memperluas bahasa Lisp dalam berbagai dimensi menggunakan berbagai teknik pemrograman meta - tanpa me-restart perangkat lunak untuk waktu yang lama. Karena itu ia harus fleksibel dan dapat diperpanjang - tetapi pada saat yang sama ia harus kuat. Mengubah bahasa (makro pada dasarnya adalah cara bagi pengguna untuk memperluas kompiler) tanpa membuat program macet.

Sekarang sesuatu seperti JavaScript juga digunakan untuk memperluas program, biasanya browser web. Tetapi sebagian besar waktu seseorang tidak banyak meta-pemrograman dalam JavaScript - selain beberapa peretasan OOP .

Contoh:

Seseorang dapat mengimplementasikan perangkat lunak matematika umum umum untuk domain aljabar komputer dalam dua cara: menulis mesin dalam bahasa C dengan bahasa khusus di atas (seperti Mathematica ) atau dalam beberapa dialek Lisp yang lebih maju. Macsyma / Maxima dalam Common Lisp, Reduce in Standard Lisp, Aksioma dalam Common Lisp.

(Ada juga satu atau lebih yang ditulis dengan Python.)

Tidak banyak sistem yang menawarkan serangkaian fitur seperti Axiom , yang berjalan di atas Common Lisp.

Apa yang membuat Lisp menarik untuk jenis aplikasi ini adalah campuran fitur: matematika dasar lanjutan (bignum, rasio, ...), perhitungan simbolik, kompiler interaktif, dll. Sangat mungkin untuk mendapatkan hal-hal ini dengan mengimplementasikannya dalam bahasa tingkat Dengan begitu, seseorang akan menerapkan 50% atau lebih dari sistem Lisp khas.

Rainer Joswig
sumber
2

Tidak sejauh yang saya ketahui. Keempat dengan mudah sama dinamisnya dengan Lisp, mungkin lebih dari itu karena kode dinamis di Forth terlihat seperti kode Keempat biasa sedangkan makro Lisp cenderung menggunakan fitur yang berbeda dari kode Lisp biasa (di Clojure setidaknya saya belum pernah menggunakan kutipan sintaks di luar makro) dan akibatnya mereka terlihat sangat berbeda dari kode Lisp biasa. Sebagai contoh seberapa dinamis Forth, berikut adalah cara untuk mengimplementasikan komentar di Forth :

: (   41 word drop ; immediate
( That was the definition for the comment word. )
( Now we can add comments to what we are doing! )
stonemetal
sumber
1
Betapa menyenangkannya Forth, saya selalu menganggapnya buram dan canggung, mungkin karena ini berbasis tumpukan dan semuanya terbalik.
Robert Harvey
2
Karena penasaran, apa yang Anda maksud dengan 'dipisahkan dari bagian utama bahasa'? Makro di Lisp memiliki akses penuh ke semua fungsi yang ditentukan pada titik makro didefinisikan, yang mana saja dapat digunakan untuk membangun formulir yang makro diperluas. Ini dapat melibatkan informasi yang diambil dari database dan / atau server. Contoh komentar Anda, dapat didefinisikan sebagai: (komentar defmacro (& badan istirahat)), bukan?
Danny Woods
1
@DannyWoods Maksudku makro tidak terlihat seperti kode biasa. Paling tidak di clojure Anda dapat memberi tahu kode makro dari kode biasa karena sangat menggunakan kutipan sintaks, splicing tanda kutip, dll yang tidak biasa dalam kode biasa. Contoh kode yang saya berikan tampak seperti kode normal sampai Anda melihat langsung. Membaca ulang jawaban saya itu hanya diungkapkan dengan buruk.
stonemetal
1
@stonemetal Tidak perlu khawatir, tetapi perlu dicatat bahwa tidak ada makro khusus tentang kutipan sintaks, baik Common Lisp atau Clojure. Kadang-kadang nyaman untuk memiliki ekspresi backtick dalam definisi fungsi reguler, dan badan makro dapat dibangun secara manual dengan daftar sederhana (walaupun Anda hanya perlu melakukan ini sekali atau dua kali untuk memutuskan bahwa kutipan sintaks adalah hal yang baik!)
Danny Woods
1
Agar adil, hal yang sama dapat dilakukan di Lisp, dengan mendaftarkan makro pembaca kustom.
fjarri
2

Lisp memiliki banyak dialek, dan masing-masing memiliki serangkaian fitur sendiri. Fitur favorit saya yang tidak mungkin diadopsi oleh bahasa lain adalah "tumpukan spaghetti" dari Interlisp .

Tumpukan spaghetti seperti penutupan, tetapi pada steroid. Ini tidak hanya menyimpan fungsi saat ini, tetapi seluruh konteks hingga bagian atas tumpukan. Sesuatu seperti co-rutin , kecuali bahwa Anda dapat membuatnya secara sewenang-wenang, menghasilkan hierarki konteks tumpukan.

ddyer
sumber
Tidak tahu itu, akan memeriksanya, terima kasih atas jawaban Anda :)
iceX
7
Apakah ini sama dengan kelanjutan Skema?
Nicola Musatti
1
@NicolaMusatti, "spaghetti stack" adalah strategi implementasi umum untuk kelanjutan seperti Skema (yang dapat dipanggil setelah fungsi yang membuatnya kembali).
Alex D