LISP (historis, LISP) adalah keluarga dari bahasa pemrograman komputer yang memiliki sejarah panjang dan notasi, awalan khas sepenuhnya kurung Polandia. Awalnya ditetapkan pada tahun 1958, LISP adalah tingkat tinggi tertua kedua bahasa pemrograman yang digunakan secara luas saat ini , hanya Fortran lebih tua (dengan satu tahun). Seperti Fortran, LISP telah berubah banyak sejak hari awal, dan sejumlah dialek telah ada lebih sejarahnya. Saat ini, tujuan umum yang paling banyak dikenal LISP dialek Common LISP, Scheme, dan Clojure.
LISP awalnya diciptakan sebagai notasi matematika praktis untuk program komputer, dipengaruhi oleh notasi kalkulus lambda Alonzo Gereja. Dengan cepat menjadi bahasa pemrograman favorit untuk buatan (AI) penelitian intelijen. Sebagai salah satu bahasa pemrograman paling awal, LISP memelopori banyak ide dalam ilmu komputer, termasuk struktur pohon data, manajemen penyimpanan otomatis, mengetik dinamis, dan compiler diri hosting.
Para LISP nama berasal dari “Pengolahan daftar”. Daftar link adalah salah satu struktur utama LISP bahasa ‘data, dan kode sumber LISP itu sendiri terdiri dari daftar. Akibatnya, program LISP dapat memanipulasi kode sumber sebagai struktur data, sehingga menimbulkan sistem makro yang memungkinkan programmer untuk membuat sintaks baru atau bahkan baru domain-spesifik bahasa tertanam dalam LISP.
Saling menukar kode dan data juga memberikan LISP sintaks langsung dikenali. Semua kode program ditulis sebagai s-ekspresi, atau kurung daftar. Sebuah panggilan fungsi atau bentuk sintaksis ditulis sebagai daftar dengan fungsi atau nama operator, dan argumen berikut, misalnya, fungsi f yang mengambil tiga argumen yang bisa disebut menggunakan (arg1 arg2 Arg3 f).
Sejarah
LISP diciptakan oleh John McCarthy pada tahun 1958 ketika ia berada di Institut Teknologi Massachusetts (MIT). McCarthy diterbitkan desain dalam makalah di Komunikasi ACM pada tahun 1960, berjudul “Fungsi Rekursif dari Ekspresi simbolik dan Komputasi mereka oleh Mesin, Bagian I” (“Bagian II” tidak pernah dipublikasikan). Dia menunjukkan bahwa dengan operator sederhana dan notasi untuk fungsi, seseorang dapat membangun sebuah bahasa Turing-lengkap untuk algoritma.
Informasi Pengolahan Bahasa adalah bahasa AI pertama, dari tahun 1955 atau 1956, dan sudah termasuk banyak konsep, seperti daftar-pengolahan dan rekursi, yang kemudian digunakan dalam LISP.
Notasi asli McCarthy digunakan tanda kurung “M-ekspresi” yang akan diterjemahkan ke dalam S-ekspresi. Sebagai contoh, mobil M-ekspresi [kontra [A, B]] setara dengan ekspresi S-(mobil (AB kontra)). Setelah LISP dilaksanakan, programmer cepat memilih untuk menggunakan S-ekspresi, dan M-ekspresi ditinggalkan. M-ekspresi muncul lagi dengan singkat upaya dari MLISP oleh Horace Enea dan CGOL oleh Vaughan Pratt.
LISP pertama kali diimplementasikan oleh Steve Russell pada komputer IBM 704. Russell telah membaca kertas McCarthy, dan menyadari (untuk kejutan McCarthy) bahwa fungsi LISP eval dapat diterapkan dalam kode mesin. Hasilnya adalah juru LISP kerja yang dapat digunakan untuk menjalankan program LISP, atau lebih baik, ‘mengevaluasi cadel ekspresi. “
Dua macro bahasa assembly untuk IBM 704 menjadi operasi primitif untuk membusuk daftar:. Mobil (Isi bagian Alamat nomor Register) dan cdr (Isi bagian Pengurangan jumlah Daftar). Dari konteksnya, jelas bahwa istilah “Register” digunakan di sini berarti “Memori Register”, saat ini disebut “Memori Lokasi”. Dialek LISP masih menggunakan mobil dan cdr
untuk operasi yang mengembalikan item pertama dalam daftar dan sisanya dari daftar masing-masing.
Lengkap pertama LISP compiler, yang ditulis dalam LISP, dilaksanakan pada tahun 1962 oleh Tim Hart dan Mike Levin di MIT. Kompiler ini memperkenalkan model LISP penyusunan incremental, dimana dikompilasi dan ditafsirkan fungsi mencampurkan bisa bebas. Bahasa yang digunakan di memo Hart dan Levin adalah lebih dekat dengan gaya LISP modern daripada kode sebelumnya McCarthy.
LISP adalah sistem sulit untuk diterapkan dengan teknik kompiler dan hardware saham tahun 1970-an. Rutinitas pengumpulan sampah, kemudian dikembangkan oleh-MIT mahasiswa pascasarjana Daniel Edwards, membuatnya praktis untuk menjalankan LISP pada tujuan umum sistem komputasi, tetapi efisiensi masih masalah.
Hal ini menyebabkan penciptaan mesin LISP: hardware khusus untuk menjalankan lingkungan LISP dan program. Kemajuan dalam kedua perangkat keras komputer dan teknologi compiler segera membuat mesin LISP obsoleteDuring 1980-an dan 1990-an, upaya besar dilakukan untuk menyatukan bekerja pada dialek LISP baru (kebanyakan penerus MacLISP seperti ZetaLISP dan NIL (Implementasi Baru LISP)) menjadi satu bahasa. Bahasa yang baru, Common LISP, agak kompatibel dengan dialek diganti (buku Common LISP Bahasa catatan kompatibilitas berbagai konstruksi). Pada tahun 1994, ANSI menerbitkan standar Common LISP, “ANSI Teknologi Pemrograman X3.226-1994 Informasi Bahasa Common LISP.”
Koneksi Ke Kecerdasan Buatan
Sejak awal, LISP berkaitan erat dengan komunitas riset kecerdasan buatan, terutama pada PDP-10 sistem. LISP digunakan sebagai pelaksanaan Planner bahasa pemrograman mikro yang digunakan dalam sistem AI terkenal SHRDLU. Pada 1970-an, sebagai AI penelitian melahirkan cabang komersial, kinerja sistem LISP yang ada menjadi isu yang berkembang.
Genealogi dan varian
Lebih dari lima puluh tahun sejarahnya, LISP telah melahirkan banyak variasi pada tema inti dari sebuah bahasa S-ekspresi. Selain itu, masing-masing dialek tertentu mungkin memiliki implementasi-untuk beberapa contoh, ada lebih dari selusin implementasi Common LISP.
Perbedaan antara dialek mungkin cukup terlihat-misalnya, Common LISP dan Scheme menggunakan kata kunci yang berbeda untuk mendefinisikan fungsi. Dalam dialek yang standar, namun demikian, implementasi sesuai mendukung bahasa inti yang sama, tetapi dengan ekstensi yang berbeda dan perpustakaan.
Secara historis signifikan dialek
LISP 1 – implementasi Pertama.
LISP 1,5 – Pertama luas versi, yang dikembangkan oleh McCarthy dan lain-lain di MIT. Dinamakan demikian karena berisi beberapa perbaikan pada penerjemah asli “LISP 1″, tapi bukan restrukturisasi besar sebagai LISP 2 direncanakan akan.
Stanford LISP 1,6 – Ini merupakan penerus LISP 1,5 dikembangkan di Stanford AI Lab, dan didistribusikan secara luas untuk PDP-10 sistem yang menjalankan sistem TOPS-10 operasi. Hal itu dianggap usang oleh MacLISP dan InterLISP.
MACLISP – dikembangkan untuk MIT Proyek MAC (tidak ada hubungannya dengan Apple Macintosh, atau untuk McCarthy), keturunan langsung dari LISP 1.5. Itu berlari pada PDP-10 dan sistem Multics. (MACLISP kemudian akan datang untuk disebut MacLISP, dan sering disebut sebagai MacLISP.)
InterLISP – dikembangkan di BBN Technologies untuk PDP-10 sistem yang menjalankan sistem operasi TENEX, kemudian diadopsi sebagai “pantai Barat” LISP untuk LISP Xerox mesin sebagai InterLISP-D. Versi kecil yang disebut “InterLISP 65″ diterbitkan untuk 6502 berbasis baris komputer Atari. Untuk beberapa waktu MacLISP dan InterLISP adalah pesaing kuat.
Franz LISP – awalnya sebuah proyek Berkeley, kemudian dikembangkan oleh Franz Inc Nama adalah deformasi lucu dari nama “Franz Liszt”, dan tidak merujuk ke Allegro Common LISP, dialek dari Common LISP dijual oleh Franz Inc, di lebih tahun terakhir.
XLISP, yang AutoLISP menjadi dasarnya.
Standard LISP dan Portable Standard LISP secara luas digunakan dan porting, terutama dengan Sistem Aljabar Komputer MENGURANGI.
ZetaLISP, juga dikenal sebagai LISP Mesin LISP – digunakan pada mesin-mesin LISP, keturunan langsung dari MacLISP. ZetaLISP memiliki pengaruh besar pada Common LISP.
LeLISP adalah dialek LISP Perancis. Salah satu Pembangun Antarmuka pertama ditulis dalam LeLISP.
Common LISP (1984), seperti yang dijelaskan oleh Common LISP Bahasa – sebuah upaya konsolidasi beberapa divergen (ZetaLISP, Spice LISP, NIL, dan S-1 LISP) untuk membuat pengganti dialek untuk MacLISP, dengan pengaruh substantif dari Skema dialek juga. Versi Common LISP yang tersedia untuk platform luas dan diterima oleh banyak orang sebagai standar de facto sampai publikasi ANSI Common LISP (ANSI X3.226-1994).
Dylan di versi pertama campuran Skema dengan Sistem Obyek Common LISP.
EuLISP – upaya untuk mengembangkan LISP efisien dan dibersihkan-up baru.
ISLISP – upaya untuk mengembangkan LISP efisien dan dibersihkan-up baru. Standar sebagai ISO / IEC 13816:1997 dan kemudian direvisi sebagai ISO / IEC 13816:2007: Teknologi informasi – Pemrograman bahasa, lingkungan mereka dan antarmuka sistem perangkat lunak – Pemrograman bahasa ISLISP.
Skema IEEE – IEEE standar, 1178-1990 (R1995)
ANSI Common LISP – sebuah standar American National Standards Institute (ANSI) untuk Common LISP, yang diciptakan oleh subkomite X3J13, menyewa kapal untuk memulai dengan Common LISP: Bahasa yang sebagai dokumen dasar dan bekerja melalui proses konsensus publik untuk mencari solusi untuk berbagi isu portabilitas program dan kompatibilitas implementasi Common LISP. Meskipun secara formal standar ANSI, pelaksanaan, penjualan, penggunaan, dan pengaruh dari ANSI Common LISP telah dan terus untuk dilihat seluruh dunia.
ACL2 atau “Sebuah Logika Komputasi untuk Common LISP aplikatif”, sebuah varian (efek samping gratis) aplikatif dari LISP Umum. ACL2 baik bahasa pemrograman di mana Anda dapat model sistem komputer dan alat untuk membantu membuktikan properti dari model-model.
Sejak tahun 2000
Setelah agak menurun pada 1990-an, LISP baru-baru ini mengalami kebangkitan yang menarik. Kebanyakan aktivitas baru difokuskan di sekitar implementasi open source dari Common LISP, dan termasuk pengembangan perpustakaan portabel baru dan aplikasi. Edisi cetak baru dari Common LISP Praktis oleh Peter Seibel, tutorial bagi programmer baru LISP, diterbitkan pada 2005 [18]. Ini tersedia gratis secara online.
Banyak baru LISP programer terinspirasi oleh penulis seperti Paul Graham dan Eric S. Raymond mengejar bahasa lain dianggap kuno. Baru LISP programmer sering menggambarkan bahasa sebagai pengalaman yang membuka mata dan mengklaim secara substansial lebih produktif daripada dalam bahasa lain [19]. Peningkatan kesadaran dapat dikontraskan dengan “musim dingin AI” dan keuntungan singkat LISP di pertengahan 1990-an [20].
Dan Weinreb daftar dalam survei tentang implementasi Common LISP [21] sebelas aktif dipertahankan Common LISP implementasi. Scieneer Common LISP adalah implementasi komersial baru bercabang dari CMUCL dengan rilis pertama pada tahun 2002.
Komunitas open source telah menciptakan infrastruktur pendukung baru: CLiki adalah sebuah wiki yang mengumpulkan informasi terkait Common LISP, direktori Common LISP daftar sumber daya, # cadel adalah saluran IRC populer (dengan dukungan oleh bot LISP yang ditulis), LISPpaste mendukung berbagi dan komentar dari potongan kode, Planet LISP mengumpulkan isi dari berbagai LISP terkait blog, pada pengguna LISPForum mendiskusikan topik LISP, LISPjobs adalah layanan untuk mengumumkan tawaran pekerjaan dan ada layanan berita mingguan Berita, Mingguan LISP. Common-LISP.net adalah situs hosting untuk proyek open source Common LISP.
50 tahun LISP (1958-2008) telah dirayakan di LISP50 @ OOPSLA [22]. Ada pertemuan user biasa lokal di Boston, Vancouver, dan Hamburg. Kegiatan lainnya meliputi Rapat Bersama Eropa LISP, Eropa LISP Simposium dan Konferensi Internasional LISP.
Komunitas Skema secara aktif mempertahankan lebih dari dua puluh implementasi. Beberapa implementasi baru yang signifikan (Ayam, Gambit, Gauche, Ikarus, pencurian, Ypsilon) telah dikembangkan dalam beberapa tahun terakhir. Laporan Revised5 pada Skema Bahasa algorithmic [23] standar Skema diterima secara luas dalam komunitas Scheme. Permintaan Skema untuk proses Pelaksanaan telah menciptakan banyak perpustakaan standar kuasi dan ekstensi untuk Skema. Pengguna komunitas implementasi Skema individu terus tumbuh. Sebuah proses standardisasi bahasa baru dimulai pada 2003 dan menyebabkan standar Skema R6RS pada tahun 2007. Penggunaan akademis Skema untuk mengajar ilmu komputer tampaknya telah agak menurun. Beberapa universitas tidak lagi menggunakan Skema dalam kursus ilmu komputer pengantar mereka.
Ada beberapa dialek LISP baru: Arc, Nu, dan Clojure.
Mayor dialek
Dua dialek utama LISP digunakan untuk keperluan umum saat ini adalah pemrograman Common LISP dan Scheme. Bahasa ini merupakan pilihan desain berbeda secara signifikan.
Common LISP adalah penerus MacLISP. Pengaruh utama adalah LISP Mesin LISP, MacLISP, NIL, S-1 LISP, Spice LISP, dan Skema [24] Ia memiliki banyak fitur LISP Mesin LISP (dialek LISP besar digunakan untuk program Mesin LISP), tapi. Adalah dirancang untuk menjadi efisien diimplementasikan pada komputer pribadi atau workstation. Common LISP memiliki standar bahasa besar termasuk banyak built-in tipe data, fungsi, makro dan elemen bahasa lain, serta sistem objek (Common LISP Object System atau CLOS lebih pendek). Common LISP juga meminjam fitur tertentu dari Skema seperti scoping leksikal dan penutupan leksikal.
Skema (dirancang sebelumnya) adalah desain yang lebih minimalis, dengan satu set yang lebih kecil dari fitur standar tetapi dengan fitur implementasi tertentu (seperti ekor-panggilan optimasi dan continuations penuh) belum tentu ditemukan di Common LISP.
Skema adalah dialek tail-rekursif statis scoped dan benar dari bahasa pemrograman LISP ditemukan oleh Guy Steele Lewis Jr dan Gerald Jay Sussman. Ini dirancang untuk memiliki semantik sangat jelas dan sederhana dan berbagai cara untuk membentuk ekspresi. Berbagai macam paradigma pemrograman, termasuk gaya lewat penting, fungsional, dan pesan, menemukan ekspresi dalam Skema nyaman. Skema terus berkembang dengan serangkaian standar (Revisedn Laporan Skema Bahasa algorithmic) dan serangkaian Permintaan Skema Pelaksanaan.
Clojure adalah dialek LISP modern yang menargetkan Java Virtual Machine (dan CLR). Hal ini dirancang untuk menjadi bahasa umum-tujuan pragmatis, menggabungkan didekati dan pengembangan interaktif bahasa dinamis dengan infrastruktur yang efisien dan kuat untuk pemrograman multithreaded. Clojure adalah yang paling “fungsional” dari LISPs utama, menggambar pengaruh yang cukup besar dari Haskell dan menempatkan penekanan yang sangat kuat pada kekekalan. Clojure adalah bahasa yang dikompilasi, karena mengkompilasi langsung ke JVM bytecode, namun tetap benar dinamis. Setiap fitur yang didukung oleh Clojure didukung pada saat runtime. Clojure menyediakan akses mudah ke kerangka Jawa dan perpustakaan, dengan petunjuk jenis opsional dan inferensi tipe, untuk memastikan bahwa panggilan ke Jawa dapat menghindari refleksi dan memungkinkan operasi primitif cepat.
Selain itu, dialek LISP digunakan sebagai bahasa scripting dalam beberapa aplikasi, dengan yang paling terkenal yang Emacs LISP dalam editor Emacs, Visual LISP di AutoCAD, Nyquist di Audacity. Ukuran kecil dari juru Skema minimal tetapi berguna membuatnya sangat populer untuk embedded scripting. Contohnya termasuk SIOD dan TinyScheme, yang keduanya telah berhasil tertanam di prosesor gambar GIMP dengan nama generik “Script-fu” [25] LIBREP, penerjemah LISP oleh John Harper awalnya didasarkan pada Emacs LISP bahasa,. Telah tertanam di window manager Sawfish [26]. Juru Guile digunakan dalam GnuCash. Dalam GCC, plugin Melt menyediakan dialek LISP-y, diterjemahkan ke dalam C, untuk memperpanjang compiler dengan coding lewat tambahan (di Melt).
Bahasa Inovasi
LISP adalah bahasa pemrograman pertama homoiconic: representasi utama dari kode program adalah jenis yang sama struktur daftar yang juga digunakan untuk struktur data utama. Akibatnya, fungsi LISP dapat dimanipulasi, diubah atau bahkan dibuat dalam program LISP tanpa parsing luas atau manipulasi kode mesin biner. Ini umumnya dianggap salah satu keuntungan utama dari bahasa berkaitan dengan daya ekspresif, dan membuat bahasa bisa menerima evaluasi metacircular.
Struktur if-then-else di mana-mana, sekarang diterima begitu saja sebagai unsur penting dari setiap bahasa pemrograman, diciptakan oleh McCarthy untuk digunakan dalam LISP, di mana ia melihat penampilan pertama dalam bentuk yang lebih umum (struktur cond). Itu diwariskan oleh ALGOL, yang mempopulerkannya.
LISP sangat dipengaruhi Alan Kay, pemimpin penelitian pada Smalltalk, dan kemudian pada gilirannya LISP dipengaruhi oleh Smalltalk, dengan mengadopsi fitur pemrograman berorientasi objek (kelas, contoh, dll) pada akhir tahun 1970. Obyek Flavours sistem (kemudian CLOS) intrduced multiple inheritance.
LISP memperkenalkan konsep pengumpulan sampah otomatis, di mana sistem berjalan tumpukan mencari memori yang tidak terpakai. Sebagian besar algoritma pengumpulan sampah modern yang canggih seperti pengumpulan sampah generasi dikembangkan untuk LISP.
Sebagian besar karena kebutuhan sumber daya sehubungan dengan perangkat keras komputer awal (termasuk mikroprosesor awal), LISP tidak menjadi sebagai populer di luar komunitas AI sebagai Fortran dan ALGOL-keturunan bahasa C. Baru bahasa seperti Java dan Python telah memasukkan beberapa versi terbatas dari beberapa fitur dari LISP, tetapi tentu tidak dapat membawa koherensi dan sinergi konsep penuh ditemukan dalam LISP. Karena kesesuaian untuk aplikasi tidak jelas, kompleks, dan dinamis, LISP saat ini menikmati beberapa kebangkitan kepentingan populer.
Sintaks dan semantik
Simbolis ekspresi
LISP adalah bahasa ekspresi-oriented. Tidak seperti bahasa lainnya, tak ada perbedaan istilah antara “ekspresi” dan “pernyataan”, semua kode dan data yang ditulis sebagai ekspresi. Ketika ekspresi dievaluasi, menghasilkan nilai (dalam Common LISP, mungkin beberapa nilai), yang kemudian dapat dimasukkan ke dalam ekspresi lainnya. Setiap nilai dapat menjadi semua jenis data.
1958 kertas McCarthy memperkenalkan dua jenis sintaks: S-ekspresi (ungkapan simbolik, juga disebut “sexps”), yang mencerminkan representasi internal dari kode dan data, dan M-ekspresi (Ekspresi Meta), yang mengungkapkan fungsi S-ekspresi. M-ekspresi tidak pernah mendapat kasih karunia, dan hampir semua digunakan saat ini LISPs S-ekspresi untuk memanipulasi baik kode dan data.
Penggunaan tanda kurung perbedaan LISP yang paling segera jelas dari keluarga bahasa pemrograman lain. Akibatnya, siswa telah lama diberikan julukan LISP seperti Lost In Kurung Bodoh, atau Banyak Kurung Berlebihan Mengiritasi [27] Namun, sintaks S-ekspresi juga bertanggung jawab untuk sebagian besar kekuasaan LISP ini:. Sintaks yang sangat teratur, yang memfasilitasi manipulasi oleh komputer. Namun, sintaks dari LISP tidak terbatas pada notasi kurung tradisional. Hal ini dapat diperluas untuk mencakup notasi alternatif. XMLISP, misalnya, adalah ekstensi Common LISP yang mempekerjakan metaobject-protokol untuk mengintegrasikan S-ekspresi dengan Extensible Markup Language (XML).
Ketergantungan pada ekspresi memberikan fleksibilitas bahasa besar. Karena LISP fungsi sendiri ditulis sebagai daftar, mereka dapat diproses persis seperti data. Hal ini memungkinkan penulisan yang mudah dari program yang memanipulasi program lain (metaprogramming). Banyak dialek LISP mengeksploitasi fitur ini menggunakan sistem makro, yang memungkinkan perpanjangan bahasa hampir tanpa batas.
Daftar
Daftar LISP ditulis dengan unsur-unsurnya dipisahkan oleh spasi, dan dikelilingi oleh tanda kurung. Misalnya, (1 2 foo) adalah daftar yang elemen tiga atom: nilai 1, 2, dan foo. Nilai-nilai ini secara implisit diketik: mereka masing-masing dua bilangan bulat dan LISP spesifik tipe data disebut “simbol”, dan tidak harus dideklarasikan seperti itu.
Daftar kosong () juga direpresentasikan sebagai nihil atom khusus. Ini adalah satu-satunya entitas di LISP yang baik atom dan daftar.
Ekspresi ditulis sebagai daftar, menggunakan notasi prefix. Unsur pertama dalam daftar adalah nama suatu bentuk, yaitu, fungsi, operator, makro, atau “operator khusus” Sisa dari daftar adalah argumen (lihat di bawah.). Misalnya, daftar mengembalikan fungsi argumen sebagai daftar, sehingga ekspresi
(list '1 '2 'foo)
mengevaluasi untuk daftar (1 2 foo). The “kutipan” sebelum argumen dalam contoh sebelumnya adalah “operator khusus” yang mencegah argumen dikutip dari sedang dievaluasi (tidak benar-benar diperlukan untuk angka, sejak 1 bernilai 1, dll). Setiap ekspresi kuotasi yang secara rekursif dievaluasi sebelum ekspresi melampirkan dievaluasi. Sebagai contoh
(list 1 2 (list 3 4))
mengevaluasi untuk daftar (1 2 (3 4)). Perhatikan bahwa argumen ketiga adalah daftar; daftar dapat dikelompokkan.
Operator
Operator aritmatika diperlakukan sama. Ekspresi :
(+ 1 2 3 4)
mengevaluasi sampai 10. Setara di bawah notasi infiks akan “1 + 2 + 3 + 4″. Arithmetic operator dalam LISP adalah variadic (atau n-ary), mampu mengambil sejumlah argumen.
“Operator khusus” (kadang disebut “bentuk khusus”) menyediakan struktur kontrol LISP itu. Sebagai contoh, operator khusus jika diperlukan tiga argumen. Jika argumen pertama adalah non-nihil, ia bernilai argumen kedua, jika tidak, mengevaluasi argumen ketiga. Dengan demikian, istilah
(if nil
(list 1 2 "foo")
(list 3 4 "bar"))
mengevaluasi ke (3 4 “bar”). Tentu saja, ini akan lebih berguna jika ekspresi non-sepele telah diganti di tempat nihil.
Lambda ekspresi
Lain operator khusus, lambda, digunakan untuk mengikat variabel ke nilai-nilai yang kemudian dievaluasi dalam sebuah ekspresi. Operator ini juga digunakan untuk membuat fungsi: argumen untuk lambda adalah daftar argumen, dan ekspresi atau ekspresi yang mengevaluasi fungsi (nilai yang dikembalikan adalah nilai dari ekspresi terakhir yang dievaluasi). Ekspresi :
(lambda (arg) (+ arg 1))
mengevaluasi ke fungsi yang, bila diterapkan, mengambil satu argumen, mengikat ke arg dan mengembalikan nomor satu lebih besar dari argumen itu. Ekspresi Lambda diperlakukan tidak berbeda dari fungsi bernama, mereka dipanggil dengan cara yang sama. Oleh karena itu, istilah
((lambda (arg) (+ arg 1)) 5)
Evaluasi ke 6
Atom
Dalam LISP asli ada dua dasar tipe data: atom dan daftar. Daftar A adalah terbatas memerintahkan urutan elemen, di mana setiap elemen itu sendiri baik atom atau daftar, dan atom adalah angka atau simbol. Simbol pada dasarnya merupakan item yang bernama unik, ditulis sebagai string alfanumerik dalam kode sumber, dan digunakan baik sebagai nama variabel atau sebagai item data dalam pengolahan simbolis. Misalnya, daftar (FOO (BAR 1) 2) berisi tiga elemen: FOO simbol, daftar (BAR 1), dan nomor 2.
Perbedaan penting antara atom dan daftar adalah bahwa atom adalah abadi dan unik. Dua atom yang muncul di tempat yang berbeda dalam kode sumber tapi ditulis dengan cara yang persis sama mewakili objek yang sama
sedangkan daftar masing-masing objek yang terpisah yang dapat diubah secara independen dari daftar lain dan dapat dibedakan dari daftar lain oleh operator perbandingan.
Sebagai tipe data lebih diperkenalkan dalam dialek LISP kemudian, dan gaya pemrograman berkembang, konsep atom kehilangan pentingnya.
Banyak dialek masih mempertahankan predikat atom untuk kompatibilitas warisan, mendefinisikannya benar untuk setiap objek yang bukan merupakan kontra.
Conses dan daftar
Daftar LISP adalah linked list sendiri-sendiri. Setiap sel dari daftar ini disebut kontra (dalam Skema, sepasang), dan terdiri dari dua pointer, yang disebut mobil dan cdr. Ini adalah setara dengan data dan bidang berikutnya dibahas dalam daftar artikel terkait, masing-masing.
Dari struktur data banyak yang bisa dibangun dari sel kontra, salah satu yang paling dasar disebut daftar yang tepat. Sebuah daftar yang tepat adalah baik simbol nihil (daftar kosong) khusus, atau kontra, dimana poin mobil ke datum (yang mungkin adalah struktur kontra, seperti daftar), dan poin cdr untuk daftar lain yang tepat.
Jika kontra diberikan diambil untuk menjadi kepala linked list, maka mobil yang menunjuk pada elemen pertama dari daftar, dan yang cdr poin ke seluruh daftar. Untuk alasan ini, mobil dan fungsi cdr juga disebut pertama dan sisanya ketika mengacu pada conses yang merupakan bagian dari linked list (bukan, katakanlah, pohon).
Dengan demikian, daftar LISP bukan merupakan objek atom, sebagai turunan dari kelas wadah dalam C + + atau Java akan. Sebuah daftar tidak lebih dari suatu agregat dari conses terkait. Sebuah variabel yang mengacu pada daftar yang diberikan hanyalah sebuah pointer ke kontra pertama dalam daftar. Traversal dari daftar dapat dilakukan dengan “cdring down” daftar; yaitu, mengambil CDRs berturut-turut untuk mengunjungi masing-masing kontra dari daftar; atau dengan menggunakan salah satu dari sejumlah fungsi tingkat tinggi untuk memetakan fungsi lebih daftar.
Karena conses dan daftar sangat universal dalam sistem LISP, itu adalah kesalahpahaman umum bahwa mereka hanya LISP itu struktur data. Bahkan, semua tapi LISPs paling sederhana memiliki struktur data lainnya – seperti vektor (array), tabel hash, struktur, dan sebagainya.
S-Ekspresi Mewakili Daftar
Kurung S-ekspresi mewakili struktur linked list. Ada beberapa cara untuk mewakili daftar yang sama sebagai ekspresi S-. Sebuah kontra dapat ditulis dalam notasi dotted-pasangan (a. B), di mana a adalah mobil dan b cdr. Daftar yang lebih panjang yang tepat mungkin ditulis (a (b. (. C. (D. Nihil)))) di titik-titik-pair notasi. Ini konvensional disingkat (abcd) dalam notasi daftar. Sebuah daftar yang tidak tepat [28] dapat ditulis dalam sebuah kombinasi dari kedua – sebagai (abc d.) Untuk daftar tiga conses yang terakhir cdr adalah d (yaitu, daftar (a (b (c d))… ) dalam bentuk sepenuhnya ditentukan).
Daftar pengolahan prosedur
LISP menyediakan banyak built-in prosedur untuk mengakses dan mengontrol daftar. Daftar dapat dibuat langsung dengan prosedur daftar, yang mengambil sejumlah argumen, dan mengembalikan daftar argumen ini.
(list 1 2 'a 3)
;Output: (1 2 a 3)
;Output: (1 (2 3) 4)
(list 1 '(2 3) 4)
Karena cara bahwa daftar yang dibangun dari pasangan kontra, para [[kontra]] prosedur dapat digunakan untuk menambahkan sebuah elemen ke depan daftar. Perhatikan bahwa prosedur kontra adalah asimetris dalam bagaimana menangani argumen daftar, karena cara daftar dibangun.
(cons 1 '(2 3))
;Output: (1 2 3)
;Output: ((1 2) 3 4)
(cons '(1 2) '(3 4))
The [[append]] procedure appends two (or more) lists to one another. Because LISP lists are linked lists, appending two lists has asymptotic time complexity
(append '(1 2) '(3 4))
;Output: (1 2 3 4)
(append '(1 2 3) '() '(a) '(5 6))
;Output: (1 2 3 a 5 6)
Bersama Struktur
Daftar LISP, menjadi daftar link sederhana, dapat berbagi struktur dengan satu sama lain. Artinya, dua daftar dapat memiliki ekor yang sama, atau urutan terakhir dari conses. Sebagai contoh, setelah eksekusi kode LISP berikut Umum:
(setf foo (list 'a 'b 'c))
(setf bar (cons 'x (cdr foo)))
foo daftar dan bar (abc) dan (xbc) masing-masing. Namun, ekor (bc) adalah struktur yang sama di kedua daftar. Ini bukan salinan; sel kontra menunjuk ke b dan c di lokasi memori yang sama untuk kedua daftar.
Berbagi struktur daripada penyalinan dapat memberikan peningkatan kinerja yang dramatis. Namun, teknik ini dapat berinteraksi dengan cara yang tidak diinginkan dengan fungsi yang mengubah daftar diberikan kepada mereka sebagai argumen. Mengubah satu daftar, seperti dengan mengganti c dengan seekor angsa, akan mempengaruhi yang lain:
(setf (third foo) 'goose)
Perubahan ini untuk foo (ab angsa), tetapi dengan demikian juga bar perubahan (x b angsa) – akibat kemungkinan tak terduga. Ini bisa menjadi sumber bug, dan fungsi yang mengubah argumen mereka didokumentasikan sebagai destruktif karena alasan ini.
Pecinta pemrograman fungsional menghindari fungsi destruktif. Dalam dialek Skema, yang mendukung gaya fungsional, nama-nama fungsi yang merusak ditandai dengan tanda seru peringatan, atau “bang”-seperti set-mobil! (baca Ledakan set mobil), yang menggantikan mobil dari sebuah kontra. Dalam dialek Common LISP, fungsi destruktif yang biasa; setara dengan set-mobil! bernama rplaca untuk “mobil ganti.” Fungsi ini jarang terlihat namun sebagai Common LISP menyertakan fasilitas khusus, setf , untuk membuatnya lebih mudah untuk mendefinisikan dan menggunakan fungsi yang merusak. Sebuah gaya sering di Common LISP adalah menulis kode fungsional (tanpa panggilan destruktif) saat prototipe, kemudian untuk menambahkan panggilan destruktif sebagai optimasi di mana itu aman untuk melakukannya.
Diri mengevaluasi bentuk dan mengutip
LISP mengevaluasi ekspresi yang dimasukkan oleh pengguna. Simbol dan daftar mengevaluasi beberapa ekspresi (biasanya, sederhana) lain – misalnya, simbol mengevaluasi ke nilai itu nama variabel, (2 + 3) mengevaluasi ke 5. Namun, sebagian besar bentuk lain untuk mengevaluasi diri mereka sendiri: bila Anda memasukkan 5 ke dalam LISP, ia mengembalikan 5.
Setiap ekspresi juga dapat ditandai untuk mencegah dari yang dievaluasi (seperti yang diperlukan untuk simbol dan daftar). Ini adalah peran operator kutipan khusus, atau singkatan ‘(tanda kutip tunggal). Misalnya, biasanya jika Anda memasukkan simbol foo Anda akan mendapatkan kembali nilai dari variabel yang sesuai (atau kesalahan, jika tidak ada variabel tersebut). Jika Anda ingin merujuk ke simbol literal, Anda masukkan (kutipan foo) atau, biasanya, ‘foo.
Kedua Common LISP dan Scheme juga mendukung operator backquote (dikenal sebagai quasiquote dalam Skema), masuk dengan karakter `. Ini hampir sama dengan kutipan biasa, kecuali ia memungkinkan ekspresi dievaluasi dengan nilai interpolasi ke dalam daftar dikutip dengan koma dan koma pada operator. Jika snue variabel memiliki nilai (bar baz) maka `(foo, snue) mengevaluasi ke (foo (bar baz)), sementara` (foo, @ snue) mengevaluasi ke (foo bar baz). Backquote ini paling sering digunakan dalam mendefinisikan ekspansi makro.
Diri mengevaluasi bentuk dan bentuk dikutip setara LISP dari literal. Dimungkinkan untuk memodifikasi nilai-nilai (bisa berubah) literal dalam kode program. Misalnya, jika fungsi mengembalikan bentuk dikutip, dan kode yang memanggil fungsi memodifikasi bentuk, hal ini dapat mengubah perilaku fungsi pada iterasi berikutnya.
(defun should-be-constant ()
'(one two three))
(let ((stuff (should-be-constant)))
(setf (third stuff) 'bizarre)) ; bad!
(should-be-constant) ; returns (one two bizarre)
Memodifikasi bentuk dikutip seperti ini umumnya dianggap gaya yang buruk, dan didefinisikan oleh LISP ANSI umum sebagai salah (yang mengakibatkan perilaku “tidak terdefinisi” dalam file dikompilasi, karena berkas-compiler dapat menyatu konstanta yang sama, menempatkan mereka dalam menulis dilindungi memori, dll).
LISP formalisasi dari kutipan telah dicatat oleh Douglas Hofstadter (dalam Gödel, Escher, Bach) dan lain-lain sebagai contoh ide filosofis referensi diri.
Ruang Lingkup Dan Penutupan
Keluarga LISP modern yang terbagi atas penggunaan lingkup dinamis atau statis (leksikal alias). Clojure, Common LISP dan Scheme menggunakan pelingkupan statis secara default, sedangkan NewLISP, PicoLISP dan bahasa tertanam di Emacs dan AutoCAD penggunaan dinamis pelingkupan.
Daftar Struktur Macro Kode Program, Dan Compiler
Perbedaan mendasar antara LISP dan bahasa lainnya adalah bahwa dalam LISP, representasi tekstual dari sebuah program adalah hanya penjelasan dibaca manusia dari struktur data internal yang sama (daftar link, simbol, angka, karakter, dll) akan digunakan oleh LISP sistem yang mendasarinya.
LISP menggunakan ini untuk menerapkan sistem makro yang sangat kuat. Seperti bahasa makro lainnya seperti C, makro kembali kode yang kemudian dapat dikompilasi. Namun, tidak seperti macro C, macro adalah fungsi LISP dan sebagainya dapat memanfaatkan kekuatan penuh dari LISP.
Selanjutnya, karena kode LISP memiliki struktur yang sama sebagai daftar, macro dapat dibangun dengan salah satu daftar pengolahan fungsi dalam bahasa. Singkatnya, apa pun yang LISP dapat Anda lakukan untuk struktur data, LISP macro lakukan untuk kode. Sebaliknya, dalam kebanyakan bahasa lain, output parser adalah murni internal untuk
Penerapan Bahasa Dan Tidak Dapat Dimanipulasi Oleh Programmer.
Hal ini membuat mudah untuk mengembangkan bahasa yang efisien dalam bahasa. Misalnya, Sistem LISP Common Object dapat diimplementasikan sebagai perpanjangan bersih bahasa menggunakan macro. Ini berarti bahwa jika aplikasi membutuhkan mechanims warisan yang berbeda, misalnya, dapat menggunakan sistem objek yang berbeda. Hal ini berbeda sekali dengan kebanyakan bahasa lain, misalnya Java tidak mendukung multiple inheritance dan tidak ada cara yang masuk akal untuk menambahkannya.
Dalam implementasi LISP sederhana, struktur daftar langsung ditafsirkan untuk menjalankan program; fungsi secara harfiah adalah bagian dari struktur daftar yang dilalui oleh penerjemah dalam melaksanakan. Namun, sebagian besar sistem LISP juga mencakup kompilator. Compiler menerjemahkan struktur daftar ke dalam kode mesin atau bytecode untuk eksekusi. Kode ini dapat berjalan secepat (atau kadang-kadang lebih cepat) dari kode dikompilasi dalam bahasa konvensional seperti C. Macro memperluas sebelum langkah kompilasi, dan dengan demikian bisa sangat efisien.
Evaluasi dan loop read-eval-print
Bahasa cadel sering digunakan dengan baris perintah interaktif, yang dapat dikombinasikan dengan lingkungan pengembangan terintegrasi. Pengguna jenis dalam ekspresi pada baris perintah, atau mengarahkan IDE untuk mengirimkan mereka ke sistem LISP. LISP membaca ekspresi dimasukkan, mengevaluasi mereka, dan mencetak hasilnya. Untuk alasan ini, baris perintah LISP disebut “read-eval-print loop”, atau repl.
Operasi dasar dari repl adalah sebagai berikut. Ini adalah deskripsi sederhana yang menghilangkan banyak elemen dari LISP nyata, seperti mengutip dan macro.
Fungsi membaca menerima tekstual S-ekspresi sebagai input, dan mem-parsing mereka ke dalam struktur data internal. Misalnya, jika Anda ketik teks (+ 1 2) saat diminta, membaca menerjemahkan ini ke dalam linked list dengan tiga elemen: + simbol, nomor 1, dan nomor 2. Hal ini terjadi bahwa daftar ini juga merupakan bagian sah dari kode LISP, yaitu, dapat dievaluasi. Hal ini karena mobil daftar menamai sebuah fungsi-operasi penjumlahan.
Perhatikan bahwa foo akan dibaca sebagai simbol tunggal. 123 akan dibaca sebagai 123 nomor. “123” akan dibaca sebagai string “123”.
Fungsi eval mengevaluasi data, kembali nol atau lebih data lain LISP sebagai hasilnya. Evaluasi tidak harus berarti interpretasi, beberapa sistem LISP mengkompilasi setiap ekspresi ke kode mesin asli. Hal ini sederhana, namun, untuk menggambarkan evaluasi sebagai interpretasi: Untuk mengevaluasi sebuah daftar yang mobilnya menamai fungsi, eval pertama mengevaluasi setiap argumen yang diberikan dalam Surat cdr, kemudian menerapkan fungsi untuk argumen. Dalam hal ini, fungsi ini itu, dan menerapkannya pada daftar argumen (1 2) menghasilkan jawaban 3. Ini adalah hasil dari evaluasi.
Foo simbol mengevaluasi ke nilai foo simbol. Data seperti “123” string mengevaluasi untuk string yang sama. Daftar (kutipan (1 2 3)) mengevaluasi ke daftar (1 2 3).
Ini adalah tugas dari fungsi cetak untuk mewakili output ke pengguna. Untuk hasil yang sederhana seperti 3 ini adalah sepele. Sebuah ekspresi yang dievaluasi untuk sepotong struktur daftar akan membutuhkan cetak yang melintasi daftar dan mencetaknya sebagai ekspresi S-.
Untuk menerapkan repl LISP, perlu hanya untuk melaksanakan ketiga fungsi dan fungsi yang tak terbatas loop. (. Tentu, pelaksanaan eval akan menjadi lebih rumit, karena juga harus menerapkan semua operator khusus seperti jika atau lambda) ini dilakukan, repl dasar itu sendiri hanyalah satu baris kode: (loop (cetak (eval (baca)) )).
Para repl LISP biasanya juga menyediakan editing input, sebuah sejarah input, penanganan kesalahan dan sebuah antarmuka untuk debugger.
LISP biasanya dievaluasi dengan penuh semangat. Dalam Common LISP, argumen dievaluasi agar aplikatif (‘paling kiri terdalam’), sementara dalam rangka Skema argumen tidak terdefinisi, meninggalkan ruang untuk optimasi oleh kompilator.
Kontrol Struktur
LISP awalnya memiliki struktur kontrol sangat sedikit, tetapi lebih banyak yang ditambahkan selama evolusi bahasa ini. (Operator asli bersyarat LISP itu, cond, adalah prekursor nanti jika-maka-lain struktur.)
Programmer dalam dialek Skema sering loop ekspres menggunakan rekursi ekor. Skema kesamaan dalam ilmu komputer akademis telah menyebabkan beberapa siswa untuk percaya bahwa rekursi ekor adalah cara, saja, atau yang paling umum untuk menulis iterasi dalam LISP, tetapi ini tidak benar. Semua LISP sering terlihat memiliki dialek penting gaya konstruksi iterasi, dari loop do Skema untuk ekspresi kompleks Common LISP yang loop. Selain itu, isu utama yang membuat tujuan dan bukan hal subjektif adalah Skema yang membuat persyaratan khusus untuk penanganan panggilan ekor, dan akibatnya alasan bahwa penggunaan rekursi ekor umumnya didorong untuk Skema adalah bahwa praktek secara tegas didukung oleh definisi bahasa itu sendiri. Sebaliknya, ANSI Common LISP tidak memerlukan [29] optimasi sering disebut sebagai penghapusan panggilan ekor. Akibatnya, fakta bahwa ekor gaya rekursif sebagai pengganti kasual untuk penggunaan lebih iterasi konstruksi tradisional (seperti dilakukan, dolist atau loop) tidak disarankan [30] di Common LISP bukan hanya masalah preferensi gaya, tetapi berpotensi salah satu efisiensi (karena panggilan ekor tampak dalam Common LISP mungkin tidak dikompilasi seperti lompatan sederhana) dan program kebenaran (karena rekursi ekor dapat meningkatkan penggunaan stack dalam Common LISP, mempertaruhkan stack overflow).
Beberapa struktur kontrol LISP adalah operator khusus, setara dengan kata kunci sintaksis bahasa lain. Ekspresi menggunakan operator ini memiliki penampilan permukaan yang sama sebagai panggilan fungsi, tetapi berbeda dalam bahwa argumen tidak harus dievaluasi-atau, dalam hal ekspresi iterasi, dapat dievaluasi lebih dari sekali.
Berbeda dengan kebanyakan bahasa pemrograman utama lainnya, LISP memungkinkan programmer untuk mengimplementasikan struktur kontrol menggunakan bahasa itu sendiri. Beberapa struktur kontrol diimplementasikan sebagai macro LISP, dan bahkan bisa menjadi makro diperluas dengan programmer yang ingin tahu bagaimana mereka bekerja.
Kedua Common LISP dan Scheme memiliki operator untuk non-lokal aliran kontrol. Perbedaan operator ini adalah beberapa perbedaan yang paling dalam antara kedua dialek. Skema mendukung kembali peserta continuations menggunakan panggilan / prosedur cc, yang memungkinkan program untuk menyimpan (dan kemudian mengembalikan) tempat tertentu dalam pelaksanaannya. Common LISP tidak mendukung re-entrant continuations, tetapi mendukung beberapa cara penanganan continuations melarikan diri.
Sering, algoritma yang sama dapat dinyatakan dalam LISP baik penting atau gaya fungsional. Seperti disebutkan di atas, Skema cenderung mendukung gaya fungsional, menggunakan rekursi ekor dan continuations untuk mengekspresikan kontrol aliran. Namun, gaya imperatif masih sangat mungkin. Gaya disukai oleh banyak programmer Common LISP mungkin tampak lebih akrab bagi programmer digunakan untuk bahasa terstruktur seperti C, sedangkan yang disukai schemers lebih mirip murni-fungsi bahasa seperti Haskell.
Karena warisan awal LISP di list processing, ia memiliki beragam tingkat tinggi fungsi yang berkaitan dengan iterasi atas urutan. Dalam banyak kasus dimana loop eksplisit akan diperlukan dalam bahasa lain (seperti untuk loop dalam C) dalam Lips tugas yang sama dapat dicapai dengan fungsi tingkat tinggi. (Hal yang sama juga terjadi pada banyak bahasa pemrograman fungsional.)
Contoh yang baik adalah fungsi yang pada Skema ini disebut peta dan di Common LISP disebut mapcar. Mengingat fungsi dan satu atau lebih daftar, mapcar berlaku fungsi berturut-turut untuk elemen daftar ‘dalam rangka, mengumpulkan hasil dalam daftar baru:
(mapcar #'+ '(1 2 3 4 5) '(10 20 30 40 50))
This applies the + function to each corresponding pair of list elements, yielding the result (11 22 33 44 55).
Contoh
Berikut adalah contoh kode Common LISP.
Dasar “Halo dunia” Program:
(print "Hello world")
Sebagai pembaca mungkin telah memperhatikan dari diskusi di atas, sintaks LISP cocok alami untuk rekursi. Masalah matematika seperti penghitungan set didefinisikan secara rekursif sederhana untuk mengekspresikan dalam notasi ini.
Evaluasi faktorial nomor ini:
(defun factorial (n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
Sebuah implementasi alternatif, seringkali lebih cepat daripada versi sebelumnya jika sistem LISP memiliki optimasi ekor rekursif:
(defun factorial (n &optional (acc 1))
(if (<= n 1)
acc
(factorial (- n 1) (* acc n))))
Kontras dengan versi iteratif yang menggunakan Common LISP lingkaran makro:
(defun factorial (n)
(loop for i from 1 to n
for fac = 1 then (* fac i)
finally (return fac)))
The following function reverses a list. (LISP’s built-in reverse function does the same thing.)
(defun -reverse (list)
(let ((return-value '()))
(dolist (e list) (push e return-value))
return-value))
Obyek sistem
Berbagai sistem objek dan model telah dibangun di atas, di samping, atau ke dalam LISP, termasuk:
The Common LISP Object System, CLOS, merupakan bagian integral dari ANSI Common LISP. CLOS keturunan Rasa Baru dan CommonLOOPS. ANSI Common LISP adalah standar pertama berorientasi objek bahasa pemrograman (1994, ANSI X3J13).
ObjectLISP atau Obyek LISP, yang digunakan oleh Mesin LISP Incorporated dan versi awal Macintosh Common LISP
Loop (LISP Object-Oriented System Programming) dan kemudian CommonLOOPS
Rasa, dibangun di MIT, dan yang keturunan Rasa Baru (dikembangkan oleh Symbolics).
KR (singkatan Representasi Pengetahuan), sebuah kendala berbasis objek sistem yang dikembangkan untuk membantu penulisan Garnet, perpustakaan GUI untuk Common LISP.
KEE menggunakan sistem objek disebut UNIT dan terintegrasi dengan sebuah mesin inferensi dan pemeliharaan sistem kebenaran (ATM).