स्विफ्ट में स्थिर समारोह चर


96

मैं यह पता लगाने की कोशिश कर रहा हूं कि स्विफ्ट में एक फ़ंक्शन के लिए केवल स्थानीय रूप से स्कोप किए गए एक स्थिर चर को कैसे घोषित किया जाए।

सी में, यह कुछ इस तरह दिख सकता है:

int foo() {
    static int timesCalled = 0;
    ++timesCalled;
    return timesCalled;
}

उद्देश्य-सी में, यह मूल रूप से समान है:

- (NSInteger)foo {
    static NSInteger timesCalled = 0;
    ++timesCalled;
    return timesCalled;
}

लेकिन मैं स्विफ्ट में ऐसा कुछ नहीं कर सकता। मैंने निम्नलिखित तरीकों से चर घोषित करने की कोशिश की है:

static var timesCalledA = 0
var static timesCalledB = 0
var timesCalledC: static Int = 0
var timesCalledD: Int static = 0

लेकिन इन सभी के परिणामस्वरूप त्रुटियां होती हैं।

  • पहली शिकायत "स्थैतिक गुणों को केवल एक प्रकार पर घोषित किया जा सकता है"।
  • दूसरा "अपेक्षित घोषणा" (जहाँ staticहै) और "अपेक्षित प्रतिमान" (जहाँ timesCalledBहै) की शिकायत करता है
  • तीसरे ने शिकायत की "एक लाइन पर लगातार बयानों को 'द्वारा अलग किया जाना चाहिए?" "(बृहदान्त्र के बीच की जगह में static) और" अपेक्षित प्रकार "(जहां staticहै)
  • चौथी शिकायत "लाइन से अलग किया जाना चाहिए पर लगातार बयान ';' '(के बीच की जगह में Intऔर static) और" उम्मीद की घोषणा "(के तहत बराबर चिह्न)

जवाबों:


158

मुझे नहीं लगता कि स्विफ्ट स्टैटिक वैरिएबल को बिना किसी क्लास / स्ट्रक्चर से जुड़े हुए सपोर्ट करता है। स्थिर चर के साथ एक निजी संरचना घोषित करने का प्रयास करें।

func foo() -> Int {
    struct Holder {
        static var timesCalled = 0
    }
    Holder.timesCalled += 1
    return Holder.timesCalled
}

  7> foo()
$R0: Int = 1
  8> foo()
$R1: Int = 2
  9> foo()
$R2: Int = 3

हाँ, मैंने थोड़ा सा खेलना जारी रखा और यह मूल रूप से वास्तव में क्लूनी वाला समाधान था, जिसके साथ मैं आया था।
nhgrif

17
अपडॉट किया गया, लेकिन मैं दुखी हूं हमें इसका सहारा लेना होगा।
Tricertops

1
टाइप गुण और विधियाँ एक प्रकार की होती हैं (यानी एक क्लास, स्ट्रक्चर या एनम) और अकेले किसी फंक्शन से संबंधित नहीं हो सकती हैं। प्रकार के गुणों पर Apple प्रलेखन । @Tricertops। इसके बारे में जाने का एक और तरीका यह होगा कि आप किसी क्लास में फंक्शन "फू" डाल दें, उस क्लास के लिए एक टाइप प्रॉपर्टी बनाएं और उसे फंक्शन के अंदर इस्तेमाल करें।
NSCoder

6
@NSCoder लेकिन struct Holder {…}कई कार्यों के अंदर घोषित करना संभव है और वे टकराएंगे नहीं। स्विफ्ट static letइस structबायलरप्लेट के बिना समर्थन कर सकता है ।
Tricertops

1
@ मुझे खेद है, लेकिन मुझे और अपडेट किए गए अन्य उत्तर नहीं मिल रहे हैं?
ब्रायन चेन

23

एक और समाधान

func makeIncrementerClosure() -> () -> Int {
    var timesCalled = 0
    func incrementer() -> Int {
        timesCalled += 1
        return timesCalled
    }
    return incrementer
}

let foo = makeIncrementerClosure()
foo()  // returns 1
foo()  // returns 2

3
यह एक विशिष्ट जावास्क्रिप्ट तरीका है
ब्रायन चेन

1
लेकिन अगर मैं बा () को फिर से कॉल करता हूं, तो आंतरिक फ़ंक्शन पहले कॉल पर 1 लौटता है। यह एक स्थिर चर से अलग है।
ngrgrif

2
यह यहां Apple के डॉक्स में भी पढ़ाया गया है: developer.apple.com/library/ios/documentation/Swift/Conceptual/… यह "कार्यात्मक प्रोग्रामिंग" के साथ लाइनों में रखने के लिए सबसे अच्छा समाधान प्रतीत होता है, लेकिन इसके अलावा कुछ अन्य भी हैं कुंआ। हालांकि यह स्वीकृत उत्तर होना चाहिए।
datWooWoo

1
मुझे क्षमा करें, लेकिन यह एक ही समस्या के लिए अधिक जटिलता को जोड़ने वाला एक बदसूरत हैक है। अापका नजरिया क्या है? उस मामले में मैं एक साधारण वर्ग की संपत्ति पसंद करता हूं। @ ब्रायन चेन का जवाब निकटतम निकटतम है जिसे आप प्राप्त कर सकते हैं। मैं एक फ्लिपफ्लॉप तरह के समाधान के लिए उनके जवाब का उपयोग करता हूं। डैनियल शायद स्विफ्ट प्रोग्रामिंग के एप्पल के सबसे अच्छे अनुरूप नियम हैं।
अंडालुज

1
मुझे यह समाधान विशेष रूप से पसंद आया। किसी फ़ंक्शन के दायरे के अंदर स्थिर चर के समान परिणाम प्राप्त करने के लिए उच्च-क्रम फ़ंक्शन का उपयोग करने का यह एक आदर्श उदाहरण है। स्टेटिक फंक्शन वर्जन अच्छे कारणों से स्विफ्ट में मूल रूप से समर्थित नहीं हैं। यह प्रोग्रामिंग का स्वाभाविक विकास है। पुराने फैशन तरीकों से कोड करने की कोशिश करने के लिए हैक की आवश्यकता होती है। मेरी राय में, चर कैप्चरिंग का उपयोग करने के लिए विरोध के रूप में एक अतिरिक्त नेस्टेड डेटा प्रकार जोड़ने से कोड पठनीयता कम हो जाती है।
१२:०६ पर nstein

18

Xcode 6.3 के साथ स्विफ्ट 1.2 अब उम्मीद के मुताबिक स्टैटिक का समर्थन करता है। Xcode 6.3 बीटा रिलीज़ नोट्स से:

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

ऐसा प्रतीत होता है कि कार्यों में स्थिर घोषणाएँ नहीं हो सकती हैं (जैसा कि प्रश्न में पूछा गया है)। इसके बजाय, घोषणा कक्षा स्तर पर की जानी चाहिए।

एक वर्ग (उर्फ स्टेटिक) फ़ंक्शन के अंदर बढ़ी हुई स्थिर संपत्ति दिखाने वाला सरल उदाहरण, हालांकि एक क्लास फ़ंक्शन की आवश्यकता नहीं है:

class StaticThing
{
    static var timesCalled = 0

    class func doSomething()
    {
        timesCalled++

        println(timesCalled)
    }
}

StaticThing.doSomething()
StaticThing.doSomething()
StaticThing.doSomething()

आउटपुट:

1
2
3

1
मुझे संदेह है कि यह अंतर staticएप्पल के हिस्से पर जानबूझकर हो सकता है, हालांकि एक बदलाव का अनुरोध करने के लिए बग दर्ज करने का हमेशा स्वागत है । सी में, एक चर को स्टोरेज से सोर्स-फाइल स्कोप तक staticसीमित कर दिया जाता है (जो कि हमेशा क्लास स्कोप के समान नहीं होता है), जबकि वेरिएबल डिक्लेरेशन का प्लेसमेंट लेक्सिकल स्कोप निर्धारित करता है (यानी ग्लोबल वर्सेस फंक्शन बनाम कई नेस्टेड- s)। स्विफ्ट में, स्टोरेज स्कोप हमेशा लेक्सिकल स्कोप का अनुसरण करता है, इसलिए आपके पास एक वैरिएबल नहीं हो सकता है जो किसी फ़ंक्शन के लिए लेक्सिकल हो और जिसमें ग्लोबल स्टोरेज हो। {}
21

5
डैनियल, यह वास्तव में सूक्ष्मता से (लेकिन महत्वपूर्ण रूप से) सवाल पूछने वाले से अलग है। मैं हालांकि उत्तर की सराहना करता हूं। @rickster मैं समझता हूं कि आप क्या कह रहे हैं और सोचते हैं कि आपकी टिप्पणी इस प्रश्न के अच्छे उत्तर के लिए विस्तारित हो सकती है।
nhgrif

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

सीआई में @rickster लगता है कि स्थैतिक हमेशा विश्व स्तर पर संग्रहीत होता है। हालांकि मुझे यकीन नहीं है। मुझे लगता है कि Apple यहाँ समस्या को हल करने की कोशिश कर रहा है। तेजी से, यह अब हमेशा शाब्दिक है और भंडारण वर्ग के लिए स्कोप
BTRUE

@nhgrif ने अपनी पिछली टिप्पणी के साथ, मुझे लगता है कि डैनियल का जवाब वास्तव में स्वीकृत उत्तर होना चाहिए, क्योंकि यद्यपि आप objc में किसी फ़ंक्शन में एक स्थैतिक संस्करण की घोषणा कर सकते हैं, यह वहां स्कोप नहीं किया गया था, एक स्थिर प्रकार का उपयोग करने के समान प्रभाव प्रॉपर्टी स्विफ्ट में। एकमात्र अंतर यह है कि, स्विफ्ट डिक्लेरेशन पॉइंट बहुत अधिक वर्णनात्मक है और यह भ्रामक नहीं है कि चर का दायरा क्या है।
BTRUE

0

एक और समाधान

class Myclass {
    static var timesCalled = 0
    func foo() -> Int {
        Myclass.timesCalled += 1
        return Myclass.timesCalled
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.