मैं रिवर्स ऑर्डर में सवालों का जवाब देने जा रहा हूं:
foreach
rewind
कॉल करने के लिए बिना पूरी तरह से काम करता है क्या उन foreach
और while
के बीच मतभेद जब iterators
foreach
आंतरिक rewind()
के लिए एक कॉल करता है के साथ काम करने, यही कारण है कि आप इसे अपने आप को क्या करना है नहीं है। यह हमेशा किया जाता है, इसलिए यदि आप पहले से ही एक इटरेटर का उपयोग कर चुके हैं, तो foreach
लूप शुरुआत से शुरू हो जाएगा। (आप इसे NoRewindIterator
में लपेटकर इससे बच सकते हैं)।
सरणी कभी नहीं लगाते हैं या क्यों $ iterator-> रिवाइंड() पाश
एसपीएल iterators तैयार कर रहे हैं foreach
साथ और प्रयोग की जाने वाली, जबकि डुप्लिकेट विधि में कॉल से बचने के लिए के लिए आवश्यक है बुलाया गया है ये मामला। यदि RecursiveIteratorIterator
निर्माण पर RecursiveArrayIterator::rewind()
विधि को कॉल करेगा, तो इसे फिर से कॉल किया जाएगा जब foreach
लूप प्रारंभ होता है। यही कारण है कि कॉल नहीं किया जाता है।
अतिरिक्त ए नहीं सी क्यों?
इस पता लगाने के लिए यह देखने के लिए जो RecursiveArrayIterator
के तरीकों वास्तव में कहा जाता हो अच्छा है:
<?php
class DebugRAI extends RecursiveArrayIterator {
public function rewind() { echo __METHOD__, "\n"; return parent::rewind(); }
public function current() { echo __METHOD__, "\n"; return parent::current(); }
public function key() { echo __METHOD__, "\n"; return parent::key(); }
public function valid() { echo __METHOD__, "\n"; return parent::valid(); }
public function next() { echo __METHOD__, "\n"; return parent::next(); }
}
$array = array("A", "B", "C");
$iterator = new RecursiveIteratorIterator(new DebugRAI($array));
while ($iterator->valid()) {
echo $iterator->current(), "\n";
$iterator->next();
}
यह निम्न उत्पादन का उत्पादन:
DebugRAI::valid
DebugRAI::current
A
DebugRAI::valid
DebugRAI::valid
A
DebugRAI::next
DebugRAI::valid
DebugRAI::valid
DebugRAI::current
B
DebugRAI::next
DebugRAI::valid
DebugRAI::valid
DebugRAI::current
C
DebugRAI::next
DebugRAI::valid
DebugRAI::valid
उत्पादन थोड़ा अजीब लग रहा है , विशेष रूप से दूसरा पुनरावृत्ति next()
कॉल को याद करता है, इसलिए यह केवल उसी तत्व पर रहता है।
इस का कारण यह RecursiveIteratorIterator
कार्यान्वयन में एक विशेष लक्षण है: Iterators RS_START
राज्य में शुरू और इस राज्य में पहली next
कॉल केवल hasChildren()
की जाँच करता है, लेकिन वास्तव में अंतर्निहित इटरेटर के next()
विधि कॉल नहीं करता है। ऐसा करने के बाद यह RS_NEXT
मोड में स्विच करता है जिसमें next()
कॉल ठीक से होता है। यही कारण है कि आगे की चाल एक कदम से देरी हो रही है।
मेरी आंखों में यह एक बग है, लेकिन https://bugs.php.net/bug.php?id=44063 अन्यथा दावा करता है।
IteratorIterator भी अजीब व्यवहार करता है अगर आप रिवाइंड नहीं कहते हैं। http://stackoverflow.com/questions/2458955/why-must-i-rewind-iteratoriterator – goat
@rambocoder ने अभी भी यह देखा है .. यह एक बग की तरह दिख रहा है – Baba
मैंने इसे अकेला छोड़ दिया क्योंकि मेरा पहला अंतर्ज्ञान अगर मैं था लेखन स्प्लिड, इसे [जैसे] [http://www.php.net/~helly/php/ext/spl/iteratoriterator_8inc_source.html) (बस विधि कॉल अग्रेषित करना होगा), शायद एक बूल चर के साथ वापसी मूल्यों को कैश करने के लिए। लेकिन, जब मैंने 'कैशिंगइटरेटर' जैसी चीजों के बारे में सोचना शुरू किया और पूरे इटरेटर/सजावटी प्रतिमान अभी भी 'रिकर्सिवइटरेटर इटरेटर' जैसे जटिल इटरेटर्स के साथ काम करेंगे, और पागल क्षणों में अपवाद/त्रुटियों को फेंक दिया जाएगा, बिना किसी बारे में सोचना बहुत जटिल था बहुत सारा प्रयास। – goat