F#4:让/使用/做

在本文中,我们将研究F#中的绑定,尤其是我们将研究Let / Use / Do。 现在您可能会问自己是什么绑定,并且由于我们尚未检查它们,所以现在该讨论一下了。

简而言之,绑定将标识符与值或函数相关联。


您可以使用let关键字将名称与值或函数相关联。 实际上,Let有一个细微的不同用法,其中一个在模块的顶层声明,然后另一个在我们定义一些局部上下文的地方声明。 这是他们两个的例子:

module DemoModule = let someFunction = let a = 1 let b = 2 a * b 

我们可以使用完全限定的名称来访问someFunction,例如DemoModule.someFunction,但是嵌套的Let(a,b)绑定仅可用于Let顶级。 通常,当我们使用Let绑定声明内部模块的某些值时,会看到更多的情况,因此让我们集中精力在这里(尽管很重要的一点是,知道可以在模块级别使用Let)。

因此,让我们来看更多示例。

 let aString ="this is a string" let aInt = 12 let aDecimal = 12.444 let aPiFunction () = Math.PI let aSquareRootFunction (x) = Math.Sqrt(x) let aFullyTypedSquareRootFunction (x :float) = Math.Sqrt(x) let a,b = "a","tuple" 

您可以看到我们可以使用Let绑定来绑定多个值,这些值可以是各种类型,例如:

  • 整数
  • 小数
  • 没有输入参数的功能
  • 具有输入参数的函数(其中类型为F#的逻辑推理系统将正确选择类型)
  • 具有完全定义的参数类型的函数
  • 元组(在这种情况下,字符串*字符串元组)

在其他地方,您可以在类中看到Let绑定,但是我们将在本系列的下一篇文章中对此进行更详细的讨论。

您可以阅读有关MSDN上的Let绑定的更多信息。

使用方法


Use绑定与Let绑定非常相似,因为它会将值绑定到表达式的结果。 主要区别在于,使用绑定旨在与IDisposable类型一起使用,并在其值不在范围内时自动删除该值。 这与.NET using关键字非常相似,尽管我不认为F#Use绑定与.NET中的使用完全相同,因为.NET中的using关键字实际上是try /最后调用Dispose( )。

在上一篇有关文本格式设置的文章中,我们已经看到了Use绑定的示例,但是为了提醒自己,让我们再来看一看。

 use sw = new StreamWriter(@"c:\temp\fprintfFile.txt") fprintf sw "This is a string line %s\r\n" "cat" fprintf sw "This is a int line %i" 10 sw.Close() 

在此示例中,Use绑定保证了StreamWriter方法将在调用sw.Close()之后调用其Dispose()方法,如上所示。

Use仅适用于IDisposables,如果尝试将其用于其他用途,则会出现编译错误,如下所示:

图片

由于Dispose()方法是在Use绑定的末尾调用的,因此应注意不要返回与Let关联的值。

 let Write = use sw = new StreamWriter(@"c:\temp\fprintfFile.txt") sw 

如果您绝对需要传回IDisposable,这是Use绑定的一部分,则可以改用回调。 这样的事情会起作用,但是我会停下来问自己,如果您做这些事情,您是否正确地设计了您的设计:

 let Write callback = use sw = new StreamWriter(@"c:\temp\fprintfFile.txt") fprintf sw "Write is writing to the StreamWriter" callback sw sw let callback sw = fprintf sw "sw is the StreamWriter" let disp = Write callback 


do绑定用于执行代码,而无需定义函数或值。 绑定必须始终返回Unit(无值/无效)。 在许多情况下,您可以省略Do绑定,一切都会按预期进行。

这是一些使用Do绑定的示例。

 do printf "doing the do" //oh oh not a unit do printf "print a sum %i" 1 + 1 do 1 + 1 

如果我改用上面的代码给您看一个屏幕截图,您会发现如果尝试对非Unit结果使用Do,则编译器会抱怨。

图片

您有两种选择:

  • 使用管道运算符忽略结果
  • 创建让绑定

我在下面展示了每个示例:

 let x = 1 + 1 do printf "print a sum %i" x do (1+1 |> ignore) 

放开 使用! 做吧!


尽管我不想讨论它们,但有时您可能会偶然看到Let! 使用! 执行!,当您执行此操作时,这就是所谓的计算表达式的一部分。 您很可能会在F#异步工作流中看到这一点,我们将在最后一篇文章中介绍。 如果我足够理解,我什至可以尝试解释如何创建自己的“计算表达式”,尽管它们是一个相当抽象的概念和一个相当复杂的主题,所以现在不是时候了。

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


All Articles