2012-11-11 8 views
6

मैं एक आरईएसटी वेब सेवा में एक रैपर लिख रहा हूं और मैं दृढ़ता से स्कैला एपीआई टाइप करना चाहता हूं।क्या स्कैला में नाम और पैरामीटर के मानों के साथ एक मानचित्र [स्ट्रिंग, कोई भी] होना संभव है?

निम्नलिखित मैं अब तक क्या कर रहा हूँ है:

def getMentions(count: Option[Int] = None, 
       sinceID: Option[TweetID] = None, 
       maxID: Option[TweetID] = None, 
       trimUser: Option[Boolean] = None, 
       contributorDetails: Option[Boolean] = None, 
       includeEntities: Option[Boolean] = None) : List[Tweet] = { 
val parameters = Map("count" -> count, 
        "since_id" -> sinceID, 
        "max_id" -> maxID, 
        "trim_user" -> trimUser, 
        "contributor_details" -> contributorDetails, 
        "include_entities" -> includeEntities) 
/* 
* Convert parameters, which is a Map[String,Any] to a Map[String,String] 
* (Removing Nones) and pass it to an object in charge of generating the request. 
*/ 
... 
} 

यह दृष्टिकोण काम कर रहा है, लेकिन यह मुझे की जरुरत होती है parameters नक्शा उत्पन्न करने के लिए। यदि मैं मानचित्र का प्रतिनिधित्व करने वाले पैरामीटर और उनके मूल्यों तक पहुंचने में सक्षम था, तो मैं जो कर रहा हूं वह बहुत साफ होगा।

उत्तर

11

आप रनटाइम प्रतिबिंब के साथ ऐसा कर सकते हैं, और मुझे यकीन है कि आपको जवाब मिलेंगे कि अगर आप इसे चाहते हैं, लेकिन यह वास्तव में Scala 2.10's macros के लिए एक साफ उपयोग केस है, तो यहां जाता है। सबसे पहले यह मान हम ParamMapMaker.scala नाम की एक फ़ाइल है:

object ParamMapMaker { 
    def paramMap: Map[String, Any] = macro paramMapImpl 

    def paramMapImpl(c: scala.reflect.macros.Context) = { 
    import c.universe._ 

    val params = c.enclosingMethod match { 
     case DefDef(_, _, _, ps :: Nil, _, _) => 
     ps.map(p => 
      reify((
      c.Expr[String](Literal(Constant(p.name.decoded))).splice, 
      c.Expr[Any](Ident(p.symbol)).splice 
     )).tree 
     ) 
     case _ => c.abort(c.enclosingPosition, "Can't call paramMap here!") 
    } 

    c.Expr[Map[String, Any]](Apply(Select(Ident("Map"), "apply"), params)) 
    } 
} 

मैं पाठक के लिए एक (आसान) व्यायाम के रूप में नक्शे कुंजी आवरण साँप छोड़ देंगे।

object Test extends App { 
    def foo(hello: String, answer: Int) = ParamMapMaker.paramMap 

    println(foo("world", 42)) 
} 

अब हम इन दोनों के संकलन:

scalac -language:experimental.macros ParamMapMaker.scala 
scalac Test.scala 

और जब हम Test चलाने हम निम्नलिखित मिलेगा:

हम यह भी एक परीक्षण फ़ाइल (Test.scala नाम पर आधारित)

Map(hello -> world, answer -> 42) 

इस बारे में निफ्टी बात यह है कि आर के ऊपर कोई भी नहीं है अनटाइम प्रतिबिंब। हम -Ymacro-debug-verbose साथ परीक्षण फ़ाइल संकलन करते हैं, तो हम देखते हैं कि निम्नलिखित कोड संकलन समय पर तैयार की गई है (प्रभाव में) foo के शरीर के लिए:

Map.apply[String, Any](
    scala.Tuple2.apply[String, String]("hello", hello), 
    scala.Tuple2.apply[String, Int]("answer", answer) 
) 

वास्तव में हम उम्मीद थी के रूप में।

+1

क्या आप जानते हैं कि एसबीटी के साथ इसका उपयोग करना संभव है? – mariosangiorgio

+3

मैंने इसे समझ लिया। इसे केवल स्काला संस्करण 'स्कैलावर्सन: = "2.10.0-आरसी 2" 'को बदलने की आवश्यकता है और सुविधा का उपयोग कर फाइलों में' आयात भाषा .experimental.macros' आयात करने की आवश्यकता है। – mariosangiorgio

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

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