Apa dasar matematika untuk nilai-nilai kelas pertama / kedua / ketiga dalam bahasa pemrograman?

19

Ditambahkan

Baru menemukan dua pertanyaan terkait

/math//q/1759680/1281

/programming//a/2582804/156458


Dalam bahasa pemrograman, dari Bahasa Pemrograman Pragmatik Michael Scott

Secara umum, nilai dalam bahasa pemrograman dikatakan memiliki status kelas pertama jika dapat dilewatkan sebagai parameter, dikembalikan dari subrutin, atau ditugaskan ke dalam variabel. Jenis sederhana seperti integer dan karakter adalah nilai kelas pertama di sebagian besar bahasa pemrograman. Sebaliknya, nilai "kelas dua" dapat dilewatkan sebagai parameter, tetapi tidak dikembalikan dari subrutin atau ditugaskan ke dalam variabel, dan nilai "kelas tiga" bahkan tidak bisa diteruskan sebagai parameter.

Label adalah nilai kelas tiga di sebagian besar bahasa pemrograman, tetapi nilai kelas dua di Algol. Subrutin menampilkan variasi terbanyak. Mereka adalah nilai kelas pertama dalam semua bahasa pemrograman fungsional dan sebagian besar bahasa scripting. Mereka juga nilai-nilai kelas pertama dalam C # dan, dengan beberapa batasan, dalam beberapa bahasa imperatif lainnya, termasuk Fortran, Modula-2 dan -3, Ada 95, C, dan C ++. 11 Mereka adalah nilai kelas dua di sebagian besar bahasa imperatif lainnya, dan nilai kelas tiga di Ada 83.

  1. Apa dasar matematika untuk nilai-nilai kelas pertama / kedua / ketiga dalam bahasa pemrograman?

    Terminologi mengingatkan saya pada logika urutan pertama / kedua, tetapi apakah mereka terkait?

  2. Tampak bagi saya bahwa perbedaan di antara mereka adalah kasus spesifik mana nilai dapat digunakan

    • dilewatkan sebagai parameter,
    • kembali dari subrutin, atau
    • ditugaskan ke dalam variabel.

    Mengapa kasus spesifik itu penting, sementara kasus lain tidak disebutkan?

Terima kasih.

Tim
sumber
23
Mengklasifikasikan nilai ke dalam kelas pertama / kedua sama sia-sianya dengan mengklasifikasikan bahasa ke dalam paradigma. Yang akan Anda dapatkan hanyalah generalisasi samar yang membingungkan gambar. Ini bukan pendekatan yang tepat untuk memahami bahasa pemrograman. Yang penting adalah memahami sintaks, statika, dan dinamika bahasa, tetapi itu terlalu besar untuk
dibahas
3
Selain: PL / I akan menjadi contoh label sebagai kelas satu. Di PL / I Anda dapat mendeklarasikan variabel yang diketik ke label, menetapkannya lokasi kode, dan membukanya. Anda juga dapat meneruskannya sebagai parameter, dan bahkan membuat arraynya.
Theraot
@Theraot: Mungkin saya berkencan sendiri, tetapi apakah saya satu-satunya yang pernah berurusan dengan GOTO yang ditugaskan dan dihitung di FORTRAN? Dan tidak, saya tidak menulis @ $%! kode, saya terjebak rekayasa ulang itu.
jamesqf
@ jamesqf Saya sadar akan menetapkan label pada FORTRAN dan COBOL, tidak, saya belum pernah menggunakannya. Saya tidak yakin bagaimana cara mengklasifikasikan label di sana. Namun untuk apa yang saya baca (saya punya manual) PL / Saya melampaui itu, dan saya yakin bahwa label adalah kelas satu di sana.
Theraot

Jawaban:

45

Tidak ada, dan itu cukup sewenang-wenang.

Satu-satunya perbedaan yang bermanfaat adalah antara kelas satu dan yang lainnya. Setiap case yang ada di braket "lain" memiliki seperangkat aturan sendiri yang berbeda dalam setiap case dan menyatukan semuanya hanya tidak sangat membantu. "Kelas satu" berarti "Anda tidak harus mencari aturan", pada dasarnya, dan "lainnya" adalah "Anda harus mempelajari aturan".

Misalnya di C ++ fungsi individu adalah nilai kelas pertama, asalkan tidak memiliki stat. Set overload tidak tetapi lambda. Dalam C # fungsi umumnya nilai-nilai kelas satu tetapi ada beberapa kasus canggung yang muncul ketika berhadapan dengan tipe inferensi yang mencegah mereka dari semua kasus.

DeadMG
sumber
10
+1, meskipun dalam konteks buku seperti Bahasa Pemrograman Pragmatik yang membandingkan sejumlah besar konstruksi dalam sejumlah besar bahasa, dan menganalisis persamaan dan perbedaan serta implikasi secara mendalam, saya pikir jenis tulisan singkat ini dapat berguna. (Hanya saja jangan seenaknya mengharapkan orang lain untuk memahami "tangan kedua" dan "tangan ketiga" sebagai hal-hal yang bermakna.)
ruakh
(Eh, di mana dengan "tangan kedua" dan "tangan ketiga" saya tentu saja berarti "kelas dua" dan "kelas tiga". :-P)
ruakh
3
Jika Anda ingin berdagang dengan fungsi bekas, Anda sebaiknya melakukannya dalam bahasa di mana fungsi adalah warga negara kelas satu. ^^
5gon12eder
@ 5gon12eder: "fungsi bekas" adalah yang Anda panggil dari perpustakaan pihak ketiga, bukan?
jamesqf
11

Saya setuju dengan DeadMG, perbedaan penting adalah antara kelas satu dan "segalanya." Namun, ada cara yang lebih akrab untuk mengklasifikasikan perbedaan.

Nilai kelas adalah data, yang lain adalah kode. (Secara kasar: Saya yakin ada pengecualian. Tapi ini perkiraan yang bagus untuk bahasa dunia nyata.)

Dalam beberapa bahasa Anda dapat memperlakukan kode sebagai data. Bahasa fungsional terkenal untuk ini: beberapa dari mereka membiarkan Anda mengubah kode program saat dijalankan (fondasi pemrograman genetik ).

Bahasa seperti C dan C ++ memungkinkan Anda untuk mengambil alamat fungsi: sementara Anda tidak dapat memodifikasinya, Anda bisa meneruskan fungsi sebagai parameter ke fungsi lain. C ++ juga memiliki gula sintaksis dari functors . Idenya adalah untuk menciptakan keseluruhan objek yang, pada permukaannya, tampak berperilaku seperti fungsi dan dapat diedarkan seolah-olah itu adalah data. Apa yang dinyatakan sebagai nilai kelas bawah dapat diperlakukan sebagai nilai kelas satu.

Secara matematis, saya pikir cara terbaik adalah memikirkan AST program . Biasanya, setiap token memiliki jenis spesifik yang mungkin kompatibel atau tidak dengan jenis lain. Pikirkan nilai-l, nilai-r, dan semua jenis nilai kekacauan lainnya dalam C ++ . Kemudian tambahkan kata kunci, simbol yang berfungsi, dll. Beberapa di antaranya mungkin nilai kelas pertama, kedua, atau ketiga tergantung pada bahasa.

Saya tidak yakin mengetahui "kelas" nilai adalah yang paling penting, kecuali mungkin dalam lingkungan akademik. Di dunia nyata, hal penting yang perlu diketahui adalah bagaimana Anda bisa mengoper kode, memperlakukannya seperti data: functors, lambdas / closure, function pointer, dll.


sumber
2
Contoh nilai non-kode non-kelas: Lua memiliki ..."variabel" khusus yang digunakan untuk menunjukkan parameter fungsi vararg. Anda dapat menggunakannya dalam banyak ekspresi seolah-olah itu adalah daftar nilai (seperti print(...)atau local args = {...}) tetapi ada beberapa hal yang tidak dapat Anda lakukan dengannya, seperti merujuknya pada closure ( function(...) return function() return ... end end).
Kolonel Thirty Two
8

Denotational Semantics menyediakan basis matematika untuk menggambarkan bagaimana nilai dan variabel bekerja dalam bahasa pemrograman. Itu dijelaskan dengan sangat baik dalam Gelar Ilmu Komputer saya bahwa saya mendapat nilai tertinggi dalam ujian Denotational Semantics, kemudian melupakan sebagian besar dan tidak pernah memiliki kebutuhan untuk menggunakannya dalam kehidupan 20 tahun sebagai seorang programmer.

Anda dapat memilih untuk menggunakan dasar matematika yang terdefinisi dengan baik, atau Anda dapat menggunakan terminologi informal seperti "status kelas pertama". Saya akan belajar lebih banyak lagi jika kursus ini didasarkan pada Pragmatik Bahasa Pemrograman Scott, namun matematika formal diperlukan untuk seseorang yang akan melakukan PhD dalam desain bahasa pemrograman.

Jika Anda membaca spesifikasi untuk sebagian besar bahasa pemrograman, Anda akan melihat kurangnya pembangkang dari Denotational Semantics, namun sebagian besar bahasa yang dirancang dengan baik memiliki seseorang di tim yang ahli dalam desain bahasa pemrograman, maka memahami Denotational Semantics dengan baik.

Jadi Michearl Scott menggunakan terminologi informal yang memiliki beberapa hubungan dengan matematika formal, sambil menyajikan subjek dengan cara yang sebagian besar programmer dapat memperoleh manfaat dari. Terminologinya tidak digunakan oleh orang lain, jadi itu tidak berguna untuk berkomunikasi, tetapi itu memberi Anda dasar yang baik pada pertanyaan yang harus Anda tanyakan ketika melihat bahasa pemrograman baru untuk pertama kalinya.

Perhatikan bahwa Michael L. Scott adalah peneliti terkemuka di Computer Sci, jadi akan mengerti dan sangat senang menggunakan matematika formal, tetapi seperti peneliti terbaik, ia terampil dalam menjelaskan penerapan penelitian kepada kita semua.

Ian
sumber
Terima kasih. Buku mana yang digunakan di kelas Anda? Buku mana yang Anda rekomendasikan sekarang? Saya seorang pembelajar mandiri
Tim
@Tim, saya melakukan kelas saya lebih dari 20 tahun yang lalu! Saya berharap buku Michearl Scott adalah salah satu yang terbaik dan akan mencakup lebih dari yang Anda butuhkan kecuali Anda akan melakukan penelitian tingkat Phd.
Ian
3

Tidak, kata "pertama" dalam "kelas satu" dan "tingkat pertama" memiliki arti yang berbeda.

Tapi ya, konsep "kelas satu" dan "tingkat pertama" saling terkait. Mereka berdua tentang mengklasifikasikan konsep mana yang bahasa dapat menggambarkan bahasa juga bisa abstrak.

Sebuah konsep adalah kelas satu jika mekanisme abstraksi bahasa yang biasa dapat abstrak atas konsep itu.

Sebagai contoh, bahasa pemrograman Java dapat menggambarkan bilangan bulat, dan semua mekanisme biasa untuk abstrak atas bilangan bulat (menerimanya sebagai parameter metode, mengembalikannya sebagai hasil fungsi, menyimpannya dalam struktur data, ...) berfungsi untuk bilangan bulat.

Sebuah konsep adalah urutan pertama jika tidak dapat digunakan untuk abstrak.

Sebagai contoh, sekali lagi di Jawa, kita dapat menggunakan metode untuk abstrak atas hal-hal tertentu. Tetapi kita tidak dapat menggunakan metode untuk abstrak metode, karena nama metode tidak dapat dilewatkan sebagai parameter metode. Ini berbeda dalam JavaScript, di mana Anda dapat menggunakan notasi braket untuk mengakses properti objek dengan namanya sebagai string, dan Anda bisa abstrak di atas string.

Sebuah konsep adalah urutan kedua jika dapat digunakan untuk abstrak atas penggunaan urutan pertama itu sendiri, tetapi tidak lebih dari penggunaan urutan kedua.

Misalnya, di Jawa, Anda bisa menggunakan Generik untuk abstrak lebih dari jenis (seperti pada class Foo<T> { public List<T> content; }). Namun, Anda tidak dapat menggunakan generik untuk abstrak di atas Generik (seperti pada class Bar<T> { public T<Int> content; }). Ini berbeda dalam Scala.

Konsep adalah orde ketiga jika dapat digunakan untuk abstrak atas penggunaan orde pertama dan orde kedua, tetapi tidak lebih dari penggunaan orde kedua.

Dan seterusnya.

Akhirnya, sebuah konsep adalah orde yang lebih tinggi jika dapat digunakan untuk abstrak daripada penggunaannya sendiri secara sewenang-wenang.

Rangkuman: Jika fitur abstraksi adalah kelas satu, itu juga tingkat tinggi. Dan jika fitur abstraksi adalah urutan pertama, itu tidak bisa kelas satu.

Toxaris
sumber
1
Anda dapat melakukannya List<List>di Jawa. Mungkin Anda bisa mengklarifikasi apa yang Anda maksud dengan bagian itu?
Polygnome
1
Poin bagus. Maksudku: class Foo<A> { A<Int> ... }. Maksud saya, saya menggunakan parameter tipe generik sebagai kelas generik. Maka, Foo<List>akan instantiate A<Int>ke List<Int>. Di Jawa, itu tidak mungkin. Saya akan mencoba mengedit ini untuk jawabannya nanti.
Toxaris
Memang itu tidak mungkin.
Polygnome
Saya sekarang mengganti List<List>contoh yang menyesatkan . Terima kasih telah menunjukkan masalah ini, @Polygnome.
Toxaris
@ Toksi Saya pikir ini hanya terminologi istimewa yang Anda buat sendiri. Sebuah 'konsep' bukan orde pertama atau orde kedua, sebuah kuantifier logis.
Miles Rout
2

Apa dasar matematika untuk nilai-nilai kelas pertama / kedua / ketiga dalam bahasa pemrograman?

Tidak ada yang saya sadari.

Terminologi mengingatkan saya pada logika urutan pertama / kedua, tetapi apakah mereka terkait?

Tidak juga.

"Kelas" elemen bahasa pemrograman hanyalah cara singkat berpikir tentang pertanyaan hal-hal apa yang ingin digunakan oleh pengguna bahasa saya untuk memanipulasi secara terprogram ? Misalnya, C # memberi Anda rangkaian operasi yang kaya untuk memanipulasi nilai , serangkaian cara yang kurang kaya untuk memanipulasi tipe , dan tidak ada operasi yang memanipulasi label .

Namun intuisi Anda bahwa ada koneksi di sini tidak sepenuhnya salah tempat. Ada analogi yang dibuat dari logika orde pertama ke pemrograman prosedural, dan dari logika orde tinggi ke pemrograman fungsional. Logika urutan pertama adalah tentang manipulasi nilai secara logis; pemrograman prosedural adalah tentang manipulasi nilai-nilai program. Logika tingkat tinggi adalah tentang manipulasi logis dari pernyataan logika , pemrograman fungsional adalah tentang manipulasi fungsi program .

Mengapa kasus spesifik itu penting, sementara kasus lain tidak disebutkan?

Anda harus bertanya kepada penulis untuk jawaban yang pasti.

Saya tidak akan terlalu terpaku pada gagasan "kelas" ini. Itu bukan hal yang secara formal didefinisikan. Ini adalah singkatan yang digunakan perancang bahasa untuk berbicara tentang hal-hal apa saja yang dapat dimanipulasi secara terprogram.

Eric Lippert
sumber
2

"Nilai kelas", dalam konteks ini, adalah terminologi standar dalam teori bahasa pemrograman. Nilai kelas adalah sesuatu yang dapat dimanipulasi sebagai nilai normal dalam bahasa, sesuatu yang dapat dihitung pada saat runtime. Tentu saja, itu adalah definisi tautologis sampai Anda mendefinisikan semantik untuk bahasa tersebut, dan kemudian sebuah nilai adalah apa pun yang ditetapkan semantik sebagai nilai. Inti dari konsep ini adalah untuk mengidentifikasi apa yang dapat dimanipulasi secara langsung, bukan hanya diakses secara tidak langsung.

Misalnya, di hampir setiap bahasa pemrograman, bilangan bulat mesin dengan ukuran terbatas (mis. Bilangan bulat 8-bit, atau bilangan bulat 32-bit, atau bilangan bulat 64-bit, dll.) Adalah nilai kelas satu. Anda dapat menyimpannya dalam variabel, meneruskannya dan mengembalikannya ke fungsi, dll. Dalam sebagian besar bahasa tetapi tidak pada bahasa tingkat rendah seperti assembly dan C, string adalah nilai kelas satu - tetapi di C, mereka tidak, Anda hanya dapatkan pointer ke string. Di C, string dan array bukan nilai kelas pertama: misalnya Anda tidak bisa meneruskan array ke suatu fungsi, Anda tidak bisa menetapkan array ke variabel array, dll. Di C, fungsi bukan nilai kelas satu baik: Anda tidak dapat menyimpan fungsi dalam suatu variabel, hanya sebuah pointer ke suatu fungsi. Sebaliknya, string dan fungsi adalah nilai kelas satu di sebagian besar bahasa pemrograman tingkat tinggi: Anda dapat menyimpannya dalam sebuah string, dll.

Contoh konsep yang tidak kelas dalam banyak bahasa pemrograman yang dirancang untuk dikompilasi adalah tipe. Dalam bahasa seperti C atau Java, tipe hidup pada waktu kompilasi, Anda tidak dapat memanipulasi mereka menggunakan konstruksi bahasa. (Java juga memiliki sistem tipe dinamis berdasarkan kelas; kelas adalah nilai kelas pertama melalui refleksi.) Sebaliknya, bahasa seperti Python memiliki typefungsi yang mengembalikan nilai yang mewakili jenis argumennya.

Negasi "nilai kelas" dalam terminologi standar adalah "bukan nilai kelas". Istilah "nilai kelas dua" tidak umum digunakan, dan "nilai kelas tiga" bahkan lebih sedikit. Jangan berharap melihat mereka di luar buku ini. Sama sekali tidak ada dasar untuk mendefinisikan "kedua" sebagai "dapat diteruskan sebagai parameter" dan "ketiga" sebagai "tidak dapat diteruskan sebagai parameter", tidak ada skala hal yang dapat diberi nomor bermakna. Sangat sedikit bahasa yang membuat perbedaan antara nilai-nilai yang dapat dikirimkan sebagai parameter ke fungsi dan nilai-nilai yang dapat ditugaskan ke variabel, sehingga tidak berguna untuk mendefinisikan nama untuk konsep ini.

Gilles 'SANGAT berhenti menjadi jahat'
sumber