2

I don't understand why I'm getting the error below:

> let x = "ABCDAACCECFG"|>Seq.sort|>Seq.groupBy (fun x->x);;
val x : seq<char * seq<char>>

> x;;
val it : seq<char * seq<char>> =
  seq
    [('A', seq ['A'; 'A'; 'A']); ('B', seq ['B']);
     ('C', seq ['C'; 'C'; 'C'; 'C']); ('D', seq ['D']); ...]

> (x|> Seq.head).GetType();;
val it : System.Type =
  System.Tuple`2[System.Char,System.Collections.Generic.IEnumerable`1[System.Char]]
    {Assembly = mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;
     AssemblyQualifiedName = "System.Tuple`2[[System.Char, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Collections.Generic.IEnumerable`1[[System.Char, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
...
     DeclaredProperties = [|Char Item1;
                            System.Collections.Generic.IEnumerable`1[System.Char] Item2;
                            Int32 System.ITuple.Size|];
...;}

> x|> Seq.map (fun x -> x.Item1, x.Item2)|>dict;;

  x|> Seq.map (fun x -> x.Item1, x.Item2)|>dict;;
  ------------------------^^^^^

stdin(123,25): error FS0039: The field, constructor or member 'Item1' is not defined.

It appears to me that x is a sequence of tuples where each tuple has an Item1 (Char) and Item2 (seq Char) property. I'd like to turn this into a dictionary.

Clearly, I'm missing something. Can anyone help me understand what I'm doing wrong and how to get it right?

Dweeberly
  • 4,668
  • 2
  • 22
  • 41
  • 4
    For one thing, if `x` is already a two-tuple, then what you're attempting to do is just an identity conversion, i.e. equal to `x |> Seq.map (fun x -> x) |> dict`. ;-] `dict x` is sufficient for your code, but in general you access elements of a tuple via pattern matching/destructuring, not via `ItemN`. – ildjarn Aug 21 '17 at 01:34
  • Possible duplicate of [How can I refer to a specific member of a Tuple of any size in F#](https://stackoverflow.com/questions/5252628/how-can-i-refer-to-a-specific-member-of-a-tuple-of-any-size-in-f) – ildjarn Aug 21 '17 at 01:37
  • 2
    you can always access the tuple elements with the functions `fst` and `snd` however as per the first comment, what is it exactly that you are trying to do? Maybe there is a better way? – s952163 Aug 21 '17 at 01:52
  • 2
    The `.Item1` and `.Item2` properties are not exposed for F# tuples; you're expected to use pattern-matching. E.g., `fun (a,b) -> ...` will ensure that the names `a` and `b` inside that function now refer to the first and second items of the tuple. But as @ildjarn already pointed out, your `(fun x -> x.Item1, x.Item2)` function is doing absolutely nothing, so it can just be removed. – rmunn Aug 21 '17 at 03:46

1 Answers1

2

It doesn't appear that F# surfaces the Item1 and Item2 properties from the underlying tuple like in C#. I tried the following which appear to work without error.

Using functions fst and snd:

x|> Seq.map (fun x -> fst x, snd x) |> dict

Using pattern matching:

x|> Seq.map (function (key, value) -> (key, value)) |> dict

And apparently without using Seq.map works as well:

x |> dict
jpierson
  • 16,435
  • 14
  • 105
  • 149
  • 1
    Thank you that's what I needed. I found the second (pattern matching) form particularly useful as one thing I wanted to do was to create a dictionary with the key and count (Seq.length) of the value array. – Dweeberly Aug 21 '17 at 16:55