2009-07-24 19 views
82

मुझे पता है कि include, isset, require, print, echo, और कुछ अन्य कार्य नहीं हैं लेकिन भाषा संरचनाएं हैं।PHP निर्माण में एक भाषा निर्माण और "अंतर्निर्मित" फ़ंक्शन के बीच क्या अंतर है?

इनमें से कुछ भाषा संरचनाओं को ब्रांड्स की आवश्यकता है, अन्य नहीं।

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

कुछ के पास वापसी मूल्य है, अन्य नहीं।

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

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

उत्तर

123

मेरे इरादे से अधिक लंबा है; कृपया मेरे साथ सहन करें।)

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

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

// 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" तक घटा दिया जा सकता है, या इसके विपरीत (भाषा परिभाषाएं कोष्ठक जोड़ सकते हैं और साथ ही उनसे छुटकारा पा सकते हैं)। , वे प्रभावी रूप पार्सर में hardcoded रहे हैं जबकि कार्यों भाषा निर्माणों का एक सेट करने के लिए किया जाता है और पार्सर आपको लगता है कि मानचित्रण बदलने के लिए अनुमति देता है:

यही कारण है कि आप echo या print की तरह भाषा निर्माणों को फिर से परिभाषित नहीं कर सकते हैं की जड़ है संकलित या रनटाइम पर अपनी भाषा संरचनाओं या अभिव्यक्तियों के सेट को प्रतिस्थापित करने के लिए।

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

और जानकारी:

  • Backus-Naur form, वाक्य रचना औपचारिक भाषाओं (याक इस फार्म का उपयोग करता है)

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

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

वाह! इस महान उत्तर के लिए धन्यवाद! –

+2

ग्रेट उत्तर जो कई भाषाओं पर लागू होने के लिए पर्याप्त रूप से खुला है, न केवल PHP। धन्यवाद! –

+0

निश्चित रूप से बहुत लंबा, लेकिन वाह! निश्चित रूप से इसके लायक है। –

4

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

अलावा मुझे नहीं लगता कि कि वहाँ अन्य मतभेद हैं कि (देखें Zend/zend_language_parser.y)

1

आप override built-in functions कर सकते हैं। कीवर्ड हमेशा के लिए हैं।

+0

यह एक अंतर्निहित फ़ंक्शन नहीं है। एपीडी (उन्नत PHP डीबगर) एक्सटेंशन में परिभाषित किया गया है। –

+0

ओवरराइडिंग कार्यों के बारे में, आप रनकिट एक्सटेंशन पर लूट ले सकते हैं (यह कोर नहीं है, यह एक एक्सटेंशन है, इसलिए ओपी का जवाब नहीं है, लेकिन केवल इस जवाब के लिए); यह वास्तव में शक्तिशाली है, और एपीडी से अधिक हालिया है (और मेरा मानना ​​है कि मैंने कुछ समय पहले सुना था कि कुछ लोग अभी भी इस पर काम कर रहे थे, भले ही यह pecl.php.net पर नहीं दिखाया गया हो) –

14

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

एक परिणाम यह है कि वे तेजी से कर रहे हैं (कई बार पढ़ा या तो मैंने सुना है /)

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

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 के आंतरिक के बारे में बहुत कुछ पता है ...इतना है कि यह अभी हो जाएगा ^^

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

के बारे में पता होगा रहे हैं (और मैं वास्तव में अन्य उत्तर से रुचि, btw ^^)

एक संदर्भ के रूप में: (यह list of keywords and language constructs in PHP

+0

आपके पास एक ऐसा कार्य हो सकता है जो एक गैर- संदर्भ द्वारा चर ले कर नोटिस उत्पन्न किए बिना चर सेट करें। यह जारीकर्ता() जैसी भाषा संरचनाओं तक ही सीमित नहीं है। –

+0

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

संबंधित मुद्दे