2012-11-11 9 views
13

में लूप के दौरान फ़ंक्शन सिमुलेटिंग कैसे लिखें, मैं लूप के दौरान अनुकरण करने वाले फ़ंक्शन को कैसे लिख सकता हूं? इसे 2 तर्क लेना चाहिए: निष्पादित करने के लिए स्थिति और अभिव्यक्ति।स्कैला

val whileLoop: (Boolean,Any)=>Unit = (condition:Boolean, expression:Any) => { 
expression 
if(condition) whileLoop(condition,expression) 
() }  

लेकिन यह, यह काम नहीं करता लगता है जैसे:

मैं निम्नलिखित की कोशिश की

val arr = Array[Int](-2,5,-5,9,-3,10,3,4,1,2,0,-20)  

इसके अलावा, मैं चर मैं है:

var i = 0 

मैं आगमन के सभी तत्वों को प्रिंट करना चाहते हैं मैं सरणी है। मैं ऐसा कर सकते हैं निम्न कोड के साथ:

while(i<arr.length) { println(tab(i)); i+=1 } 

मैं अपने whileLoop फंक्शन का उपयोग करके भी ऐसा ही करना चाहते हैं। लेकिन मैं फ़ंक्शन नहीं लिख सकता जो चर के संदर्भ में आता है और उसे संशोधित करता है। मैं केवल एक तत्व के साथ सरणी का उपयोग कर सकता हूं, उदा।

val nr = Array(0) 

और समारोह:

val printArray: Array[Int]=>Unit = (n:Array[Int]) => { 
println(arr(n(0))) 
n(0)+=1 
() 
} 

और उसके बाद में उपयोग करते हुए मेरे whileLoop: StackOverflowError

whileLoop(nr(0)<arr.length, printArray) 

ऊपर कोड का उपयोग करने के बाद मैं और एन.आर. (0) है शून्य के बराबर । फ़ंक्शन का पालन करने के बाद:

val printArray: Array[Int]=>Unit = (n:Array[Int]) => { 
println(arr(nr(0))) 
nr(0)+=1 
() 
} 

एक ही परिणाम देता है।

मैं सही समारोह whileLoop कैसे लिख सकता हूँ और प्रयोग है कि सभी आगमन तत्वों मुद्रित करने के लिए कर सकते हैं?

सलाह के लिए अग्रिम धन्यवाद।

उत्तर

26

आपके कार्यान्वयन के साथ मुख्य समस्या यह है कि स्थिति और अभिव्यक्ति का मूल्यांकन केवल एक बार किया जाता है, जब आप पहली बार whileLoop पर कॉल करते हैं। रिकर्सिव कॉल में, आप केवल एक मान पास करते हैं, अभिव्यक्ति नहीं।

आप द्वारा नाम तर्क का उपयोग करके इस का समाधान कर सकते हैं:

def whileLoop(cond : =>Boolean, block : =>Unit) : Unit = 
    if(cond) { 
    block 
    whileLoop(cond, block) 
    } 

एक उदाहरण के रूप:

scala> val a = Array(1, 2, 3) 
scala> var i = 0 
scala> whileLoop(i < a.length, { println(i); i += 1 }) 
1 
2 
3 

ध्यान दें कि चर a और i सही ढंग से दर्शाया जाता है। आंतरिक रूप से, स्कैला कंपाइलर ने फ़ंक्शन दोनों स्थितियों और अभिव्यक्ति (ब्लॉक) के लिए बनाया, और ये कार्य उनके पर्यावरण के संदर्भ को बनाए रखते हैं।

भी ध्यान रखें कि अधिक वाक्यात्मक चीनी awesomeness के लिए, आप एक currified समारोह के रूप में whileLoop परिभाषित कर सकते हैं:

def whileLoop(cond : =>Boolean)(block : =>Unit) : Unit = 
    if(cond) { 
    block 
    whileLoop(cond)(block) 
    } 

यह अनुमति देता है आप यह सिर्फ एक वास्तविक पाश जबकि तरह कॉल करने के लिए:

whileLoop(i < a.length) { 
    println(a(i)) 
    i += 1 
} 
+1

बहुत बहुत धन्यवाद - यह वही था जो मुझे चाहिए था। मैं गलत समझता हूं कि क्या गलत था। – Paul

2

यह क्या मैं इसके साथ आया: सबसे पहले, आपके फ़ंक्शन को इन 4 तर्कों की आवश्यकता है:

- array which is yet to be processed 
- predicate that tells the function when to stop 
- function that takes the array to be processed and current state and produces a new state 
- and state that is being propagated through the recurion: 

मुझे लगता है कि कोड सुंदर आत्म व्याख्यात्मक है:

def whileFunc[A,B](over: Array[A], predicate: Array[A] => Boolean, apply: (Array[A],B) => B, state: B):B = { 
    val doIterate = predicate(over) 
    if(doIterate) whileFunc(over.tail, predicate, apply, apply(over,state)) else state 
} 

इस एक बहुत अच्छे बनाया जा सकता है, लेकिन मैं इसे यथासंभव आसान बनाने का प्रयास। सरणी में सभी तत्वों को गिनती के लिए, आप यह बहुत की तरह कहेंगे:

scala>  whileFunc(Array(1,2,3), (a:Array[Int]) => !a.isEmpty,(a:Array[Int],s: Int) => s + a.head, 0) 
res5: Int = 6 

तत्वों में से प्रत्येक मुद्रित करने के लिए:

whileFunc[Int, Unit](Array(1,2,3), (a:Array[Int]) => !a.isEmpty,(a:Array[Int],s: Unit) => print(a.head), Unit) 
123 

वैसे, आप सामान के इस प्रकार में रुचि रखते हैं, तो, मैं आपको स्कैला में कार्यात्मक प्रोग्रामिंग खरीदने की सलाह दूंगा, ऐसे दो अध्याय हैं जो आपको इस तरह के कार्यों को लागू करते हैं। बहुत मज़ा हैं।

+0

धन्यवाद भी, यह दिलचस्प विकल्प है। – Paul