2014-04-14 13 views
6

मूल रूप से, वहाँ इस सवाल का दो भागों हैं:क्या जंग मैक्रोज़ का उपयोग कर प्रक्रियाओं को घोषित करना संभव है?

  1. आप Rust में किसी मैक्रो को एक अज्ञात पहचानकर्ता पारित कर सकते हैं?

  2. क्या आप जंग मैक्रो में नए चर नामों को उत्पन्न करने के लिए तारों को जोड़ सकते हैं? !

उदाहरण के लिए, कुछ की तरह:

macro_rules! expand(
    ($x:ident) => (
    let mut x_$x = 0; 
) 
) 

कॉलिंग का विस्तार (hi) स्पष्ट विफल रहता है क्योंकि हाय एक अज्ञात पहचानकर्ता होता है लेकिन क्या आप इसे किसी भी तरह से कर सकते हैं?

यानी। कुछ की तरह सी में समतुल्य:

#include <stdio.h> 
#define FN(Name, base) \ 
    int x1_##Name = 0 + base; \ 
    int x2_##Name = 2 + base; \ 
    int x3_##Name = 4 + base; \ 
    int x4_##Name = 8 + base; \ 
    int x5_##Name = 16 + base; 

int main() { 
    FN(hello, 10) 
    printf("%d %d %d %d %d\n", x1_hello, x2_hello, x3_hello, x4_hello, x5_hello); 
    return 0; 
} 

आप क्यों कहते हैं, क्या एक भयानक विचार है। आप कभी ऐसा क्यों करना चाहते हैं?

मुझे खुशी है कि आपने पूछा!

इस जंग ब्लॉक पर विचार करें:

{ 
    let marker = 0; 
    let borrowed = borrow_with_block_lifetime(data, &marker); 
    unsafe { 
     perform_ffi_call(borrowed); 
    } 
} 

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

उपयोग मैक्रो इस उद्देश्य के काफी मुसीबतों मैं संकलक के साथ लड़ रहे है कम होगा के लिए अस्थायी चर घोषणा कर सकते हैं (यह भी Why are all my pointers pointing to the same place with to_c_str() in rust? देखें)

। यही कारण है कि मैं यह करना चाहता हूँ।

#![feature(concat_idents)] 

macro_rules! test { 
    ($x:ident) => ({ 
     let z = concat_idents!(hello_, $x); 
     z(); 
    }) 
} 

fn hello_world() { } 

fn main() { 
    test!(world); 
} 

हालांकि, जहां तक ​​मुझे पता है क्योंकि concat_idents!() अपने आप में एक मैक्रो है:

उत्तर

9

हाँ, आप मनमाने ढंग से पहचानकर्ता एक मैक्रो में एक नया पहचानकर्ता में concat_idents!() मैक्रो का उपयोग पारित कर सकते हैं और पहचानकर्ता हाँ, आप जोड़ सकते हैं , आप इस समेकित पहचानकर्ता को हर जगह का उपयोग नहीं कर सकते हैं, आप केवल उदाहरण के लिए कुछ निश्चित स्थानों में सादे पहचानकर्ता का उपयोग कर सकते हैं, और यह मेरी राय में, एक बड़ी कमी है। कल कल मैंने एक मैक्रो लिखने की कोशिश की जो मेरे कोड में बहुत सारे बॉयलरप्लेट को हटा सकता था, लेकिन आखिर में मैं ऐसा करने में सक्षम नहीं था क्योंकि मैक्रोज़ समेकित पहचानकर्ताओं के मनमाने ढंग से प्लेसमेंट का समर्थन नहीं करता है।

बीटीडब्ल्यू, अगर मैं आपके विचार को सही ढंग से समझता हूं, तो आपको अद्वितीय नाम प्राप्त करने के लिए वास्तव में समेकित पहचानकर्ताओं की आवश्यकता नहीं होती है। जंग मैक्रोज़, सी के विपरीत, hygienic हैं। इसका मतलब यह है कि एक मैक्रो के अंदर पेश किए गए स्थानीय चर के सभी नाम इस मैक्रो कहलाए जाने वाले दायरे में रिसाव नहीं करेंगे। उदाहरण के लिए, आप यह मान सकता है कि इस कोड काम करेगा:

macro_rules! test { 
    ($body:expr) => ({ let x = 10; $body }) 
} 

fn main() { 
    let y = test!(x + 10); 
    println!("{}", y); 
} 

है यही कारण है कि, हम एक चर x बना सकते हैं और इसकी घोषणा के बाद एक अभिव्यक्ति डाल दिया।ऐसा नहीं है कि test!(x + 10) में x कि चर मैक्रो द्वारा घोषित को संदर्भित करता है सोचने के लिए तो स्वाभाविक है, और सब कुछ ठीक हो जाना चाहिए, लेकिन वास्तव में इस कोड संकलन नहीं होगा:

main3.rs:8:19: 8:20 error: unresolved name `x`. 
main3.rs:8  let y = test!(x + 10); 
          ^
main3.rs:3:1: 5:2 note: in expansion of test! 
main3.rs:8:13: 8:27 note: expansion site 
error: aborting due to previous error 

तो आप सभी की जरूरत की विशिष्टता है अगर स्थानीय, तो आप सुरक्षित रूप से कुछ भी नहीं कर सकते हैं और अपने इच्छित नामों का उपयोग कर सकते हैं, वे स्वचालित रूप से अद्वितीय होंगे। मैक्रो ट्यूटोरियल में यह explained है, हालांकि मुझे कुछ हद तक भ्रमित करने का उदाहरण मिलता है।

+1

concat_idents मुझे हटा सकता है, यह पहले से ही फीचर-गेटेड [# 13295] (https://github.com/mozilla/rust/pull/13295) और [# 13294] (https://github.com/mozilla)/जंग/मुद्दे/13294) – Arjan

+0

हमें वास्तव में सी ## के समान इस सुविधा की आवश्यकता है। मुझे लगातार मैक्रोज़ लिखना पड़ता है जहां उपयोगकर्ता मुझे दो नाम देते हैं क्योंकि स्ट्रिंग कॉन्सैट इतनी सीमित है। –

1

ऐसे मामलों में जहां concat_idents काम नहीं करता है (जो कि ज्यादातर मामलों में मैं इसका उपयोग करना चाहता हूं) नामस्थानों का उपयोग करने के लिए समेकित पहचानकर्ताओं की समस्या को बदलना काम करता है।

है यही कारण है कि, गैर काम कर कोड के बजाय:

macro_rules! test { 
    ($x:ident) => ({ 
     struct concat_idents!(hello_, $x) {} 
     enum contact_idents!(hello_, $x) {} 
    }) 
} 

उपयोगकर्ता नाम स्थान नाम कर सकते हैं, और उसके बाद पूर्व निर्धारित नाम है जिन्हें आप नीचे देख:

macro_rules! test { 
    ($x:ident) => ({ 
     mod $x { 
      struct HelloStruct {} 
      enum HelloEnum {} 
     } 
    }) 
} 

अब आप एक नाम है मैक्रो के तर्क के आधार पर। यह तकनीक विशिष्ट मामलों में केवल सहायक है।

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

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