2017-02-04 3 views
5

का उपयोग किये बिना (स्ट्रिंग * ओबीजे) की एक सूची कैसे लिखें, मेरा लक्ष्य डीएसएल में नाम/मूल्य जोड़े की सूची लिखना और इसे पढ़ने योग्य बनाना है। यहां मान int, float, string या इनमें से किसी भी प्रकार की सूची हो सकते हैं।अपस्टास्ट

मैं string * obj जोड़े का उपयोग कर रहा हूं और उन्हें (string * obj) list पर ले जाने वाले फ़ंक्शन में भेज रहा हूं।

obj पैरामीटर को उपेक्षित किए बिना सूची लिखने के लिए क्या है?

let myfun (values:(string*obj) list) = 
    // Do something... 

// This is pretty ugly 
myfun ["Name", upcast "Freddie"; "Age", upcast 50] 

// This would be the ideal 
myfun ["Name", "Freddie"; "Age", 50] 

उत्तर

8

प्रोग्रामिंग 101: यदि आप इसे पैकेज पुन: उपयोग के लिए अपने आप को अधिक से अधिक एक ही बात दोहरा पाते हैं, यह एक समारोह बनाते हैं। आपके मामले में, समारोह होगा जेनेरिक (अर्थात किसी भी प्रकार की पैरामीटर लेने के लिए) और पैरामीटर पर Upcast कार्य करें:

let pair name value = name, value :> obj 
myfun [pair "Name" "Freddie"; pair "Age" 50] 

हम्म ... ज्यादा अच्छे, यह क्या है? लेकिन रुको, हम अभी तक नहीं कर रहे हैं! अब जब आपके पास यह फ़ंक्शन है, तो आप इसे एक अच्छा नाम दे सकते हैं, जो इसे अच्छी तरह से कॉल कर देगा। कहो, ==>:

let (==>) name value = name, value :> obj 
myfun ["Name" ==> "Freddie"; "Age" ==> 50] 

संभव प्रकार के अपने सेट पहले से जाना जाता है और अपेक्षाकृत छोटे हैं (के रूप में अपने प्रश्न में इंगित करता है), तो आप एक कदम और आगे जाने के लिए और संकलक जाँच लें कि केवल अनुमति दी प्रकार उपयोग किया जाता है हो सकता है । ऐसा करने के लिए, आप विधि भार के, स्थिर का समाधान प्रकार की कमी और कुछ वाक्यात्मक प्रवंचना का उपयोग करना होगा:

type Casters() = 
    static member cast (v: string) = v :> obj 
    static member cast (v: float) = v :> obj 
    static member cast (v: int) = v :> obj 
    static member cast (v: string list) = v :> obj 
    static member cast (v: float list) = v :> obj 
    static member cast (v: int list) = v :> obj 

let inline cast (casters: ^c) (value: ^t) = 
    ((^c or ^t) : (static member cast : ^t -> obj) value) 

let inline (==>) name value = name, (cast (Casters()) value) 

["Name" ==> "Freddie"; "Age" ==> 50] // OK 
["What?" ==> true] // Error: "bool" is not an allowed type 
+0

धन्यवाद, लेकिन अपने _pair_ समारोह मुझे प्रकार से _The स्थिर बलात्कार देता है' 'करने के लिए ख एक इस कार्यक्रम point_ करने से पहले जानकारी के आधार पर एक अनिश्चित प्रकार शामिल है। क्या आप एक ही त्रुटि नहीं देख रहे हैं? [tryfsharp] (http://www.tryfsharp.org/create/seankearon/file3.fsx) –

+2

एक गलती। मैंने वास्तविक प्रकार के साथ उचित अपस्टास्ट ऑपरेटर की बजाय अपना 'अपकास्ट' कॉपी किया। इसे अभी सुधार लिया। –

+0

यह बहुत अच्छा है, धन्यवाद! –

2

आपका कहना है कि अपने मूल्यों केवल सूचीबद्ध प्रकार के हो सकते हैं। मुझे आश्चर्य है कि क्या आपके पास भेदभाव वाले संघ के बजाय obj का उपयोग करने का कोई विशेष कारण है, जो इस कार्य के लिए पूरी तरह उपयुक्त है?

मैं obj के बजाय एक ड्यू प्रकार का उपयोग करने फ्योदोर के जवाब संशोधित कर लिया है:

type Value = 
    | Int  of int  | Float  of float  | String  of string 
    | IntList of int list | FloatList of float list | StringList of string list 

type Casters() = 
    static member cast v = Int v 
    static member cast v = Float v 
    static member cast v = String v 
    static member cast v = IntList v 
    static member cast v = FloatList v 
    static member cast v = StringList v 

let inline cast (casters: ^c) (value: ^t) = 
    ((^c or ^t) : (static member cast : ^t -> Value) value) 

let inline (==>) name value = name, (cast (Casters()) value) 

["Name" ==> "Freddie"; "Age" ==> 50] // OK 
["What?" ==> true] // Error: "bool" is not an allowed type 

इस दृष्टिकोण का लाभ अब आप प्रकार जाँच पैटर्न मिलान है कि जब आप मानों तक पहुंच है, और आप डॉन 'टी obj के असुरक्षित downcasting क्या करना है:

let myfun (values:(string*Value) list) = 
    values 
    |> List.map (fun (k, v) -> 
     match v with 
     | Int v -> k + ":" + string v 
     | String v -> k + ":" + v.Trim()) 
     // etc. 
    |> String.concat "\n" 

myfun ["Name" ==> "Freddie"; "Age" ==> 50] |> printfn "%s" 
//Name:Freddie 
//Age:50 
+0

हाँ, यह एक बहुत अच्छा मुद्दा है। मैं इस कार्यक्रम में कहीं और कर रहा हूं, डीएसएल समेत कोड से संबंधित प्रश्न। –