F#6:元组

因此,我们继续F#的旅程。 下面的文章将重点介绍可能具有或不具有标准.NET等效项的F#类型。 这篇文章是关于元组的。

什么是元组


元组是一组未命名但有序的值,可能是不同的类型。

创建元组


元组很容易创建,我们只做如下所示的事情。 请注意,我是如何创建一个元组的混合包的,其中一些是数字,而另一些是字符串,我们还可以混合并匹配类型和值的数量。

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

通用元组


接受元组的函数也可以毫无问题地接受通用元组。 诸如F#的推理系统将很乐意为元组处理正确类型的推理。 这是一个例子。

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

这是上面执行的结果,您可以看到someFunction函数被接受并与各种类型的元组一起使用而没有问题。

图片

元组签名


到目前为止,我们还没有完全了解F#签名,实际上,由于我认为这很复杂,因此我也决定将其整个博客都投入到这个主题中。 但是,我们位于我们现在所在的位置,即现在和现在,并且我们正在研究元组,所以现在我只想演示元组的特征。

假设我在FSI窗口中声明了以下元组:
 let a = (1,2) let b = (1,"codfather") let c = (1,"c", 12.5) 

然后我在FSI窗口中检查了它们; 我们将看到以下内容:
 val a : int * int = (1, 2) val b : int * string = (1, "codfather") val c : int * string * float = (1, "c", 12.5) 

这很有趣,我们可以在这里看到几件事:
  • 括号不是类型签名的一部分
  • F#类型系统可以根据元组本身包含的值正确推断类型。
  • 逗号替换为“ *”

因此,透明的元组如下所示:
 let a = (1,2) 

将具有以下签名:
 int * int 


元组分解


因此,我们看到了如何创建元组,但是如何将它们拆分或解构为单独的值呢。 有可能吗 当然可以 和以前一样,让我们​​从几个示例开始:
 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 

结果将在标准控制台窗口中打印,如下所示:
图片

使用让


但是我们如何得到各个部分呢? 好吧,您只需要上面的代码,但让我们看一个示例。 假设我们有一个这样的元组:
 (1,2) 

而且我想将元组的两个“值”的值都绑定到一些新的单个值上,我们可以这样做:
 let (a,b) = (1,2) 

我们还可以只选择我们真正需要的值,这是对不需要的部分使用通配符完成的。 这保证了没有不必要的价值约束。 这是一个例子:
 let (_,z) = (1,2) 


使用内置的元组功能


还内置支持从元组获取第一个和第二个值。 使用“ fst ”和“ snd ”功能可以做什么。 除了第2个元素外,不支持任何其他功能(这可能是最常见的情况)。 “ Fst ”和“ snd ”的用法如下:
 let first = fst (1, 2) let second = snd (1, 2) 

现在,我想提请您注意一种特殊情况,在这种情况下,我们可能与试图爆炸为单个值的值的数量不匹配。 因此,这将类似于此处的示例:
 let (a ,b) = (1,"cat", 'c') 

您可以看到元组本身实际上包含3个值,但是Let绑定只有2个值,因此编译器会向我们发出警告,如下面的屏幕快照所示:
图片

创建新的元组


您可能想从现有的元组创建新的元组,这很简单,这里是一个示例:
 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 

图片

元组比较


只有在以下情况下元组才被视为相等

  • 它们具有相同数量的值。
  • 所有值都被认为是相等的(显然,这些值可以是自定义的Equals方法或自定义的IEquatable实现等)

让我们看一些简单的例子。

 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')) 

图片

实际上,如果您的元组具有不同的长度(元素数),并且尝试使用等号运算符“ =”来比较它们,则会收到警告:
图片

元组匹配模式


我们还没有处理匹配模式,但是稍后我们将看到有关此主题的整篇文章。 同时,只要知道这是再次匹配输入参数的方法即可。 您可以对元组执行此操作,操作如下:
 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) 

图片

Source: https://habr.com/ru/post/zh-CN470271/


All Articles