F # 6: Tuples

So, our journey to F # continues. The following article will focus on F # types that may or may not have standard .NET equivalents. This post is about tuples.



What are tuples



A tuple is a group of unnamed, but ordered values, possibly of different types.



Creating Tuples



Tuples are very easy to create, we just do something like the one shown below. Notice how I created a mixed package of tuples, some of which are numbers and others are strings, and we can also mix and match both types and the number of values.



let a = (1,2) let b = (1,"cat") let c = (1,"cat") let d = (1,"cat", 'c')
      
      





Universal tuples



Functions that accept tuples can also accept universal tuples without any problems. An inference system like F # will happily handle the inference of the correct types for a tuple. Here is an example.



 let someFunction tup = let (x,y) = tup printfn "x is %A and y is %A" xy do someFunction ("cat","dog") do someFunction (11,12)
      
      





And here are the results of the execution above, where you can see that the someFunction function accepted and worked with various typed tuples without problems.



image



Tuple Signatures



So far, we have not touched upon the understanding of F # signatures at all, in fact, this is a topic to which I also decided to devote a whole blog post, since I believe that it is quite complicated. However, we are located where we are, that is, here and now, and we are studying tuples, so now I just wanted to demonstrate what the signature of the tuple would look like.



Suppose I declared the following tuples in the FSI window:

 let a = (1,2) let b = (1,"codfather") let c = (1,"c", 12.5)
      
      





And then I examined them in the FSI window; we will see something like this:

 val a : int * int = (1, 2) val b : int * string = (1, "codfather") val c : int * string * float = (1, "c", 12.5)
      
      





This is interesting, we can see a couple of things here, namely:



So the crystal clear tuple looks like this:

 let a = (1,2)
      
      





Will have the following signature:

 int * int
      
      







Tuple Breakdown



So, we saw how we can create tuples, but what about breaking or deconstructing them back into separate values. Is it possible? Yes of course. As before, let's start with a few examples:

 let (a,b) = (1,2) printfn "(a,b) = (1,2), so value of 'a' should be 1, and it is =%i,\r\n 'b' should be 2, and it is =%i" ab //   ,  ,     ,   //     let (_,z) = (1,2) printfn "grabbing last value from (1,2) which is = %i" z let (a,b :string) = (1,"cat") printfn "grabbing (1,\"cat\") which has values = %i %s" ab let (a :int,b :string) = (1,"cat") printfn "grabbing (1,\"cat\") which has values = %i %s" ab let (a ,b, c) = (1,"cat", 'c') printfn "grabbing (1,\"cat\",'c') which has values = %i %s %c" abc let first = fst (1, 2) printfn "grabbing fst from (1,2) which has values = %i" first let second = snd (1, 2) printfn "grabbing 2nd from (1,2) which has values = %i" second
      
      





The results are printed in a standard console window, as follows:

image



Using Let



But how did we get the individual parts? Well, all you need is the code above, but let's look at one example. Suppose we had a tuple like this:

 (1,2)
      
      





And I wanted to get the values ​​of both "values" of the tuple, tied to some new individual values, we could just do this:

 let (a,b) = (1,2)
      
      





We can also select only those values ​​that we really need, which is done using a wildcard for unwanted parts. Which guarantees the absence of unnecessary value binding. Here is an example:

 let (_,z) = (1,2)
      
      







Using the built-in tuple functions



There is also built-in support for getting the first and second values ​​from a tuple. What can be done with the fst and snd functions. There is no support for anything other than the 2nd element (these are probably the most common cases). “ Fst ” and “ snd ” can be used as follows:

 let first = fst (1, 2) let second = snd (1, 2)
      
      





Now I want to draw your attention to a special case where we may have a mismatch with the number of values ​​that we are trying to explode into individual values. So this will be something like an example here:

 let (a ,b) = (1,"cat", 'c')
      
      





You can see that the tuple itself actually contains 3 values, but the Let binding has only 2 values, so the compiler warns us about this, as you can see in the screenshot below:

image

Creating New Tuples



You might want to create new tuples from existing tuples, it's simple enough, here is an example:

 let oldOne = (1,2) let (x,y) = oldOne let newOne = (x+1,y+1) printfn "original = %A, and we did this (x+1,y+1)\r\n to obtain newOne = %A" oldOne newOne
      
      





image



Comparing Tuples



Tuples are considered equal only if





Let's look at some simple example.



 printfn "(1,2) = (3,4) =% b" ((1,2) = (3,4)) printfn "(1,2) = (1,2) =% b" ((1,2) = (1,2)) printfn "('a', 'b') = ('a', 'b') =% b" (('a', 'b') = ('a', 'b')) printfn "('a', 'b') = ('a', 'c') =% b" (('a', 'b') = ('a', 'c'))
      
      





image



In fact, if your tuples have different lengths (the number of elements) and you try to compare them using the equality operator “=”, you will get a warning:

image



Tuple matching patterns



We have not dealt with matching patterns yet, but later we will see a whole post on this topic. In the meantime, just know that this is a way to match input parameters again. You can do this for tuples, which is done as follows:

 let someFunction tup = match tup with | 1,2 -> printfn "you passed (1,2)" | _,_ -> printfn "you passed some other tuple" do someFunction (11,12) do someFunction (4,5) do someFunction (1,2) do someFunction (13,23)
      
      





image







All Articles