PHP में एक भाषा निर्माण और एक "अंतर्निहित" फ़ंक्शन के बीच अंतर क्या है?


92

मुझे पता है कि include, isset, require, print, echo, और कुछ अन्य कार्यों लेकिन भाषा निर्माणों नहीं हैं।

इन भाषा निर्माणों में से कुछ को कोष्ठक की आवश्यकता होती है, अन्य नहीं।

require 'file.php';
isset($x);

कुछ का रिटर्न वैल्यू है, अन्य नहीं।

print 'foo'; //1
echo  'foo'; //no return value

तो एक भाषा निर्माण और एक अंतर्निहित फ़ंक्शन के बीच आंतरिक अंतर क्या है ?

जवाबों:


131

(यह मेरे इच्छित से अधिक लंबा है; कृपया मेरे साथ सहन करें।)

अधिकांश भाषाएं कुछ "सिंटैक्स" से बनी होती हैं: भाषा कई अच्छी तरह से परिभाषित कीवर्ड से युक्त होती है, और उस भाषा में आपके द्वारा बनाई जा सकने वाली अभिव्यक्तियों की पूरी श्रृंखला उस सिंटैक्स से निर्मित होती है।

उदाहरण के लिए, मान लें कि आपके पास एक साधारण चार-फ़ंक्शन अंकगणित "भाषा" है, जो इनपुट के रूप में केवल एकल-अंक पूर्णांक लेता है और संचालन के आदेश को पूरी तरह से अनदेखा करता है (मैंने आपको बताया कि यह एक सरल भाषा थी)। उस भाषा को वाक्य रचना द्वारा परिभाषित किया जा सकता है:

// The | means "or" and the := represents definition
$expression := $number | $expression $operator $expression
$number := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
$operator := + | - | * | /

इन तीन नियमों से, आप किसी भी संख्या में एकल-अंक-इनपुट अंकगणितीय अभिव्यक्तियों का निर्माण कर सकते हैं। इसके बाद आप इस वाक्य रचना के लिए एक पार्सर लिख सकते हैं कि उसके घटक प्रकार में किसी भी मान्य इनपुट (नीचे टूट जाता है $expression, $numberया $operatorपरिणाम के साथ) और संबंधित है। उदाहरण के लिए, अभिव्यक्ति 3 + 4 * 5को निम्नानुसार तोड़ा जा सकता है:

// 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

अब हमारे पास मूल अभिव्यक्ति के लिए, हमारी परिभाषित भाषा में एक पूरी तरह से व्यवस्थित वाक्य रचना है। एक बार जब हमारे पास यह हो जाता है, तो हम एक संयोजन के माध्यम से जा सकते हैं और सभी संयोजनों के परिणामों को खोजने के लिए एक परिणाम लिख सकते हैं $number $operator $number, और एक परिणाम $numberछोड़ सकते हैं जब हमारे पास केवल एक ही होता है ।

ध्यान दें कि $expressionहमारी मूल अभिव्यक्ति के अंतिम पार्स संस्करण में कोई निर्माण नहीं बचा है। ऐसा इसलिए है क्योंकि $expressionहमेशा हमारी भाषा में अन्य चीजों के संयोजन को कम किया जा सकता है।

PHP बहुत समान है: भाषा निर्माण हमारे $numberया के बराबर के रूप में पहचाने जाते हैं $operator। उन्हें अन्य भाषा निर्माणों में कम नहीं किया जा सकता है ; इसके बजाय, वे आधार इकाइयाँ हैं जिनसे भाषा निर्मित होती है। फ़ंक्शंस और भाषा निर्माणों के बीच महत्वपूर्ण अंतर यह है: पार्सर सीधे भाषा निर्माणों से संबंधित है। यह भाषा निर्माण में कार्यों को सरल बनाता है।

कारण यह है कि भाषा का निर्माण कोष्ठकों की आवश्यकता हो सकती है या नहीं हो सकती है और कुछ का रिटर्न मान है जबकि अन्य पूरी तरह से PHP पार्सर कार्यान्वयन के विशिष्ट तकनीकी विवरण पर निर्भर नहीं करते हैं। मैं उस अच्छी तरह से वाकिफ नहीं हूं कि पार्सर कैसे काम करता है, इसलिए मैं इन सवालों को विशेष रूप से संबोधित नहीं कर सकता, लेकिन एक दूसरी भाषा के लिए कल्पना करें जो इस पर शुरू होती है:

$expression := ($expression) | ...

प्रभावी रूप से, यह भाषा किसी भी भाव को लेने और आसपास के कोष्ठकों से छुटकारा पाने के लिए स्वतंत्र है। PHP (और यहां मैं शुद्ध अनुमान लगा रहा हूं) अपनी भाषा के निर्माण के लिए कुछ समान काम कर सकता है: पार्स print("Hello")करने print "Hello"से पहले नीचे कम हो सकता है, या इसके विपरीत (भाषा की परिभाषाएं कोष्ठक जोड़ने के साथ-साथ उनसे छुटकारा भी पा सकती हैं)।

यह इस बात की जड़ है कि आप भाषा निर्माण को फिर से परिभाषित क्यों नहीं कर सकते हैं echoया print: वे प्रभावी रूप से पार्सर में हार्डकोड किए जाते हैं, जबकि फ़ंक्शन भाषा निर्माणों के एक सेट पर मैप किए जाते हैं और पार्सर आपको संकलन या रनटाइम पर उस मैपिंग को बदलने की अनुमति देता है भाषा निर्माण या अभिव्यक्ति के अपने सेट को स्थानापन्न करें।

दिन के अंत में, निर्माण और अभिव्यक्तियों के बीच आंतरिक अंतर यह है: भाषा निर्माणों को समझा जाता है और पार्सर द्वारा निपटा जाता है। बिल्ट-इन फ़ंक्शंस, जबकि भाषा द्वारा प्रदान किए गए हैं, मैप किए जाते हैं और पार्स करने से पहले भाषा के निर्माण के एक सेट के लिए सरलीकृत किया जाता है।

और जानकारी:

  • बैकस-नौर रूप , औपचारिक भाषाओं को परिभाषित करने के लिए प्रयुक्त वाक्यविन्यास (yacc इस रूप का उपयोग करता है)

संपादित करें: कुछ अन्य उत्तरों के माध्यम से पढ़ना, लोग अच्छे अंक बनाते हैं। उनमें से:

  • एक भाषा बिलियन एक फ़ंक्शन की तुलना में कॉल करने के लिए तेज़ है। यह सच है, अगर केवल मामूली रूप से, क्योंकि PHP दुभाषिया को पार्स करने से पहले उस फ़ंक्शन को उसके भाषा-निर्मित समकक्षों में मैप करने की आवश्यकता नहीं है। एक आधुनिक मशीन पर, हालांकि, यह अंतर काफी नगण्य है।
  • एक भाषा अंतर्निहित त्रुटि-जाँच को बायपास करती है। प्रत्येक बिलिन के लिए PHP के आंतरिक कार्यान्वयन के आधार पर यह सच हो सकता है या नहीं भी हो सकता है। यह निश्चित रूप से सच है कि अधिक बार नहीं, फ़ंक्शंस में अधिक उन्नत त्रुटि-जांच और अन्य कार्यक्षमता होगी जो बिल्डिन नहीं करते हैं।
  • भाषा निर्माण का उपयोग फ़ंक्शन कॉलबैक के रूप में नहीं किया जा सकता है। यह सच है, क्योंकि एक निर्माण एक फ़ंक्शन नहीं है । वे अलग संस्थाएँ हैं। जब आप एक बिलिन को कोड करते हैं, तो आप एक फ़ंक्शन को कोड नहीं कर रहे हैं जो तर्क लेता है - बिलिन के सिंटैक्स को सीधे पार्सर द्वारा संभाला जाता है, और फ़ंक्शन के बजाय एक बेसिन के रूप में पहचाना जाता है। (यह समझना आसान हो सकता है यदि आप प्रथम श्रेणी के कार्यों के साथ भाषाओं पर विचार करते हैं: प्रभावी रूप से, आप ऑब्जेक्ट के रूप में कार्यों को पास कर सकते हैं। आप बिलिंस के साथ ऐसा नहीं कर सकते।)

2
बहुत बढ़िया उत्तर जो ओपन-एंडेड है, जो कई भाषाओं में लागू होता है, न कि केवल PHP पर। धन्यवाद!
लेवी मोटेलो

15

भाषा निर्माण भाषा द्वारा ही प्रदान किए जाते हैं (जैसे "यदि", "जबकि", ...) जैसे निर्देश; इसलिए उनका नाम।

इसका एक परिणाम यह है कि वे पूर्व-परिभाषित या उपयोगकर्ता द्वारा परिभाषित कार्यों की तुलना में अधिक तेज़ हैं (या मैंने कई बार सुना / पढ़ा है)

मुझे नहीं पता कि यह कैसे किया जाता है, लेकिन एक चीज जो वे कर सकते हैं (क्योंकि सीधे भाषा में एकीकृत होने के कारण) किसी प्रकार की त्रुटि से निपटने के तंत्र को "बायपास" किया जाता है। उदाहरण के लिए, बिना किसी सूचना, चेतावनी या त्रुटि के बिना isset () का उपयोग गैर-विद्यमान चर के साथ किया जा सकता है।

function test($param) {}
if (test($a)) {
    // Notice: Undefined variable: a
}

if (isset($b)) {
    // No notice
}

* ध्यान दें कि यह सभी भाषाओं के निर्माण की बात नहीं है।

फ़ंक्शंस और भाषा निर्माणों के बीच एक और अंतर यह है कि उनमें से कुछ को कीवर्ड के बिना कोष्ठक के बिना कहा जा सकता है।

उदाहरण के लिए :

echo 'test'; // language construct => OK

function my_function($param) {}
my_function 'test'; // function => Parse error: syntax error, unexpected T_CONSTANT_ENCAPSED_STRING

यहाँ भी, यह सभी भाषा निर्माणों के लिए नहीं है।

मुझे लगता है कि भाषा निर्माण को "अक्षम" करने का कोई तरीका नहीं है क्योंकि यह भाषा का हिस्सा है। दूसरी ओर, बहुत सारे "बिल्ट-इन" PHP फ़ंक्शन वास्तव में बिल्ट-इन नहीं होते हैं, क्योंकि वे एक्सटेंशन द्वारा प्रदान किए जाते हैं, ताकि वे हमेशा सक्रिय रहें (लेकिन उनमें से सभी नहीं)

एक और अंतर यह है कि भाषा निर्माण का उपयोग "फंक्शन पॉइंटर्स" के रूप में नहीं किया जा सकता है (मेरा मतलब है, कॉलबैक, उदाहरण के लिए):

$a = array(10, 20);

function test($param) {echo $param . '<br />';}
array_map('test', $a);  // OK (function)

array_map('echo', $a);  // Warning: array_map() expects parameter 1 to be a valid callback, function 'echo' not found or invalid function name

मेरे दिमाग में अभी कोई और विचार नहीं आ रहा है ... और मुझे PHP के इंटर्नल के बारे में ज्यादा जानकारी नहीं है ... इसलिए अभी यह सही होगा ^ ^

यदि आपको यहां बहुत अधिक उत्तर नहीं मिलते हैं, तो शायद आप इसे मेलिंग-लिस्ट इंटर्नल्स ( http://www.php.net/mailing-lists.php देखें ) से पूछ सकते हैं , जहां कई PHP कोर-डेवलपर्स हैं; वे हैं जो शायद उस सामान के बारे में जानते हैं ^ ^

(और मैं वास्तव में अन्य जवाबों से दिलचस्पी लेता हूं, ^ ^ ^)

एक संदर्भ के रूप में: PHP में कीवर्ड और भाषा का निर्माण


आपके पास एक फ़ंक्शन हो सकता है जो संदर्भ द्वारा चर लेने के बिना एक नोटिस उत्पन्न करने के बिना एक सेट चर को स्वीकार करता है। यह भाषा निर्माण जैसे कि isset () तक सीमित नहीं है।
टॉम हाई 7

ओह, इस बारे में नहीं सोचा था :-( धन्यवाद!
पास्कल मार्टिन

4

कोड के माध्यम से वैडिंग करने के बाद, मैंने पाया है कि php ने एक yacc फ़ाइल में कुछ कथनों को पार्स किया है। इसलिए वे विशेष मामले हैं।

(देखें Zend / zend_language_parser.y)

इसके अलावा मुझे नहीं लगता कि अन्य मतभेद हैं।


1

आप अंतर्निहित कार्यों को ओवरराइड कर सकते हैं । कीवर्ड्स हमेशा के लिए हैं।


यह बिल्ट-इन फ़ंक्शन नहीं है। APD (उन्नत PHP डीबगर) विस्तार में परिभाषित किया गया है।
इयोनू जी। स्टेन

ओवरराइडिंग फ़ंक्शंस के बारे में, आपको रनकिट एक्सटेंशन में एक लूट हो सकती है (यह या तो कोर नहीं है, यह एक एक्सटेंशन है, इसलिए ओपी का जवाब नहीं है, लेकिन केवल इस उत्तर के लिए); यह वास्तव में शक्तिशाली है, और एपीडी से अधिक हाल ही में (और मेरा मानना ​​है कि मैंने कुछ समय पहले सुना था कि कुछ लोग अभी भी इस पर काम कर रहे थे, भले ही इसे pecl.php.net पर नहीं दिखाया गया हो)
पास्कल मार्टिन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.