Asp.Net教程,WinForm教程,Asp.Net MVC,vs2008教程,vs2010教程,Silverlight技术,源码下载,Asp.Net视频教程
全站热门标签
vs2010 Silverlight 存储过程 水晶报表 ADO.NET JavaScript LINQ AjaxPro DataGridView 面向对象 Extjs GridView XML DevExpress HTML教程 Oracle jQuery 分页 GDI+ Visual C++2010 MySQL Office2010 WPF MVC Dojo WCF4.0 VB.NET Sql2005 textbox cookie WCF WinForm Discuz!NT SQL经典语句 T-SQL checkbox ASPxGridView F# asp.net SQL VS2008新特性 DropDownList Access TreeView Ajax VS2008 页面执行时间 Flex 字符串 回调 VB2005 DataSet C#时间 ASP.NET性能优化 用户在线检测 动画
当前位置: 主页 > vs2010教程 >

Visual Studio 2010 F#快速上手

时间:2009-11-09 21:39来源:未知 作者:admin 点击:

F#是一种.NET平台上的函数式编程语言。就像C#和VB.NET,F#可以利用.NET的核心类库,如WPF,WCF,VSTO等等,通过F#您甚至可以使用XNA编写XBox游戏。

  仅仅如此并不意味着您应该去学习它。那为何要使用F#呢?作为一种函数式编程语言,F#使得某些领域的编程要比命令式编程(如使用C#)更为容易。并行编程(Parallel Programming)和面向语言编程(Language-Oriented Programming)是其中的两个领域。

  如果您曾经编写过.NET应用程序,并感觉自己在努力使用手头的语言表达自己的想法,也许F#就是您在寻找的。

  语言基础

  #light(OCaml兼容)

  F#源自OCaml,具有交互编译OCaml的能力,也就是可以不经修改即可编译简单的OCaml程序。这种能力也带来了令人讨厌的语法。#light(发音为hash-light)是一个编译器指令,可以简化F#的语法。

  强烈建议您保持使用#light,您会发现,在大多数F#代码片段中要么会声明它,要么是假定已经声明了它。

  let square x = x * x(类型推演)

  这行代码定义了一个函数:square,它会求得数字x的平方。考虑一下C#中等价的代码:

public static int square(int x)

{

    return x * x;

}

  在C#中,您需要制定参数和返回值的类型信息,而F#则帮您搞定了。这种行为称为类型推演(Type Inference)。

  从函数的签名,F#可以知道“square”函数接受一个参数“x”,并且函数返回“x * x”(在函数体内的最后一次求值将作为返回值,因此无须return关键字)。因为很多基元类型都支持*操作,比如byte,uint64,double等,F#默认会使用int类型,有符号的32位整数。

  现在考虑下面的代码,它为其中的一个参数提供了“类型注解(type annotation)”,告诉编译器期望的类型。因为x标为“string”,“+”操作只定义在两个string间,因此y也必须为string类型,返回值是两个字符串拼接的结果。

> let concat (x : string) y = x + y;;

val concat : string -> string -> string

> concat "Hello, " "World!";;

val it : string = "Hello, World!"

  后面我们将讨论类型推演的更多高级主题,现在您只要享受F#编译器的智能带来的方便就好了。

  let numbers = [1 .. 10](F# lists)

  这行代码声明了一个列表(list),其元素是从1至10。如果您用的是[|1 .. 10|],F#会创建一个.NET的整型数组(array)。而在F#中,列表是一个不可变的链表(linked list),这也是函数式编程的基础。试着将这些代码输入到FSI中(记住添加“;;”):

// Define a list

let vowels = ['e'; 'i'; 'o'; 'u']

// Attach item to front (cons)

let cons = 'a' :: vowels

// Concat two lists

let sometimes = vowels @ ['y']

  let squares = List.map square numbers

  现在我们有了一个整型列表(numbers)和一个函数(square),我们希望创建一个新的列表,它的每一项是对numbers的每一项进行square运算后的结果。

  幸运的是,List.map可以做到。考虑下面的例子:

> List.map (fun x -> x % 2 = 0) [1 .. 10];;

val it : bool list

= [false; true; false; true; false; true; false; true; false; true]

  代码(fun x -> x % 2 = 0)定义了一个匿名函数,称为lamdba表达式,接受一个参数x,返回值为表达式“x % 2 = 0”的结果,也就是判断x是否为偶数。

  注意我们刚才做的——将一个函数作为参数传递给另一个函数。在C#中这个并不容易。但在F#可以很清楚地表达出来,而且代码很简洁。将函数像值一样传递被称为“一等函数(first order functions)”,也是函数式编程的基础。

  printfn "N^2 = %A" squares

  printf是打印文本到控制台窗口的一种简单而又类型安全的方式。要更好地了解printf,考虑下面的例子,它打印一个整数、浮点数和字符串。

> printfn "%d * %f = %s" 5 0.75 ((5.0 * 0.75).ToString());;

5 * 0.750000 = 3.75

val it : unit = ()

  %d,%f,%s分别是int、float、string的占位符。%A则可用于打印任何值。

  Console.ReadKey(true) (.NET互操作)

  我们程序的最后一行只是简单地调用了System.Console.ReadKey方法,这样可以让程序在关闭其暂停。因为F#建立在.NET的基础上,您可以在F#中调用任何.NET类库——从正则表达式到WinForms。代码“open System”用于打开命名空间,类似于C#中的using。

  不可变性(Immutability)

  也许已经注意到,我一直使用“值(value)”来表示一个标识符(identifier),而不是“变量(variable)”。这是由于默认情况下,F#中的类型是不可变的(immutable),也就是说,一经创建即不可修改。看起来这是一个很大的限制,但是不可变性可以避免某种类型的bug。另外,不可变的数据天然地具备线程安全的特性,这意味着您无需在处理并行情况时担心同步锁的发生。

  如果您确实需要修改数据,可使用F#的mutable关键字,它会创建一个变量(而不是值)。我们可以通过左箭头操作符(<-)来修改变量的值。

> let mutable x = "the original value.";;

val mutable x : string

> printfn "x's value is '%s'" x;;

x's value is 'the original value.'

val it : unit = ()

> x <- "the new one.";;

val it : unit = ()

> printfn "x's value is now '%s'" x;;

x's value is now 'the new one.'

val it : unit = ()

 

  引用值(Reference values,Microsoft.FSharp.Core.Ref<_>)

  引用值是另一种表示可修改数据的方式。但它不是将变量存储在堆栈(stack),引用值其实是一个指向存储在堆(heap)上的变量的指针(pointer)。在F#中使用可修改的值时会有些限制(比如不可以在内部lambda表达式中使用)。而ref对象则可被安全地传递,因为它们是不可变的record值(只是它有一个可修改的字段)。

  使用引用值时,用“:=”赋一个新值,使用“!”进行解引用。

> let refCell = ref 42;;

val refCell : int ref

> refCell := -1;;

val it : unit = ()

> !refCell;;

val it : int = –1

 

  模块(Modules)

     在C#中所有一切都要属于相应的类。尽管在F#中,我们仍然可以用熟悉的方式声明标准的.NET类,但它也有模块的概念,模块是值、函数和类型的集合(可以对比一下命名空间,后者只能包含类型)。

  这也是我们能够访问“List.map”的原因。在F#库(FSharp.Core.dll)中,有一个名为“List”的模块,它包含了函数“map”。

  在快速开发的过程中,如果不需要花费时间去设计严格的面向对象类型体系,就可以采用模块来封装代码。要声明自己的模块,要使用module关键字。在下面的例子中,我们将为模块添加一个可修改的变量,该变量也是一个全局变量。

module ProgramSettings =

    let version = "1.0.0.0"

    let debugMode = ref false

module MyProgram =

    do printfn "Version %s" ProgramSettings.version

    open ProgramSettings

    debugMode := true

 

  元组(Tuples)

  元组(tuple,发音为‘two-pull’)表示值的有序集合,而这些值可看作一个整体。按传统的方式,如果您要传递一组相关的值,需要创建结构(struct)或类(class),或者还需要“out”参数。使用元组我们可以将相关的值组织起来,同时并不需要引入新的类型。

  要定义一个元组,只要将一组值用逗号分隔,并用圆括号把它们括起来即可。

> let tuple = (1, false, "text");;

val tuple : int * bool * string

> let getNumberInfo (x : int) = (x, x.ToString(), x * x);;

val getNumberInfo : int -> int * string * int

> getNumberInfo 42;;

val it : int * string * int = (42, "42", 1764)

 

  函数甚至可以接受元组为参数:

> let printBlogInfo (owner, title, url) = printfn "%s's blog [%s] is online at '%s'" owner title url;;

val printBlogInfo : string * string * string -> unit

> let myBlog = ("Chris", "Completely Unique View", "http://blogs.msdn.com/chrsmith");;

val myBlog : string * string * string

> printBlogInfo myBlog;;

Chris's blog [Completely Unique View] is online at 'http://blogs.msdn.com/chrsmith'

val it : unit = ()

(责任编辑:admin)

Tags:F#
责任编辑:admin
返回顶部
------分隔线----------------------------
推荐内容
骆驼户外男 真皮磨砂日常休闲鞋 低帮 2011秋冬新款 专柜正品特价 骆驼户外男 真皮磨砂日常休闲鞋 低帮 2011秋冬新款 专柜正品特价