Strictly creating an IDictionary <_, obj>

Is there a shorter way to create an IDictionary<_,obj> , possibly without a box for each value? This is what I have.

 let values = [ "a", box 1 "b", box "foo" "c", box true ] |> dict 

Dictionary<_,obj>.Add can be called without a box, but I could not figure out how to use it, the shorter than mine.

I hope for something else besides defining a box operator.

EDIT

Based on Brian's suggestion, here is one way to do this, but he has his own problems.

 let values = Seq.zip ["a"; "b"; "c"] ([1; "foo"; true] : obj list) |> dict 
+4
source share
7 answers

Here's a solution, following the kvb suggestion (perhaps the most concise and clear so far):

 let inline (=>) ab = a, box b let values = [ "a" => 1 "b" => "foo" "c" => true ] |> dict 
+9
source

Here is the smallest thing I could crack. He has more characters than your version of boxing, but maybe he feels a little less dirty. Note that ^ is right-associative (this is the concat string operator inherited from ocaml), which allows it to work as :: , and has a higher priority than,, so parentheses are needed around tuples.

 let inline (^+) (x1:'a,x2:'b) (xl:('a*obj) list) = (x1,box x2)::xl let values = ("a", 1) ^+ ("b", "foo") ^+ ("c", true) ^+ [] |> dict 
+2
source

Here's another “solution” that is inspired by Brian’s proposal, but it uses reflection, so there’s time and security.

 let unboxPair (pair:obj) = let ty = pair.GetType() let x = ty.GetProperty("Item1").GetValue(pair,null) :?> string let y = ty.GetProperty("Item2").GetValue(pair,null) x,y let unboxPairs (pairs:obj list) = pairs |> List.map unboxPair let values = unboxPairs ["a", 1 "b", "foo" "c", true] |> dict 
+2
source

I had a similar problem in FsSql, and I just removed the box in the function:

 let inline T (a,b) = a, box b let values = dict [T("a",1); T("b","foo"); T("c",true)] 
+1
source

A variation of Stephen's idea:

 open System open System.Collections.Generic type Dictionary<'a,'b> with member this.Add([<ParamArray>] args:obj[]) = match args.Length with | n when n % 2 = 0 -> for i in 1..2..(n-1) do this.Add(unbox args.[i-1], unbox args.[i]) | _ -> invalidArg "args" "even number of elements required" let d = Dictionary<string,obj>() d.Add( "a", 1, "b", "foo", "c", true ) 
+1
source
 let v : (string*obj) list = [...] let values = dict v 

This is one way a type signature to the left of a literal list will automatically update each item.

0
source

Another solution, just define a bunch of overloaded extension elements on Dictionary<'a,'b> :

 open System.Collections.Generic type Dictionary<'a,'b> with member this.Add(x1,y1,x2,y2) = this.Add(x1,y1) this.Add(x2,y2) member this.Add(x1,y1,x2,y2,x3,y3) = this.Add(x1,y1,x2,y2) this.Add(x3,y3) member this.Add(x1,y1,x2,y2,x3,y3,x4,y4) = this.Add(x1,y1,x2,y2,x3,y3) this.Add(x4,y4) member this.Add(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5) = this.Add(x1,y1,x2,y2,x3,y3,x4,y4) this.Add(x5,y5) member this.Add(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5,x6,y6) = this.Add(x1,y1,x2,y2,x3,y3,x4,y4,x5,y5) this.Add(x6,y6) //etc. let values = let d = Dictionary<_,obj>() d.Add("a", 1, "b", "foo", "c", true) d 

Of course, the values here are not immutable as in your question, but I'm sure you could use the same strategy for this purpose.

0
source

All Articles