(Ini lebih lama dari yang saya inginkan; mohon bersabarlah.)
Sebagian besar bahasa terdiri dari sesuatu yang disebut "sintaks": bahasa terdiri dari beberapa kata kunci yang ditentukan dengan baik, dan rangkaian lengkap ekspresi yang dapat Anda buat dalam bahasa tersebut dibangun dari sintaks tersebut.
Sebagai contoh, katakanlah Anda memiliki "bahasa" aritmatika empat fungsi sederhana yang hanya menggunakan bilangan bulat satu digit sebagai masukan dan sepenuhnya mengabaikan urutan operasi (saya katakan itu adalah bahasa sederhana). Bahasa itu dapat didefinisikan dengan sintaks:
// The | means "or" and the := represents definition
$expression := $number | $expression $operator $expression
$number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
$operator := + | - | * | /
Dari ketiga aturan ini, Anda dapat membuat sejumlah ekspresi aritmatika dengan input satu digit. Anda kemudian dapat menulis parser untuk sintaks ini yang memecah setiap input yang valid ke dalam jenis komponen ( $expression
, $number
, atau $operator
) dan penawaran dengan hasilnya. Misalnya, ekspresi 3 + 4 * 5
dapat dipecah sebagai berikut:
// Parentheses used for ease of explanation; they have no true syntactical meaning
$expression = 3 + 4 * 5
= $expression $operator (4 * 5) // Expand into $exp $op $exp
= $number $operator $expression // Rewrite: $exp -> $num
= $number $operator $expression $operator $expression // Expand again
= $number $operator $number $operator $number // Rewrite again
Sekarang kami memiliki sintaks yang diurai sepenuhnya, dalam bahasa yang kami tentukan, untuk ekspresi asli. Setelah kita memiliki ini, kita dapat menelusuri dan menulis parser untuk menemukan hasil dari semua kombinasi $number $operator $number
, dan mengeluarkan hasil saat kita hanya memiliki satu yang $number
tersisa.
Perhatikan bahwa tidak ada $expression
konstruksi yang tersisa dalam versi parsing terakhir dari ekspresi asli kita. Itu karena $expression
selalu dapat direduksi menjadi kombinasi hal-hal lain dalam bahasa kita.
PHP kurang lebih sama: konstruksi bahasa diakui sebagai padanan dari kami $number
atau $operator
. Mereka tidak dapat direduksi menjadi konstruksi bahasa lain ; sebaliknya, mereka adalah unit dasar dari mana bahasa itu dibangun. Perbedaan utama antara fungsi dan konstruksi bahasa adalah ini: parser berhubungan langsung dengan konstruksi bahasa. Ini menyederhanakan fungsi menjadi konstruksi bahasa.
Alasan konstruksi bahasa mungkin atau mungkin tidak memerlukan tanda kurung dan alasan beberapa memiliki nilai kembalian sementara yang lain tidak bergantung sepenuhnya pada detail teknis spesifik dari implementasi parser PHP. Saya tidak begitu paham tentang cara kerja parser, jadi saya tidak bisa menjawab pertanyaan-pertanyaan ini secara spesifik, tapi bayangkan sejenak bahasa yang dimulai dengan ini:
$expression := ($expression) | ...
Secara efektif, bahasa ini bebas mengambil ekspresi apa pun yang ditemukannya dan menghilangkan tanda kurung di sekitarnya. PHP (dan di sini saya menggunakan tebakan murni) dapat menggunakan sesuatu yang serupa untuk konstruksi bahasanya: print("Hello")
mungkin dikurangi menjadi print "Hello"
sebelum diurai, atau sebaliknya (definisi bahasa dapat menambahkan tanda kurung dan juga menghilangkannya).
Inilah akar dari mengapa Anda tidak dapat mendefinisikan ulang konstruksi bahasa seperti echo
atau print
: mereka secara efektif dikodekan ke dalam parser, sedangkan fungsi dipetakan ke sekumpulan konstruksi bahasa dan parser memungkinkan Anda untuk mengubah pemetaan itu pada kompilasi- atau runtime ke gantilah kumpulan konstruksi atau ekspresi bahasa Anda sendiri.
Pada akhirnya, perbedaan internal antara konstruksi dan ekspresi adalah ini: konstruksi bahasa dipahami dan ditangani oleh parser. Fungsi bawaan, sementara disediakan oleh bahasa, dipetakan dan disederhanakan menjadi sekumpulan konstruksi bahasa sebelum parsing.
Info lebih lanjut:
- Bentuk Backus-Naur , sintaks yang digunakan untuk mendefinisikan bahasa formal (yacc menggunakan formulir ini)
Sunting: Membaca beberapa jawaban lain, orang membuat poin bagus. Diantara mereka:
- Bahasa bawaan lebih cepat untuk dipanggil daripada fungsi. Ini benar, jika hanya sedikit, karena interpreter PHP tidak perlu memetakan fungsi itu ke bahasa bawaannya yang setara sebelum parsing. Namun, pada mesin modern, perbedaannya bisa diabaikan.
- Sebuah bahasa bawaan melewati pemeriksaan kesalahan. Ini mungkin atau mungkin tidak benar, tergantung pada implementasi internal PHP untuk setiap builtin. Memang benar bahwa lebih sering daripada tidak, fungsi akan memiliki pemeriksaan kesalahan yang lebih canggih dan fungsionalitas lain yang tidak ada di dalamnya.
- Konstruksi bahasa tidak dapat digunakan sebagai callback fungsi. Ini benar, karena konstruk bukanlah fungsi . Mereka adalah entitas yang terpisah. Saat Anda membuat kode bawaan, Anda tidak mengkodekan fungsi yang membutuhkan argumen - sintaks dari bawaan ditangani langsung oleh parser, dan dikenali sebagai bawaan, bukan sebagai fungsi. (Ini mungkin lebih mudah dipahami jika Anda mempertimbangkan bahasa dengan fungsi kelas satu: efektif, Anda dapat meneruskan fungsi sebagai objek. Anda tidak dapat melakukannya dengan bawaan.)
Konstruksi bahasa disediakan oleh bahasa itu sendiri (seperti instruksi seperti "if", "while", ...); karena itulah nama mereka.
Salah satu konsekuensi dari itu adalah mereka lebih cepat dipanggil daripada fungsi yang ditentukan sebelumnya atau yang ditentukan pengguna (atau begitulah yang saya dengar / baca beberapa kali)
Saya tidak tahu bagaimana melakukannya, tetapi satu hal yang dapat mereka lakukan (karena terintegrasi langsung ke dalam bahasa) adalah "melewati" semacam mekanisme penanganan kesalahan. Misalnya, isset () dapat digunakan dengan variabel yang tidak ada tanpa menyebabkan pemberitahuan, peringatan, atau kesalahan.
* Perhatikan bahwa ini bukan kasus konstruksi semua bahasa.
Perbedaan lain antara fungsi dan konstruksi bahasa adalah beberapa di antaranya dapat dipanggil tanpa tanda kurung, seperti kata kunci.
Misalnya :
Di sini juga, tidak demikian halnya untuk semua konstruksi bahasa.
Saya kira sama sekali tidak ada cara untuk "menonaktifkan" konstruksi bahasa karena itu adalah bagian dari bahasa itu sendiri. Di sisi lain, banyak fungsi PHP "built-in" tidak benar-benar built-in karena disediakan oleh ekstensi sedemikian rupa sehingga selalu aktif (tetapi tidak semuanya)
Perbedaan lainnya adalah bahwa konstruksi bahasa tidak dapat digunakan sebagai "penunjuk fungsi" (maksud saya, callback, misalnya):
Saya tidak memiliki ide lain yang muncul di benak saya saat ini ... dan saya tidak tahu banyak tentang internal PHP ... Jadi itu saja sekarang ^^
Jika Anda tidak mendapatkan banyak jawaban di sini, mungkin Anda bisa menanyakan hal ini ke milis internal (lihat http://www.php.net/mailing-lists.php ), di mana terdapat banyak pengembang inti PHP; mereka adalah orang-orang yang mungkin tahu tentang hal itu ^^
(Dan saya sangat tertarik dengan jawaban lainnya, btw ^^)
Sebagai referensi: daftar kata kunci dan konstruksi bahasa di PHP
sumber
Setelah mengarungi kode, saya telah menemukan bahwa php mem-parsing beberapa pernyataan dalam file yacc. Jadi itu kasus khusus.
(lihat Zend / zend_language_parser.y)
Selain itu saya rasa tidak ada perbedaan lainnya.
sumber
Anda dapat mengganti fungsi bawaan . Kata kunci selamanya.
sumber