Apa fungsi yang dipentaskan (secara konseptual)?

24

Dalam artikel CACM baru-baru ini [1], penulis menyajikan implementasi untuk fungsi bertahap . Mereka menggunakan istilah itu seolah-olah itu terkenal, dan tidak ada referensi yang terlihat seperti pengantar yang jelas.

Mereka memberikan penjelasan singkat (penekanan saya dan nomor referensi berubah; ini 22 di aslinya)

Dalam konteks pembuatan program, pemrograman multistage (MSP, staging for short) sebagaimana didirikan oleh Taha dan Sheard [2] memungkinkan programmer untuk secara eksplisit menunda evaluasi ekspresi program ke tahap selanjutnya (dengan demikian, staging ekspresi). Tahap ini secara efektif bertindak sebagai pembuat kode yang menyusun (dan mungkin mengeksekusi) program dari tahap berikutnya.

Namun, Taha dan Sheard menulis (penekanan milikku):

Program multi-tahap adalah program yang melibatkan pembuatan, kompilasi, dan eksekusi kode, semuanya di dalam proses yang sama. Bahasa multi-tahap mengekspresikan program multi-tahap. Pementasan, dan akibatnya pemrograman multi-tahap, menjawab kebutuhan akan solusi tujuan umum yang tidak membayar biaya interpretatif run-time.

Mereka kemudian melanjutkan ke beberapa referensi ke karya lama yang diduga menunjukkan bahwa pementasan itu efektif, yang menunjukkan bahwa konsepnya bahkan lebih tua. Mereka tidak memberikan referensi untuk istilah itu sendiri.

Pernyataan-pernyataan ini tampaknya ortogonal, jika tidak bertentangan; mungkin apa yang Rompf dan Odersky tulis adalah aplikasi dari apa yang Taha dan Sheard usulkan, tapi mungkin itu adalah perspektif lain tentang hal yang sama. Mereka tampaknya setuju bahwa poin penting adalah bahwa program (kembali) menulis bagian dari diri mereka sendiri pada saat runtime, tetapi saya tidak tahu apakah itu diperlukan dan / atau kemampuan yang cukup.

Jadi, apa pementasan masing-masing interpretasi pementasan dalam konteks ini? Dari mana asal istilah itu?


  1. Stadium Modular Ringan: Pendekatan Pragmatis untuk Pembuatan Kode Runtime dan DSL yang Dikompilasi oleh T. Rompf dan M. Odersky (2012)
  2. MetaML dan multi-stageprogramming dengan penjelasan eksplisit oleh W. Taha dan T. Sheard (2000)
Raphael
sumber
Kontradiksi apa yang Anda lihat di antara kedua pernyataan itu? Bagi saya, mereka terlihat seperti sedang membicarakan hal yang sama, dengan penekanan berbeda.
Gilles 'SANGAT berhenti menjadi jahat'
@Gilles Saya tidak perlu pembuatan kode-generasi / -kompilasi untuk menunda evaluasi sesuatu (lihat berkelanjutan). Mungkin saja itu hanya penekanan lain (saya akui opsi itu dalam pertanyaan), tetapi saya tidak bisa mengatakannya.
Raphael
Anda dapat melihat implementasi bahasa pemrograman Julia dan dokumentasi metaprogramming di @generated functions: julia.readthedocs.org/en/latest/manual/metaprogramming/…
SalchiPapa

Jawaban:

21

Sepengetahuan saya, istilah perhitungan bertahap pertama kali digunakan oleh Bill Scherlis dalam makalah ini . Sebelum itu, istilah " evaluasi parsial " digunakan untuk banyak konsep yang sama, tetapi gagasan perhitungan bertahap agak berbeda. Kedua ide tersebut terkait dengan teorema Smn Kleene .

Jika Anda memiliki fungsi dari dua argumen, tetapi Anda tahu satu argumen, katakan m , maka Anda dapat melakukan beberapa perhitungan fungsi segera menggunakan pengetahuan dari argumen pertama. Apa yang tersisa dengan Anda adalah fungsi ϕ m ( n ) yang perhitungannya hanya bergantung pada argumen kedua yang tidak diketahui.ϕ(m,n)mϕm(n)

Gagasan evaluasi parsial adalah untuk menghitung fungsi khusus secara otomatis . Mengingat kode untuk fungsi asli φ , evaluasi parsial melakukan analisis statis untuk menentukan bit kode tergantung pada m dan yang bit bergantung pada n , dan transformasi ke fungsi φ ' yang, mengingat m , konstruksi φ m . Argumen kedua n kemudian dapat dimasukkan ke fungsi khusus ini.ϕm(n) ϕmnϕmϕmn

Ide perhitungan bertahap adalah untuk memikirkan fungsi terlebih dahulu. Ini disebut fungsi "bertahap" karena berfungsi dalam beberapa tahap. Setelah kita memberikan argumen pertama m , ia membangun kode untuk fungsi khususϕm . Ini adalah "tahap pertama." Pada tahap kedua, argumen kedua disediakan untuk ϕ m yang melakukan sisa pekerjaan.ϕmϕm

Jadi, tugas evaluasi parsial adalah mengubah kode untuk fungsi biasa menjadi fungsi bertahap ϕ . Scherlis membayangkan bahwa transformasi ini dapat dilakukan dengan mekanisme yang lebih umum daripada metode evaluasi parsial sebelumnya. Subjek "perhitungan bertahap" sekarang berhubungan dengan masalah-masalah seperti:ϕϕ

  • Bagaimana cara mendefinisikan fungsi bertahap?
  • Bahasa pemrograman dan sistem tipe apa yang harus digunakan untuk mendefinisikan fungsi bertahap?
  • Apa semantik bahasa tersebut?
  • Bagaimana kita memastikan koherensi dan kebenaran fungsi yang dipentaskan?
  • Teknik apa yang berguna untuk membangun fungsi bertahap secara otomatis atau semi-otomatis?
  • Bagaimana kita membuktikan kebenaran teknik tersebut?

Perhitungan bertahap bisa sangat penting dalam praktik. Bahkan, setiap kompiler pada dasarnya adalah perhitungan bertahap. Diberikan program sumber, ia membangun program target yang diterjemahkan dan dioptimalkan, yang kemudian dapat mengambil input aktual dan menghitung hasilnya. Sulit untuk menulis program perhitungan bertahap dalam praktik karena kita harus menyulap berbagai tahap dan memastikan bahwa hal-hal yang benar dilakukan pada waktu yang tepat. Setiap orang yang telah menulis kompiler telah berjuang dengan masalah seperti itu. Juga sulit untuk menulis program yang menulis program lain, mungkin program bahasa mesin (kompiler), kueri SQL (manipulasi basis data) atau HTML / Server Pages / kode Javascript (aplikasi web) dan berjuta aplikasi lainnya.

Uday Reddy
sumber
ϕϕ
Jadi yang Anda maksud adalah evaluasi parsial adalah abstraksi atas pemrograman multi-staged, artinya eval parsial tidak menyiratkan pemrograman multi-bertahap tetapi pemrograman multi-bertahap menyiratkan eval parsial. Dimana eval parsial dapat dilakukan dalam satu atau beberapa tahap karena currying dalam bahasa fungsional tidak selalu melibatkan beberapa tahap dan menghasilkan kode saat runtime, kan?
denis631
1
Tidak persis. Evaluator parsial mengkompilasi program biasa menjadi program 2 tahap dan kemudian menjalankan tahap pertama. Dalam pemrograman bertahap, Anda menulis sendiri program multi-tahap.
Uday Reddy
9

Meskipun jawaban lain secara teknis benar, saya tidak berpikir mereka memberikan pemahaman yang benar tentang mengapa para ilmuwan komputer tertarik pada fungsi bertahap.

Dengan membuat fungsi bertahap, Anda menentukan program yang menghasilkan program. Salah satu tujuan besar teori bahasa praktis modern adalah memaksimalkan potensi penggunaan kembali. Kami ingin memungkinkan untuk menulis perpustakaan yang bukan hanya fungsi dan objek yang bermanfaat, tetapi yang membantu programmer dengan menyediakan konstruksi arsitektur tingkat tinggi.

Alangkah baiknya jika kita bisa menyingkirkan semua kode boilerplate. Kami harus dapat meminimalkan bahasa spesifikasi. Jika kita menginginkan dispatcher yang digerakkan oleh peristiwa, misalnya, berkomunikasi dengan dispatcher lain dengan desain utas yang diberikan, kita harus dapat menentukan secara kompak, dan semua pendengar IO dan objek antrian dan koneksi utas harus dapat dibangun dari spesifikasi tersebut.

Bahasa domain cenderung merupakan representasi kompak yang kami cari. Ketika orang-orang bekerja di suatu domain untuk sementara waktu, bahasa yang mereka gunakan cenderung menjatuhkan duplikasi sebagian besar informasi dan menjadi spesifikasi lean. Jadi teori pementasan ini cenderung menjadi sistem terjemahan dari bahasa domain ke bahasa eksekusi.

Compiler secara teknis adalah stager, tetapi tidak memenuhi tujuan. Tujuan dari pementasan modern adalah untuk memungkinkan program pembangunan yang membangun program untuk memaksimalkan penggunaan kembali dan mengotomatisasi konstruksi program sedapat mungkin. Akan lebih bagus jika suatu hari persyaratan fungsional suatu program adalah program.

Lihat "Pemrograman Generatif" oleh Czarnecki dan Eisenecker (ISBN-13: 978-0201309775).

ex0du5
sumber
@ Raphael: Ini adalah bab tiga dengan dasar-dasar pada domain dan digunakan kembali. Lihatlah bahkan optimasi yang Anda sebutkan. FFT tidak dilakukan dengan pementasan untuk membuatnya berjalan lebih cepat. Ini dilakukan agar programmer tidak harus menghitung tabel nilai setiap kali dengan tangan, menyalinnya ke program, dan membuat daftar besar. Ini untuk meminimalkan pekerjaan yang dilakukan dan menggunakan kembali langkah dasar. Sama dengan loop membuka gulungan. Melakukannya dengan tangan mengulangi info dan tidak dapat digunakan kembali.
ex0du5
Sudut pandang DSL ini tampaknya membatasi pementasan menjadi satu tingkat (satu kompilator DSL di dalam program), bukan?
Raphael
1
@ Raphael: Ini benar-benar tergantung pada sudut pandang Anda. Jelas, konsep ini tidak menambah kekuatan komputasi jika dilihat hanya sebagai sumber -> terjemahan yang dapat dieksekusi. Kami hanya bisa membangun kompiler untuk bahasa DS dan selesai. Dari mana kekuatan itu berasal adalah dalam iterasi. Ketika membangun perpustakaan yang akan digunakan dan diperluas oleh proyek di masa depan, tahapan alami muncul di dalam batas-batas perpustakaan. Anda mungkin memiliki pustaka yang mengubah spesifikasi objek menjadi sumber untuk serialisasi penuh, dan kemudian pustaka lain yang membuat lapisan transport yang dibangun pada beberapa spesifikasi pengiriman ...
ex0du5
1
@ Raphael: Pementasan mungkin lebih alami dibuat dengan beberapa tahap. Jika salah satu bagian dari kode telah memiliki persyaratan yang berubah banyak dari waktu ke waktu, di mana yang lain lebih stabil, itu mungkin tepat karena "lapisan geser" untuk memisahkan pementasan menjadi lapisan dengan antarmuka yang lebih stabil. Anda kemudian dapat lebih sedikit mempengaruhi sistem dengan perubahan dan menghormati bentuk pementasan prinsip terbuka-tertutup. Itu adalah masalah praktis yang tidak memiliki kebutuhan matematika, tetapi semuanya didasarkan pada kepraktisan. Kami tidak ingin satu bahasa kompiler, kami ingin mengizinkan evolusi.
ex0du5
5

Jawabannya diberikan dalam bagian perspektif teknis untuk artikel tersebut [1]. Masalah yang dipertimbangkan adalah bidang ketegangan antara kode umum dan spesifik:

Program dapat ditulis untuk tujuan umum atau tujuan khusus. Kode tujuan umum memiliki keuntungan karena dapat digunakan dalam berbagai situasi, sedangkan kode tujuan khusus dapat ditulis dengan cara yang mengambil keuntungan dari karakteristik unik dari lingkungan eksekusi dan dengan demikian memperoleh efisiensi dengan biaya usabilitas ulang.

Tentu saja kami ingin menyelesaikan ketegangan ini, yaitu mencapai kode umum dan implementasi spesifik:

Kita dapat mengajukan pertanyaan: Apakah mungkin untuk menulis kode sehingga bersifat umum tetapi kemudian secara otomatis mengkhususkan diri pada situasi yang dihadapi selama eksekusi?

Hal ini memunculkan ide untuk membuat program (umum) menulis sendiri pada saat runtime untuk mengakomodasi situasi tertentu:

Akibatnya, arah penting dari penelitian telah melibatkan pencarian untuk bahasa dan teknologi kompiler yang dapat memungkinkan programmer untuk menulis kode tujuan umum yang kemudian dengan benar dan efisien berubah menjadi kode khusus berkinerja tinggi pada saat run-time.

Saya kira Java JIT adalah contoh yang bagus. Satu ide khusus adalah pemrograman multi-tahap, yang Lee jelaskan seperti ini:

Dalam jalur penelitian ini, salah satu ide inti adalah konsep pementasan. Kami membayangkan pelaksanaan suatu program yang berjalan dalam serangkaian tahap, masing-masing menghitung nilai yang digunakan oleh tahap selanjutnya. Apa yang kita cari adalah menulis kode program sehingga tahap-tahap ini dibuat jelas. Jika ini tercapai, maka kita dapat mengatur agar kode tahap selanjutnya dikompilasi menjadi generator kode yang mengoptimalkan hasil perhitungan tahap sebelumnya.

Artinya, "pementasan" adalah cara melihat fungsi / kode yang sesuai yang mengidentifikasi fase dalam perhitungan / eksekusi yang dapat disederhanakan mengetahui hasil dari fase sebelumnya. Perhitungan "menunda" seperti dalam kutipan pertama dalam pertanyaan mungkin merupakan efek samping yang diperlukan untuk memisahkan tahapan dengan benar, tetapi itu bukan intinya.

Rompf dan Odersky menyebut transformasi fourier cepat sebagai contoh yang mungkin bermanfaat.


  1. Rubah dan landak: perspektif teknis oleh Peter Lee (2012)
Raphael
sumber