2009-11-11 15 views
13

मुझे लगता है कि डी static if एक दिलचस्प भाषा सुविधा है। यह मेरे प्रश्न को संकेत देता है: क्या संकलित भाषाओं के अन्य उदाहरण हैं जिनमें संकलक के पास कोड की मजबूत धारणा है और उन तक पहुंचने के लिए भाषा सुविधाएं हैं?क्या स्थिर के साथ डी के अलावा अन्य भाषाएं हैं?

उदाहरण के लिए, इस कोड को अजगर से repr को कुछ इसी तरह प्रदान करता है: है

char[] repr(T)(T value) { 
    static if (is(typeof(value.__repr__))) { // class T provides a "repr()" method 
    return value.__repr__(); 
    } else static if (is(T:string)) { 
    return `"` ~ value ~ `"`; 
    // ...other cases... 
    } else { 
    return toString(value); 
    } 
} 

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

कैवेट: उस अंतिम पैराग्राफ में राय थी, लेकिन मेरा मतलब सिर्फ मेरे प्रश्न के लिए कुछ प्रेरणा और स्पष्टीकरण प्रदान करना है, विवाद को पूरा नहीं करना। मैं सिर्फ यह जानना चाहता हूं कि क्या किसी अन्य संकलित भाषाओं में ऐसी विशेषताएं हैं।

+1

कई सी और सी ++ कंपाइलर्स अप्रयुक्त कोड को हटा देंगे यदि 'if' में अभिव्यक्ति संकलन समय पर निर्धारित की जा सकती है। सुनिश्चित नहीं है कि यह आपके प्रश्न का पूरी तरह उत्तर देता है। –

+0

नहीं - उपर्युक्त उदाहरण संकलित नहीं होगा क्योंकि स्थैतिक के कुछ ब्लॉक में कोड मान्य नहीं होगा। जैसे यदि टी टाइप int int थे, तो मान .__ repr __() एक संकलित त्रुटि होगी। – Grumdrig

+1

आपको उपरोक्त के लिए संकलित करने के लिए "स्थैतिक अगर (है (टाइप (मूल्य .__ repr__)))" को स्थिर करने की आवश्यकता है। या "स्थैतिक अगर (__ लक्षण (संकलन, मूल्य .__ repr__))"। – Baxissimo

उत्तर

10

वास्तविक मैक्रोज़ वाली किसी भी भाषा में स्थैतिक रूप का एक रूप है। उदाहरण के लिए लिस्प और Nemerle आपको उस कोड का निर्माण करने दें जो एक मैक्रो प्रोग्रामिंग संरचनाओं जैसे 'if' और for-loops का उपयोग करने के लिए विस्तारित करता है। वे अनिवार्य रूप से संकलित समय के निर्णय हैं और आपको स्थिर के समान कुछ करने देते हैं। नेमेरल मैक्रोज़ के मामले में संकलक के लिए मूल रूप से प्लग-इन होते हैं जिन्हें संकलन-समय पर निष्पादित किया जाता है।

सी ++ में boost MPL लाइब्रेरी है जिसमें kind of static if है जिसका उपयोग दो प्रकार के बीच चयन करने के लिए किया जा सकता है। आप कुछ कोड को रन() सदस्य में दो प्रकार के अंदर डाल सकते हैं और कुछ समान समान प्राप्त कर सकते हैं, लेकिन बहुत बोझिल वाक्यविन्यास के साथ।

struct float_impl { 
    static void run() { /* float case code */ } 
} 
struct int_impl { 
    static void run() { /* int case code */ } 
} 

typedef typename if_< 
      is_same<T, float> 
     , float_impl 
     , int_impl 
     >::type impl_t; 
impl_t::run(); 

डी में होगी:

बूस्ट एमपीएल के साथ उदाहरण के लिए आप कुछ इस तरह कर सकता है

static if(is(T == float)) { 
    /* float code */ 
} 
else { 
    /* int code */ 
} 
+0

सुंदर। नेमेर मेरे लिए नया है और बहुत रोचक है। इसे तलाशने के लिए तत्पर हैं। लिस्प मैक्रोज़ मुझे सोचना चाहिए था। – Grumdrig

2

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

यहां एक उदाहरण है जिसे मैंने कई वर्षों पहले CLLIB लाइब्रेरी (CLOCC लाइब्रेरी का हिस्सा) से अनुकूलित किया है। लक्ष्य उन कार्यों को प्रदान करना है जो किसी अन्य स्ट्रिंग के साथ किसी अन्य स्ट्रिंग के उपसर्ग स्ट्रिंग को काट लेंगे। उपसर्ग मैक्रोएक्सप्शन समय पर ज्ञात हो सकता है या ऐसा नहीं हो सकता है। यदि ऐसा है, तो हम एक अनुकूलन कर सकते हैं: उपसर्ग की लंबाई पहले गणना करें और इसे एक शाब्दिक के रूप में एम्बेड करें, ताकि यह प्रत्येक कॉल पर जेनरेट किए गए फ़ंक्शन पर पुन: संकलित न हो। मैक्रो पहले पर चुनौतीपूर्ण है, लेकिन वास्तविक जेनरेट कोड छोटा है।

(defmacro after-prefix-core (comparison-op prefix string &optional length) 
    "Similar to cllib:string-beg-with-cs." 
    (flet ((chop (prefix prefix-length string string-length) 
      `(when (and (>= ,string-length ,prefix-length) 
         (,comparison-op ,prefix ,string :end2 ,prefix-length)) 
       (subseq ,string ,prefix-length ,string-length)))) 
    (let* ((gstring (gensym "STRING-")) 
      (gstring-length (gensym "STRING-LENGTH-"))) 
     `(let* ((,gstring ,string) 
       (,gstring-length ,(or length `(length ,gstring)))) 
     ,(if (stringp prefix) 
       ;; Constant -- length known at expansion time. 
       (let ((prefix-length (length prefix))) 
       (chop prefix prefix-length gstring gstring-length)) 
       ;; Other form -- length not known at expansion time. 
       (let ((gprefix (gensym "PREFIX-")) 
        (gprefix-length (gensym "PREFIX-LENGTH-"))) 
       `(let* ((,gprefix ,prefix) 
         (,gprefix-length (length ,gprefix))) 
        ,(chop gprefix gprefix-length gstring gstring-length)))))))) 


(defmacro after-prefix (prefix string &optional length) 
    "Similar to cllib:string-beg-with." 
    `(after-prefix-core string-equal ,prefix ,string ,length)) 


(defmacro after-prefix-cs (prefix string &optional length) 
    "Similar to cllib:string-beg-with-cs." 
    `(after-prefix-core string= ,prefix ,string ,length)) 

रूप

(if (stringp prefix) 
बीच में

देखते हैं? यह macroexpansion समय पर पहला तर्क का निरीक्षण कर रहा है और इस पर निर्भर करता है कि तर्क एक शाब्दिक या प्रतीक है, इसका प्रकार ज्ञात हो सकता है या नहीं।यदि प्रकार एक प्रतीक है, तो हम मानते हैं कि हमें किसी अन्य मूल्य पर इंगित करने वाले चर के रूप में पुनर्विचार करने के लिए रन टाइम तक प्रतीक्षा करनी चाहिए।

(LET* ((#:STRING-5340 BAR) (#:STRING-LENGTH-5341 (LENGTH #:STRING-5340))) 
    (LET* ((#:PREFIX-5342 FOO) (#:PREFIX-LENGTH-5343 (LENGTH #:PREFIX-5342))) 
    (WHEN 
     (AND (>= #:STRING-LENGTH-5341 #:PREFIX-LENGTH-5343) 
      (STRING-EQUAL #:PREFIX-5342 #:STRING-5340 :END2 #:PREFIX-LENGTH-5343)) 
     (SUBSEQ #:STRING-5340 #:PREFIX-LENGTH-5343 #:STRING-LENGTH-5341)))) 

ध्यान दें कि चर #:PREFIX-LENGTH-5343FOO कीगणना लंबाई, चर #:PREFIX-5342 करने के लिए यहाँ बाध्य करने के लिए बाध्य किया जाता है:

यहाँ प्रपत्र (after-prefix foo bar) के लिए विस्तार है।

अब प्रपत्र (after-prefix "foo" bar), जहां उपसर्ग अब एक स्ट्रिंग शाब्दिक है के लिए विस्तार को देखो:

(LET* ((#:STRING-5463 BAR) (#:STRING-LENGTH-5464 (LENGTH #:STRING-5463))) 
    (WHEN (AND (>= #:STRING-LENGTH-5464 3) (STRING-EQUAL "foo" #:STRING-5463 :END2 3)) 
    (SUBSEQ #:STRING-5463 3 #:STRING-LENGTH-5464))) 

अब वहाँ कोई कंप्यूटिंग "foo" की लंबाई है; यह 3.

यह इस उदाहरण में बहुत अधिक काम की तरह प्रतीत हो सकता है, लेकिन ऐसी चीजों को करने में सक्षम होने के लिए एक अच्छी शक्ति है, जैसा कि आपका प्रश्न प्रदर्शित होता है।

2

static_if सी ++ (सी ++ 1y) के अगले संस्करण के लिए प्रस्तावित किया गया है। यह मूल रूप से सी ++ 11 के लिए प्रस्तावित किया गया था लेकिन जाहिर तौर पर देरी हुई थी।

प्रस्ताव here देखें। दिलचस्प बात यह है कि लेखकों में से एक वाल्टर ब्राइट है, डी

के निर्माता भी it's possible to fake static-if in current C++ using compiler hacks

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

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