F#的真正价值不仅仅在于你可以利用者门语言做什么,而是其于其他语言的交互性。例如,F#并不包含一个界面(GUI)库。但F#已经天生与.NET紧密相连,你可以使用.NET类库来完成任何现在已包含的功能。
例如:
/// Split a string into words at spaces
let splitAtSpaces (text: string) =
text.Split ' '
|> Array.toList
Text.Split方法就是调用了.NET类库的实例方法。
下面是一个重度使用System.Net和System.Windows.Forms类库的F#程序:
open System.Windows.Forms
let form = new Form(Visible=true,TopMost=true,Text="Welcome to F#")
let textB = new RichTextBox(Dock=DockStyle.Fill, Text="Here is some initial text")
form.Controls.Add textB
open System.IO
open System.Net
/// Get the contents of the URL via a web request
let http (url: string) =
let req = System.Net.WebRequest.Create(url)
let resp = req.GetResponse()
let stream = resp.GetResponseStream()
let reader = new StreamReader(stream)
let html = reader.ReadToEnd()
resp.Close()
html
let google = http "http://www.google.com"
textB.Text <- http "http://news.bbc.co.uk"
上述代码使用了一些非常重要的.NET类库并且使用了F#的语法风格及特性:
使用命名空间和模块(Modules)
在例子程序中你看到的第一行就是使用open关键字来使用System.Windows.Forms。当然,F#也支持直接访问:
let form = new System.Windows.Forms.Form(Visible=true,TopMost=true,
Text="Welcome to F#")
关于open的几点说明
1. open并不会真正的加载或引用一个类库,其只是引用已经加载类库的功能。加载一个类库需要在代码中使用#r,或者在命令行里使用-r选项。
2. 如果一个dll包含了一个namespace的所有方法,F#会自动引用这个dll。
3. 即便引用的namespace中有重复定义的属性或方法,也可以直接使用。F#会选择最近open的namespace中的方法。
4. Namespace的引用依然可以使用别名,例如:module MyString = My.Modules.String , type SysString = System.String.
使用new和设置属性
简单的来说,还是很直观易懂:
let form = new Form(Visible=true,TopMost=true,Text="Welcome to F#")
总之与C#的new非常相似。在new中设置的属性必须是构造函数中存在的参数或者其返回对象拥有的属性。
值得说明的是,这些属性都是object属性,也就是说他们都是可变变量。所以我们也可以通过以下方式来初始化form:
open System.Windows.Forms
let form = new Form()
form.Visible <- true
form.TopMost <- true
form.Text <- "Welcome to F#"
就像你看到的一样,F#使用<-来进行赋值操作。
观察一下代码:
let form2 = form
form2.Text <- "F# Forms are Fun"
其效果依然是改变form的text属性。这表明F#中let声明的值(value)与其所指向的对象是引用关系。=操作符的操作是浅拷贝。
值,方法和属性的差别
· 简单值(value):函数(function),参数(parameter)和使用let关键字定义的根级别(top-level)的值或匹配(pattern matching)。 例如:form, text, wordCount。
· 方法(method):函数值(function value)使用了类型。接口,类和记录(record,望高人指点这是什么东西?)及组合类型(union types)都可以拥有方法。方法可以被重载(overload)并且必须同时使用它们的参数(比较难以理解,个人感觉说的就是使用方法的时候必须传入其要求的参数。基本是句废话)。例如:System.Net.WebRequest.Create和resp.GetResponseStream。
· 属性:一个调用读写数据的成员方法的快捷方式。接口,类,和记录及组合类型全都可以拥有属性。例如:System.DateTime.Now和form.TopMost。
· 索引器(indexer properties):一个可以使用参数的属性。命名为“Item”的索引器可以通过.[_]的方式访问,例如:vector.[3]和matrix.[3,4]。
抓取网页
本章一开始的例子程序使用了System.Net类库定义了一个名为http的函数去读取HTML页面。我们也可以在F# Interactive中一步一步的调用这些方法:
> open System;;
> open System.IO;;
> open System.Net;;
> let req = WebRequest.Create("http://www.microsoft.com");;
val req : WebRequest
> let resp = req.GetResponse();;
val resp : WebResponse
> let stream = resp.GetResponseStream();;
val stream : Stream
> let reader = new StreamReader(stream);;
val reader : StreamReader
> let html = reader.ReadToEnd();;
val html : string
> textB.Text <- html;;
简明易懂。与C#无异。
总结
本章简要描述了F#与.NET类库的互操作特性。这个特性非常重要,使得我们可以立即将F#引入到日常工作当中,并不会带来任何代码重用性问题。