F#,体验函数式编程

Chris 2010/3/10 08:03

F#是微软给我们带来的一门新的编程语言,让我们可以从另外一个视角写程序。那什么是函数式编程?看看这段话也许你能够明白:

F# supports functional programming, which is a style of programming that emphasizes
what a program should do, not explicitly how the program should work
.

我的理解是,函数编程即,告诉程序要做什么,而不是告诉程序怎么做。怎么做是程序的事不是程序员的事,哈哈,有点儿神奇……记得有人说过SQL也是一种“函数式编程语言”(具体是不是正确我也不知道,但是我觉得有道理)比如我们写SELECT * FROM TABLE是告诉程序我们需要从Table中读取数据,但是我们不需要编写如何从Table中读取数据的代码。而如果是从C#的List中读取数据,我们可能不得不写foreach自己一条条检索数据。

现在,看看这个“函数式”语言给我们带来了什么?

先从一个简单的函数开始~

let square n = n * n;
//let result = square 3;
//System.Console.WriteLine result;
square 3 |> System.Console.WriteLine

 

被注释的2、3行和第4行效果是一样的,都是输出9。注意到F#两行程序就实现一个平方函数,而C#需要的代码量会多出不少。

函数递归

let rec factorial n =
    if n = 0
    then 1
    else n * factorial ( n - 1 )

factorial 5 |> Console.WriteLine;

上面是一个简单的,计算阶乘的函数。F#的语法真是能简则简,{}、return之类的统统抛弃。但是缩进好像已经成为语法的一部分:

image

上图中if原有的缩进被删除之后,IDE提示有语法错误。

Collections

list和tuples(这个不知道有什么用?)update: tuple可以存储不同类型的数据。

let turnChoices = ("left", "right")
Console.WriteLine turnChoices
let intAndSquare = (1, square 2)
Console.WriteLine intAndSquare;

上面的代码分别输出(left, right)和(1, 4),包含括号。不明白这个东东到底有什么用。

let friends = ["jim"; "jack"; "linda"; "sayid"]
let newFriends = "kate" :: friends
Console.WriteLine newFriends
printf "old: %A \r\n" friends
printf "new: %A \r\n" newFriends

 

定义一个List,将一个新的元素放入List。

得到的输出是:

image

看到kate已经被添加到新的List中,而原始的List是不会改变的:称之为immutable。其他值也是如此,如果尝试更改一个值,会得到错误:

image

上图红色方框部分尝试修改a的值,会得到错误。注意到赋值的表达式是<-,但是蛮形象,就是不习惯……

如果需要变量可以被更改需要显示的指定为mutable,如:

let mutable internalAge = 1

//赋值应该用<-而不是=

internalAge <- value++

F#对类的支持

/// The declaration creates a constructor that takes two values, name and age.
type Person(name:string, age:int) =
    // A Person object's age can be changed. The mutable keyword in the
    // declaration makes that possible.
    let mutable internalAge = age

    // Declare a second constructor that takes only one argument, a name.
    // This constructor calls the constructor that requires two arguments,
    // sending 0 as the value for age.
    new(name:string) = Person(name, 0)

    // A read-only property.
    member this.Name = name
    // A read/write property.
    member this.Age
        with get() = internalAge
        and set(value) = internalAge <- value

    // Instance methods.
    // Increment the person's age.
    member this.HasABirthday () = internalAge <- internalAge + 1

    // Check current age against some threshold.
    member this.IsOfAge targetAge = internalAge >= targetAge

    // Display the person's name and age.
    override this.ToString () =
        "Name:  " + name + "\n" + "Age:   " + (string)internalAge

// The following let expressions are not part of the Person class. Make sure
// they begin at the left margin.
let person1 = Person("John", 43)
let person2 = Person("Mary")

// Send a new value for Mary's mutable property, Age.
person2.Age <- 15
// Add a year to John's age.
person1.HasABirthday()

// Display results.
System.Console.WriteLine(person1.ToString())
System.Console.WriteLine(person2.ToString())
// Is Mary old enough to vote?
System.Console.WriteLine(person2.IsOfAge(18))

 

new关键字没有了,而是直接调用其构造函数,定义属性用member关键字,这语法和C#的区别太大了。

如果安装了VS 2010就可以直接创建F#项目,如果安装的是VS 2008就需要先从这里下载安装F#组件。

参考资料:

http://www.cnblogs.com/JeffreyZhao/archive/2010/03/03/async-and-parallel-design-patterns-in-fsharp-1-parallelizing-cpu-and-io-computations.html

http://msdn.microsoft.com/en-us/fsharp/default.aspx

http://msdn.microsoft.com/en-us/library/dd233160(VS.100).aspx 有一些入门例子

http://fsharpsamples.codeplex.com/ F#示例代码

http://www.ibm.com/developerworks/cn/web/wa-javascript.html JavaScript函数式编程,与我们的F#是不是一个概念?

.NET

Comments

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading