मेरे पास एक पुनरावर्ती कार्य है और मैं चाहता हूं कि कोई केवल फ़ंक्शन के सबसे बाहरी कॉल के लिए कुछ कथन निष्पादित करे। मैं इस कार्यक्षमता को कैसे प्राप्त करूं?

func fact(n int) int {
   if n == 0 {
      return 1
   }
   fact := n * fact(n-1)
   if outer_most{
       fmt.Printf(strconv.Itoa(n))
   }
   return fact 
}
func main() {
  fact(4)
}

इसे केवल 4 प्रिंट करना चाहिए

go
0
Shubham Chaudhary 27 पद 2017, 13:33

4 जवाब

सबसे बढ़िया उत्तर

प्रश्न का उत्तर देने के लिए: यदि किसी कारण से आप वास्तव में कुछ ऐसा चलाना चाहते हैं जो केवल सबसे बाहरी func कॉल के लिए है और एपीआई को बदलना नहीं चाहते हैं, तो गोलंग के पास रनटाइम लिब है। आप इसे इस प्रकार कर सकते हैं:

package main

import (
    "fmt"
    "runtime"
    "strconv"
)

func outer_most() bool {
    pc:=make([]uintptr,2)
    runtime.Callers(2,pc) //skip: 1 - runtime.Caller, 2 - outer_most itself
    return runtime.FuncForPC(pc[0])!=runtime.FuncForPC(pc[1]) // test if the caller of the caller is the same func, otherwise it is the outermost
}

func fact(n int) int {
   if n == 0 {
      return 1
   }
   fact := n * fact(n-1)
   if outer_most() {
       fmt.Printf(strconv.Itoa(n))
   }
   return fact 
}

func main() {
  fact(4)
}

खेल का मैदान: https://play.golang.org/p/ro1ZOn6yIR7 यह कोई अच्छा अभ्यास नहीं है, लेकिन प्रश्न को सबसे सीधे तरीके से हल करें।

नोट: वैश्विक चर का उपयोग करने से गड़बड़ियां होने की बहुत संभावना है। जब भी आप func को कॉल करते हैं, तो आपको इसे हर बार सेट करने की आवश्यकता होती है, और यदि समरूपता है, तो डेटा दौड़ शामिल होगी।

और यदि आप इस तथ्य से असहज हैं कि अतिरिक्त बूल तर्क प्रत्येक रिकर्सिव कॉल आवंटित किया जाता है (जो अनगिनत बार हो सकता है), तो आप @Adrian के उत्तर को देख सकते हैं या इसे बूल की विधि के रूप में लपेट सकते हैं।

1
leaf bebop 27 पद 2017, 20:59

आप एक depth जैसा कुछ पास कर सकते हैं जो प्रत्येक कॉल पर बढ़ता जाता है। जैसे:

func fact(depth int, n int) int {
   if n == 0 {
      return 1
   }
   fact := n * fact(depth + 1, n-1)
   if depth == 0 {
       fmt.Println(fact)  // I assume you meant to print fact here.
   }
   return fact 
}
func main() {
  fact(0, 4)
}

यदि यह वास्तव में आपका उपयोग मामला है, तो आप ऐसा करने से काफी बेहतर हैं:

func fact(n int) int {
  if n == 0 {
     return 1
  }
  return n * fact(n-1)
}
func main() {
  fmt.Println(fact(4))
}
1
Marc 27 पद 2017, 13:49

संपादित प्रश्न का उत्तर:

आप नीचे दिए गए दूसरे पैटर्न का फिर से उपयोग कर सकते हैं:

func fact(n int, outerMost bool) int {
   if n == 0 {
      return 1
   }
   fact := n * fact(n-1, false)
   if outerMost {
       fmt.Printf(strconv.Itoa(n))
   }
   return fact 
}

func main() {
    fact(4, true)
}

फिर से, आप इसे साफ करने के लिए क्लोजर या हेल्पर फ़ंक्शंस का उपयोग कर सकते हैं।

मूल उत्तर:

वैश्विक चर का उपयोग करने का प्रयास करें:

var outerMost bool = true

func fact(n int) int {
    if outerMost {
        fmt.Printf(strconv.Itoa(n))
        outerMost = false
    }
    if n == 0 {
       return 1
    }
    return n * fact(n-1)
}

func main() {
    fact(4)
}

इसे हासिल करने के और भी तरीके हैं। उदाहरण के लिए, आप क्लोजर के साथ भी इसी तरह की तकनीक का उपयोग कर सकते हैं। या fact में एक और पैरामीटर जोड़ें:

func fact(n int, outerMost bool) int {
    if outerMost {
        fmt.Printf(strconv.Itoa(n))
        outerMost = false
    }
    if n == 0 {
       return 1
    }
    return n * fact(n-1, outerMost)
}

func main() {
    fact(4, true)
}
1
abhink 27 पद 2017, 13:53

एक साधारण अनाम फ़ंक्शन शायद सबसे साफ है, क्योंकि यह एक पैरामीटर नहीं जोड़ता है, बाहरी कॉलर्स के लिए एपीआई को केवल आंतरिक तर्क को लागू करने के लिए जटिल करता है।

func fact(n int) int {
    var facto func(n int) int
    facto = func(n int) int {
        if n == 0 {
            return 1
        }
        fact := n * facto(n-1)
        return fact
    }
    n = facto(n)
    fmt.Printf("%d", n)
    return n
}

यह समान कार्यक्षमता प्राप्त करता है, लेकिन कॉलर को अतिरिक्त बूल या int मान पास करने के बारे में जानने की आवश्यकता नहीं है जो इसके लिए अप्रासंगिक है। यहां पूरा उदाहरण: https://play.golang.org/p/7vHwPDN2_FL

1
Adrian 27 पद 2017, 17:14