从C# 3.0到F#

从C# 3.0到F#

 

Written by Allen Lee

 

缘起

当你看到这篇文章的标题时,你有什么感觉?是不是很想脱口而出:"到底搞什么飞机啊,我C#还没来得及用好,现在又搞个F#,还让不让人活啊?"《程序员修炼之道》曾经建议我们"learn at least one new language every year",但Gustavo Duarte却对这种建议提出质疑,并宣称"learning new programming languages is often a waste of time for professional programmers"。面对这种争论,你可能会显示出某种理性:除非我有需要(学习新的语言),否则我认为够用就可以了。那么,你什么时候会有需要?回想一下你的项目经历,是否发现,有权提出这种需要的往往不是你,而是你的项目,只要项目有需要,即使是老掉牙的语言你也得学。根据马斯洛的需要层次理论,如果你的项目已经让你忙得一塌糊涂了,那么你根本不会有闲情和兴致学习新的语言,而在现今这个讲求快速见效的社会里,或许只有专门研究语言的人才支付得起学习新的语言的代价了,但我并非专门研究语言的人,至少现在不是,那么,我为何要学习新的语言呢?

我曾经在杰拉尔德·温伯格(Gerald M. Weinberg)的《咨询的奥秘——成功提出和获得建议的指南》里读到一个有趣的"锤子法则"(The Law of The Hammer):

在圣诞节收到锤子做礼物的孩子会发现每样东西都需要敲打。

读完上面这句话之后,你的脑子里想着什么?或许你已经猜到我想说什么了,工具在为使用者带来便利的同时也会约束使用者解决问题的思路和方法,编程语言直接体现了对问题的抽象和表达,不同范式的编程语言则协助程序员从不同的角度把握问题,这也正是我学习新的语言的主要原因。要有持久的学习行为,学习动机应该是指向内部的,其道理和《七个心理寓言》的"动机的寓言:孩子在为谁而玩"所说的是一样的。那么,我又为何选择F#呢?其实,这完全是因为C# 3.0,我们知道C# 3.0向函数式编程借鉴了不少,所以在学习C# 3.0的时候,我突然萌生了想了解函数式编程语言的念头,后来,在一次偶遇中,我邂逅了F#。在学习F#的过程中,我发现许多C# 3.0的新功能的"影子"(有人说C# 3.0的新功能是从F#那里借鉴过来的,是真的吗?),于是萌生了写下这篇文章的念头。

 

如何创建类型?

人们在接触新事物时通常不会抛开现有的积累,换句话说,你的知识和经验会影响你如何接受新事物。如果你是一个有使用面向对象编程语言经验的程序员,那么你第一个想问的问题很可能就是:"我如何创建类型?"

F#支持一种叫做Record Type的类型,它和C#里使用自动属性定义的类有点像:

代码 1

而Book的实例化也是非常直观的:

代码 2

F#会根据给出的属性名字以及值的类型推断出你要实例化的类型是Book。读到这里,你可能会问:"如果有两个不同的类型定义了相同的属性呢?"虽然出现这种情况的概率不大,但若真的让你碰上了,你可以使用显式语法来实例化它:

代码 3

面向对象编程的一个特征是封装,狭义的封装是指封装对象的内部状态(广义的封装则是指封装系统的变化因素),而对象的内部状态在对象的生命周期里发生改变是很常见的,但当我们试图在F# Interactive(类似于Python的交互式控制台)里修改Price属性时却报告错误("<-"用于赋值,相当于C#的"="):

图 1

为什么会这样呢?原来,在F#里,对象默认是不可变的(immutable),就像.NET的字符串那样。修改Price属性可以看作创建一个新对象,把原对象的Title、Authors和Tags属性的值复制到新对象对应的属性,并为新对象的Price属性设置新的值:

代码 4

读到这里,你可能在想:虽然现在内存很便宜了,但也不至于要用这种方法来耗啊?在面向对象编程里,拥有和维护可变的内部状态是对象的一个很重要的特征,正因为这样我们得以完成许多复杂的操作,但也正是可变的内部状态提高了并发操作的复杂程度和处理代价。泛泛而谈可变对象和不可变对象孰优孰劣是没有意义的,对于一个给定的系统,一些对象适合设计成可变的,另一些则应该考虑设计成不可变的,从而使两者达到一定的平衡。

在C#里,对象默认是可变的,但你可以通过readonly关键字使某个(些)数据"固定"下来;F#刚好相反,对象默认是不可变的,但你可以通过mutable关键字使某个(些)数据"活动"起来。如果我把Book重新定义为:

代码 5

那么修改Price属性就不会报错了。如果你决定使对象可变,那么你就应该做好并发处理的工作。什么?你的程序是单机单核单线程的?那你可以掷硬币决定对象是可变的还是不可变的。

除了Record Type,F#还支持Discriminated Union、Tuple和Constructed Class Type,有兴趣的话不妨到F# Home看看。

 

如何初始化对象?

C# 3.0引入了对象初始化器和集合初始化器,F#也提供了类似的功能。举个例子,假设我想初始化System.Windows.Forms.ListViewItem,并且设置它的Text、Selected和ToolTipText属性,我可以这样:

代码 6

F#把这个功能叫做初始属性设置(initial property settings)或者可选属性设置(optional property settings)。上面代码等效于:

代码 7

从这里可以看出,使用这个功能的前提条件是要初始化的属性必须具有set访问器。读到这里,你可能会问:"如果我要调用的构造函数是有参数的呢?"那也没问题,举个简单的例子,假设你要调用接受一个字符串作为参数的那个构造函数,你可以这样:

代码 8

或者这样:

代码 9

第一种方法就是简单地把你要初始化的属性追加到构造函数的参数后面;而第二种方法则使用了F#的命名参数(Named Argument)功能。命名参数可以放在任何位置,例如Selected和ToolTipText之间,但匿名参数就必须按顺序放在要初始化的属性前面。读到这里,你可能会问:"如果我要调用的构造函数的参数和我要初始化的属性重名了呢?"你在考验F#的忍耐力吗(笑)?当然,这种情况是有可能出现,首先,F# 不允许同一个名字出现两次,不管它是构造函数的参数的名字还是属性的名字,所以你不可能鱼与熊掌兼得(即构造函数的参数和属性同时初始化);其次,一旦出现这种情况了,F#会优先考虑构造函数的参数。

我们探讨了如何初始化一个对象,那么初始化一组对象又是怎样的呢?在F#里,说到集合类型就不得不提Microsoft.FSharp.Collections.List<'a>了("'a"是F#的类型参数表示法)。假设我要实例化一组Book对象(Book的定义参见代码1),并把它们储存在List<'a>里,我可以这样:

代码 10

列表里的每个元素通过";"分割。F#能够结合元素的类型推断出列表的完整类型,在这里是List<Book>(也可以表示为Book list)。F#的List<'a>通常只在F#里使用,如果要访问.NET的类库或者和其他语言交互,那么你通常会考虑使用数组(F#的List<'a>和数组的语法非常接近,能看出其中的区别吗?):

代码 11

而对于整数列表,F#还支持区间表达式,你可以指定起始值和终止值:

图 2

甚至指定递增值(步长):

图 3

如果你有兴趣进一步了解F#的List<'a>,可以阅读Dustin Campbell《Why I Love F#: Lists - The Basics》Chris Smith《Mastering F# Lists》

 

如何外包逻辑?

有一次,我和两个朋友到东方既白吃饭,选餐的时候,其中一个考虑了很久,终于发话了:"椰香咖喱牛肉饭可不可以不要椰香?"服务员看着我的朋友,非常不好意思地说:"这是不可以的。"看到服务员的表情,我猜她应该是苦于不知如何向一个12岁的小朋友解释"烧饭的工作遵循了一套标准化的流程,这个流程是不能随意更改的"。此时,我的朋友大概在想:同样的钱,不能加东西可以理解,为什么连减东西也不可以呢?虽然他最后还是选了椰香咖喱牛肉饭,但我猜他心里肯定觉得东方既白做得太呆板了。试想一下,如果你打算使用我提供的Sort方法排序books2数组(参见代码11),却发现这个方法只接受一个数组作为参数,你肯定会问:"我如何告诉这个方法我要根据价格进行排序?"接着,我告诉你:"不好意思,这是不可以的,这个方法会自行选择合适的排序依据。"此时,你会有什么感觉?

无可否认,我们已经进入了一个个性化的时代,用户不再像从前那样满足于你所提供的普遍适用的标准化软件,他们希望你的软件是可配置的,必要时还能够扩展,也就是可以满足他们的个性化需求。然而,把逻辑外包出去并不只是为了满足用户的个性化需求,为什么这样说?试想一下,你可不可以写出这样一个Sort方法,每次调用时都能"猜中"用户的排序依据?很明显,当我把books2数组传给Sort方法时,如果我不说,它不可能知道我想按书名排序还是按价格排序,是升序还是降序。换句话说,把逻辑外包出去其实就是把这种不稳定的因素封装起来,再转嫁给用户,然后美其名曰"用户参与",当然,由于用户认为你不是把麻烦抛给他,而是为他带来灵活性,于是造就了"双赢"。

考察System.Array.Sort方法的众多重载版本,不难发现.NET外包逻辑的两种主要方式是:委托和接口。在F#里,我们可以通过Lambda表达式向接受委托作为参数的重载版本注入逻辑(compare函数是F#提供的通用比较函数):

代码 12

当然,使用命名函数注入逻辑也是可以的:

代码 13

代码13除了向我们示范如何在F#里定义函数,还向我们展示了一个有趣的东西,留意comparePrice函数的定义,我并没有为x和y这两个参数指定类型,但F#却从函数体以及上下文推断出它们的类型是Book!

另外,F#并没有刻意区分命名函数和Lambda表达式,代码13的comparePrice函数也可以这样定义:

代码 14

代码13和代码14定义的两个comparePrice函数是等效的,使用上也没有区别,从代码14可以看出,在F#里,函数其实就是值,而我们在代码12里使用的Lambda表达式只不过是代码14定义的comparePrice函数的函数体。

Lambda表达式使你能够以一种紧凑的方式注入逻辑,但如果别人外包逻辑的方式是接口而不是委托呢?这个时候就轮到对象表达式(Object Expression)出场了:

代码 15

在这里,我通过"_"告诉F#我希望它帮我推断IComparer<'a>的类型变量,而F#也不负所托,成功推断出它的类型是Book。F#的对象表达式也算是一种匿名类型,但它和C# 3.0的匿名类型是不同的。在F#的对象表达式里,你可以实现接口的成员或者重写基类的成员,但不能添加任何新的成员;而C# 3.0的匿名类型则只允许属性的存在。

 

如何扩展类型?

假设我要把一组Book对象添加到System.Windows.Forms.ListView上,我应该怎样?对于习惯运用命令式编程方式思考问题的人,他可能会首先想到创建一个ToListViewItem函数:

代码 16

然后"foreach"那组Book对象,对每个Book对象应用ToListViewItem函数,并把函数返回的结果添加到ListView。由于ToListViewItem函数是一个和Book对象相关的操作,你也可能会考虑把它纳入Book类型的定义,使它变成Book类型的实例成员函数:

代码 17

需要说明的是,ToListViewItem成员函数前面的"b"指代当前的对象实例,相当于C#的"this"关键字和VB.NET的"Me"关键字,但因为F#没有强制使用特定的关键字,所以你可以根据具体的需要选择合适的符号,当然,你也可以通过制定命名规范强制使用特定的符号。现在,你可以"foreach"那组Book对象,对每个Book对象调用它的ToListViewItem成员函数,并把函数返回的结果添加到ListView。这个时候,可能会有人提出质疑:"Book类型本来是一个中立的数据载体,现在你在它的成员函数里使用了ListViewItem类型,无疑强化了Book类型和Windows Forms框架之间的关系,有损它本身的纯粹性。"面对这样的质疑,你有什么想法?

事实上,我们可能希望保留Book类型和ToListViewItem函数之间的"所属"关系,但这种关系会一直处于封印状态,直到我们通过某种仪式将它解封才可以使用。这个时候,我们可以考虑通过F# 的类型扩展(Type Extension)把ToListViewItem成员函数分离到一个单独的模块里(假设Book类型位于Lib命名空间里):

代码 18

这样,如果我们没有引用Ext模块,Book类型和ToListViewItem函数之间的关系就会继续保持封印状态:

图 4

而当我们在代码里引用Ext模块时,他们之间的关系就会解封:

图 5

有没有觉得F#的类型扩展和.NET Framework 3.5的扩展方法很像? 事实上,F#的类型扩展有两种形态:当类型扩展的代码和相关的类型处在相同的命名空间里时,它等效于分部类,F#把这种扩展称为固有扩展(Intrinsic Extension);而当两者处于不同的命名空间里时,它相当于扩展方法,F#把这种扩展称为可选扩展(Optional Extension)。但由于类型扩展和扩展方法在IL层面的实现方式是不同的,于是F#的类型扩展无法被C# 3.0/VB.NET 9.0识别,而C# 3.0/VB.NET 9.0的扩展方法也无法被F#识别。你可能会感到很奇怪:既然.NET 3.5已经提供了现成的实现方案,为什么F#还要另外弄一个出来呢?其实,现在的F#(1.9.4)是基于.NET Framework 2.0而不是3.5的,所以同时存在两种不同的实现方案并非有意的,不过Don Syme说将来F#会改用.NET Framework 3.5的实现方案,即代码18定义的类型扩展也能被C# 3.0/VB.NET 9.0识别。

那么,我现在是否可以在F#里定义能被C# 3.0/VB.NET 9.0识别的扩展方法?当然可以,虽然F#现在无法识别扩展方法,但这并不妨碍你在F#里定义这种方法:

代码 19

在F#里定义扩展方法的语法和在VB.NET 9.0里的语法相似,都是显式使用ExtensionAttribute的。接着,把代码编译成DLL,在C# 3.0或者VB.NET 9.0项目里引用一下就可以使用了,编译的时候记得在F#的项目属性里设置.NET Framework 3.5的相关DLL的引用。

噢,说着说着,差点忘记原本的目的了,我们做了这么多,最终还是难逃"foreach"那组Book对象,对每个对象应用变换操作,并把变换结果添加到ListView,那么,F#有没有提供更简单的方法可以用来完成这项任务呢?其实,F#更倾向于通过函数的组合来完成相关的工作:

代码 20

上面这行代码向我们揭示了数据的流动:books2是数据源,它的数据流经Array.map函数和ToListViewItem函数组合而成的变换函数,然后流向listView.Items.AddRange方法。我们也可以这样理解这行代码:用ToListViewItem函数对books2数组的每个元素做变换操作,然后把结果传给listView.Items.AddRange方法。从这行代码可以看出,运用函数式编程方式来思考这个问题,我们最初定义的ToListViewItem函数就已经足够了。

 

如何查询数据?

C# 3.0最引人注目的地方莫过于使用LINQ查询数据了,前面提到,目前的F#是基于.NET Framework 2.0的,那么它又如何查询数据呢?我们知道,IEnumerable<'a>是LINQ的核心接口,也是执行任何查询操作的必要条件。在F#里,你可以使用seq<'a>或者IEnumerable<'a>,seq<'a>是F#为IEnumerable<'a>提供的类型缩写(Type Abbreviations),相当于C++的typedef,而适用于seq<'a>的函数则位于Microsoft.FSharp.Collections.Seq模块里,例如Seq.filter函数、Seq.map函数、Seq.orderBy函数等。

假设我现在想用F#对代码10的books做一个查询,找出Tags属性里包含"F#"字眼的书,然后根据Price属性进行排序,那么我该如何做呢?

要判断某本书是否符合我的条件,可以把它的Tags属性按";"符号分割成一个字符串数组,然后判断这个数组里面是否包含"F#"字眼。要把一个字符串按指定的符号分割成一个字符串数组,可以使用System.String.Split实例方法,但要判断一个集合是否包含指定的元素,除了通过Lambda表达式,似乎没有更加直接的方法,所以我仿照System.Linq.Enumerable.Contains方法定义了一个contains函数:

代码 21

contains函数使用了Seq.exists函数,并且通过Lambda表达式告知判断条件为是否相等。你可能会感到很奇怪:为什么没有给contains函数的参数指定类型却可以通过编译?如果这个代码是合法的,那么value和source参数的类型是什么?当F#的编译器看到这段代码时,它发现value和source参数将会用作Seq.exists函数的参数,于是便试图从Seq.exists函数的签名推断value和source参数的类型,由于Seq.exists函数是一个泛型函数,而我们又没有在定义contains函数时给出进一步的约束,于是便断定contains函数也是一个泛型函数,并自动为value和source参数添加类型参数, F#把这个过程叫做自动泛型化(automatic generalization)。另外,你也可能感到奇怪:contains函数的参数顺序和Enumerable.Contains方法恰好相反,为什么呢?我们知道, Enumerable.Contains方法把表示集合的参数放在第一个位置是为了满足扩展方法的要求;而我在这里把表示集合的参数放在contains函数的参数列表的最后一个位置则是为了满足"|>"运算符的要求。我们在代码20已经见识过"|>"运算符了,它的作用是可以把目标函数的最后一个参数提到运算符的前面,换句话说,如果我要判断coll集合里是否包含elem元素,contains函数就可以这样用:coll |> contains elem。如果你有兴趣进一步了解"|>"运算符,可以阅读Brian《Pipelining in F#》

有了上面的准备,我们就可以开始查询数据了:

代码 22

Seq.filter函数、Seq.map函数和Seq.orderBy函数分别相当于Enumerable.Where方法、Enumerable.Select方法和Enumerable.OrderBy方法。如果我们把Seq.filter函数、Seq.map函数和Seq.orderBy函数分别定义为where函数、select函数和orderby函数:

代码 23

那么代码22就可以写成这样了:

代码 24

我们来看看对应的C# 3.0代码:

代码 25

是否感到有点喜出望外?什么?感到很失望?因为我写了一个多余的select?囧。。。

读到这里,你可能会问:"如果我只想获取Title和Price属性呢?"这个时候就轮到F#的Tuple类型出场了:

代码 26

读到这里,你可能会问:"如果我想从q里提取所有的书名,生成一个新的集合呢?"你可以通过select函数做到,但现在我想换个玩法,试一下F#的序列表达式(Sequence Expression):

代码 27

我们知道,q里的每个元素都是包含两个数据的Tuple类型,也就是说,每个元素都能匹配"(a, b)"模式,其中,书名会匹配到a,而价格则匹配到b,但由于我只关心书名,于是在b的位置上使用"_",表明我不关心b位置的数据。同样地,如果我想从q里提出所有的价格,然后对它们求和,我可以这样:

代码 28

如果你读过我的《我眼中的C# 3.0》,你应该会记得C# 3.0还提供了字典初始化语法,那么,F#是否也支持类似的语法?很遗憾,不支持,至少目前还没看到这种语法,然而,要在F#里把List<'a>变成Map<'key, 'a>却是非常容易的:

代码 29

上面这句话可以这样理解:把books按照"fun b -> (b.Title, b)"方法进行映射,然后把所得结果用作Map.of_list函数的输入。

 

业余研究语言的人

我们经常使用编程语言,但我们是否曾经停下来想一下:编程语言究竟是什么?或许对你来说,编程语言只不过是用来编写程序的一种工具,所以根本用不着耗费心思去想这个问题,但对我来说,它并非只是一种工具。我有一个好朋友很喜欢研究股票市场,她说通过股票市场可以看到人性的种种;而我则喜欢研究编程语言,因为通过编程语言可以了解设计者和使用者的思维方式,就像其他研究语言的人通过自然语言可以了解使用者的种群文化一样。

当一种新的编程语言出现并且得到很多受众的支持时,可能就会有人出来说某种旧的编程语言要被取代,甚至宣称这种旧的编程语言的消亡,与此同时,也会有人站出来,对新的编程语言的必要性提出种种质疑……。没有人希望自己选择的编程语言失去活力,当你选择一种编程语言时,其实就接受这种编程语言背后的世界观,所以你会誓死捍卫你的选择,无怪乎每次编程语言之间的优劣争论都可以上升到宗教信仰的程度。面对这类争论,我觉得optionsScalper的态度比较实际(原贴):

I tend not to think of "vs." when doing this type of work. F#, C#, C++ and others are nothing more than tools. Used well, each is capable of yielding great results.

今天,我因为C# 3.0踏进了F#的大门;明天,我会因为C# 4.0踏进谁的大门呢?无论答案是什么,可能都是很久以后的事了……

Tag标签: F#,C# 3.0
posted @ 2008-07-25 19:18 Allen Lee 阅读(2844) 评论(100)  编辑 收藏 所属分类: F#

  回复  引用  查看    
#1楼 2008-07-25 19:26 | 真见      
踩了在看。
  回复  引用  查看    
#2楼 2008-07-25 19:36 | kkun      
看完灯展回来再慢慢欣赏,F#
  回复  引用  查看    
#3楼 2008-07-25 19:37 | 真见      
我迫切想知道,FSharp跟CSharp以后那个是.Net上的一等公民。FSharp能做什么,写WebForm,WinForm?能否做出C#,C++作出的所有事情。。望楼主给个回复参考。
  回复  引用  查看    
#4楼 2008-07-25 19:37 | works guo      
顶。。
  回复  引用  查看    
#5楼 [楼主]2008-07-25 19:37 | Allen Lee      
@kkun
有灯展看这么好?
  回复  引用  查看    
#6楼 2008-07-25 19:38 | Martin(高超)      
很好,很强大
  回复  引用  查看    
#7楼 2008-07-25 19:45 | prime.li      
@真见
F#也是基于CLR的,你说它可以做C#的事情么?
  回复  引用  查看    
#8楼 2008-07-25 19:45 | 包建强      
此处下载《F#》:
http://forums.quanpc.com/14575/EJB.aspx


  回复  引用  查看    
#9楼 2008-07-25 19:51 | prime.li      
对F#不熟,不过这样的写法貌似不是MS原创。可以在Ruby,python语言里面找到相应的影子。
还有,C#和F#没有谁代替谁的问题,他们各自适合自己的开发特点。
楼主很先进啊。我现在不期盼C#4带来什么变化,只是希望CLR能更新一下。直接到CLR4.0??我预感下个版本VS2009可能带来CLR的升级。
  回复  引用  查看    
#10楼 2008-07-25 20:11 | Anders Cui      
鼎力支持!
  回复  引用  查看    
#11楼 [楼主]2008-07-25 20:14 | Allen Lee      
@真见
你这么快就看完这篇文章啦?
  回复  引用  查看    
#12楼 [楼主]2008-07-25 20:14 | Allen Lee      
@Martin(高超)
@Anders Cui
谢谢!
  回复  引用  查看    
#13楼 [楼主]2008-07-25 20:16 | Allen Lee      
@包建强
这本书确实不错,但如果觉得这本书有点深,可以先阅读《Foundations of F#》。
  回复  引用  查看    
#14楼 2008-07-25 20:18 | 横刀天笑      
IBM developerWorks里有一个编程边界的系列,作者就的意图就是从其他语言学习,然后看看能给Java语言什么教益,反观.net社区,相似的场景却很少出现,LZ好文
  回复  引用  查看    
#15楼 [楼主]2008-07-25 20:23 | Allen Lee      
@prime.li
F#借鉴了OCaml的语法。
  回复  引用    
#16楼 2008-07-25 20:48 | mosiac [未注册用户]
@横刀天笑

很好的实践,如果一个.net developer能够静下心来学习java,那么他将会明白很多东西
  回复  引用  查看    
#17楼 2008-07-25 21:33 | 包建强      
@mosiac
我不赞同。java技术有四书五经之说,哪有那么多精力分心研究。一套.NET能想明白,就很不容易了。
  回复  引用  查看    
#18楼 2008-07-25 22:00 | Rivers Zhao      
我觉得学F#还不如把javascript学精一些
  回复  引用  查看    
#19楼 2008-07-25 22:06 | chzhcpu      
博主行文流畅,旁征博引,各种典故,顺手拈来,但又毫无牵强之意,读来令人爽快,好文,好才。
  回复  引用  查看    
#20楼 [楼主]2008-07-25 22:06 | Allen Lee      
@Rivers Zhao
Javascript我是一点都不懂啊,所以也谈不上把它学精。
  回复  引用  查看    
#21楼 [楼主]2008-07-25 22:08 | Allen Lee      
@chzhcpu
能让你有这么好的阅读体验,真不枉我花了两个星期来写这篇文章啊。
  回复  引用  查看    
#22楼 2008-07-25 22:15 | Justin      
好文好文!!!
  回复  引用  查看    
#23楼 [楼主]2008-07-25 22:19 | Allen Lee      
@Justin
谢谢!
  回复  引用  查看    
#24楼 2008-07-25 22:29 | SuperWulei      
介绍J#的文章似乎不多,楼主的这篇文章介绍的虽然不全面,但很细致啊。不过我本人觉得学习那么多语言不是必要的,研究的目的是“满足主人的精神需求”。
  回复  引用  查看    
#25楼 [楼主]2008-07-25 22:30 | Allen Lee      
@SuperWulei
这篇文章是关于F#而不是J#的~~~再者,一篇文章是不可能涵盖F#的方方面面的,这篇文章仅仅涉及C# 3.0和F#的一些相似之处而已。
  回复  引用  查看    
#26楼 2008-07-25 22:31 | 阿武      
喜欢LZ的最后那一段话
  回复  引用  查看    
#27楼 [楼主]2008-07-25 22:33 | Allen Lee      
@阿武
最后那段话,你是指下面这段?

“今天,我因为C# 3.0踏进了F#的大门;明天,我会因为C# 4.0踏进谁的大门呢?无论答案是什么,可能都是很久以后的事了……”
  回复  引用  查看    
#28楼 2008-07-25 22:42 | dawave      
楼主好文!

个人感觉函数式语言是未来语言的方向,只是现在的程序员基本都被对象式或者过程式语言框住了。但是如果我们从现在开始打基础,下一代程序员应该可以象今天他们的前辈们使用OOP一样地使用F#, Payton,甚至sheme和lisp。

奥运来了,

LZ加油!写出更多F#好文

年轻的程序员们加油!如果在今天掌握了函数式语言,那你们就是明天程序员世界的大拿!

  回复  引用  查看    
#29楼 [楼主]2008-07-25 22:48 | Allen Lee      
@dawave
Payton?还是Python?
  回复  引用  查看    
#30楼 2008-07-25 22:54 | dawave      
@Allen Lee
typo
  回复  引用  查看    
#31楼 2008-07-25 22:56 | xjb      
我还是专注c#吧
  回复  引用  查看    
#32楼 [楼主]2008-07-25 23:03 | Allen Lee      
@dawave
typo是什么?
  回复  引用  查看    
#33楼 [楼主]2008-07-25 23:04 | Allen Lee      
@xjb
这很好啊,加油啦~~~
  回复  引用  查看    
#34楼 2008-07-25 23:06 | 银河      
好长的文章。
收藏起来慢慢看。

  回复  引用  查看    
#35楼 2008-07-25 23:29 | 横刀天笑      
@包建强
我觉得.net也是一样,要在技术上更好提升光关注.net一门还是不够的,.net家族虽然成员之多,但是风格却相同,时不时的画个周吧的时间看看其他语言的东西,却是很有益处的,将其他语言的特点吸引过来。比如RubyOnRails处理模板的做法,我看了后,后来某一个项目中很自然的采用了asp.net handler+json+javascript这样的一个架构,页面上的数据绑定都实现自动化。这样吸取别的语言的长处为我所用。
个人愚见。


  回复  引用    
#36楼 2008-07-25 23:30 | yesun [未注册用户]
垃圾
  回复  引用  查看    
#37楼 [楼主]2008-07-25 23:36 | Allen Lee      
@yesun
你是来生事端的吗?
  回复  引用  查看    
#38楼 2008-07-25 23:37 | Angel Lucifer      
说实话,俺不看好 F# 的前途。它虽然跟 C# 一样是 CLR 一等公民,但考虑到由于 C-like 语言的遗留资源,实在是怀疑此语言能够大规模普及。
  回复  引用    
#39楼 2008-07-26 00:07 | lucklier [未注册用户]
http://www.fenglog.com/blog/article.asp?id=350
冒昧说说从您的文章中的一些东西的感悟,拙见见笑了。
  回复  引用  查看    
#40楼 2008-07-26 00:09 | 朱扬谷      
Function Programming 确实感觉很强。 F# 应该值得去了解。
  回复  引用  查看    
#41楼 2008-07-26 02:00 | sumer      
ofp 和 oop各有所长吧,F#并不是无中生有用来替代C#的。
F#应该是一些算法密集型程序的选择,感觉是在做代数题,
所以这个语言和我们应该关系不大,它是“数学家”的语言,
可惜中国“数学家”的土壤不够肥沃。
让那些研究核弹爆炸,天体运行,分子结构的人都来到.net不好么?
用C#容易画出一个苹果和一个地球,用F#更容易写个万有引力公式。
我第一次听说F#,但我从楼主的介绍中得出以上结论,纯属个人愚见。
  回复  引用  查看    
#42楼 [楼主]2008-07-26 05:51 | Allen Lee      
@Angel Lucifer
每个人都会有自己的选择,能够选择自己认为有前途的东西是一种福气。选择你认为有前途的编程语言吧,尽可能多地和它接触,最终你会发现一些东西的 :)
  回复  引用  查看    
#43楼 2008-07-26 05:57 | 怪怪      
呵呵, 支持一个~

对于F#,我不满意的地方在于它仍然使用传统的类型系统。

还有就是, 它名分还没正, 就已经太复杂了... 除了你文中介绍的内容, 再加上匹配那一部分和其它一些细节, 说实话, 即便我作为半个冒险者也望而却步....
  回复  引用  查看    
#44楼 [楼主]2008-07-26 06:00 | Allen Lee      
@lucklier
看了你的文章,如果一篇文章能引起读者的一些思考,即使没有把文章全部看完,我想也是对作者很好的鼓励了,看来你找到我在这篇文章里其中两个比较花心思写的地方了 :)
  回复  引用  查看    
#45楼 [楼主]2008-07-26 06:10 | Allen Lee      
@怪怪
作为一种基于CLR的语言,F#必定会使用CTS,或许IronScheme更能引起你的兴趣,它和IronPython一样使用了DLR,L#可能也是一种选择,它也曾经计划使用DLR,不知道现在什么状态。

至于F#的名分,Microsoft已经决定将它产品化了,相信在下一个版本的Visual Studio里亮相。至于F#的模式匹配(Pattern Matching),这是它其中一大亮点,如果你对它有一个完整的了解的话,相信你会被它吸引住的。
  回复  引用  查看    
#46楼 2008-07-26 06:17 | 怪怪      
@Allen Lee
我是被它吸引住了, 就是被传统的类型系统(不是指底层实现,而是指表达层面)给把热情浇灭了...; 但是我也不赞成动态语言的方式解决这个问题。 所以我的打算是观望一阵,再不出现我想要的东西, 我就自己动手, 丰衣足食了。

不过我确实应该再重新体会一下匹配这块,毕竟是近两年语言改进中比较少见的东西, F#我印象里是开源的吧? 其实我还想尝试的还有Boo, 可惜精力有点不够用了。
  回复  引用  查看    
#47楼 2008-07-26 06:20 | 怪怪      
不过, 如果F#真的进入VS, 同时: 1. C#没有大的变化; 2. 我自己没啥动静, 那我可能就改用F#了。
  回复  引用  查看    
#48楼 [楼主]2008-07-26 06:21 | Allen Lee      
@怪怪
目前从F#官方下载到的安装包是包含源代码的,似乎这是因为现阶段F# Team推荐通过静态连接编译F#项目,貌似F#并非开源项目~~~
  回复  引用  查看    
#49楼 [楼主]2008-07-26 06:22 | Allen Lee      
@怪怪
C#会有变化的,你没看那个C# 4.0面谈视频么?
  回复  引用  查看    
#50楼 [楼主]2008-07-26 06:24 | Allen Lee      
@sumer
你的回复让我想起之前在hubFS.net上看到的一篇帖子《Are functional programmers normal? :)》(http://cs.hubfs.net/forums/thread/3279.aspx):P
  回复  引用  查看    
#51楼 [楼主]2008-07-26 06:33 | Allen Lee      
@怪怪
“表达层面的传统的类型系统”?怎么说?
  回复  引用    
#52楼 2008-07-26 08:52 | zdf [未注册用户]
跟着微软好累呀
  回复  引用  查看    
#53楼 2008-07-26 08:53 | 留恋星空      
超级变变变.
  回复  引用  查看    
#54楼 [楼主]2008-07-26 09:02 | Allen Lee      
@zdf
那就不要跟着微软走,跟着自己的心走就好了 :)
  回复  引用  查看    
#55楼 [楼主]2008-07-26 09:02 | Allen Lee      
@留恋星空
变形金刚?
  回复  引用  查看    
#56楼 2008-07-26 09:22 | 戏水      
内容详实 ,行文流畅 , 毋庸置疑的好文

末学对函数式编程语言不甚了解, 您的这篇文章给我很大帮助 ,非常感谢。
希望能继续写一些应用F#解决实际问题的例子。
  回复  引用  查看    
#57楼 [楼主]2008-07-26 09:57 | Allen Lee      
@戏水
见笑了,我学F#并非为了用它取代C#完成我平时的事情,而是希望在思考问题的时候能多有一个不同的角度而已 :)

不过,将来如果有一些好的F#想法也会在这里分享的。
  回复  引用  查看    
#58楼 2008-07-26 10:17 | dawave      
typo: 拼写错误
  回复  引用  查看    
#59楼 2008-07-26 10:42 | 小杰      
既然全部代码都用了简化语法. 不如一开始说一下 #light .
  回复  引用  查看    
#60楼 2008-07-26 11:16 | mikelij      
F#没有什么意思. 只不过微软想霸天下的一个企图. 讨好某些开发人员而已.
  回复  引用  查看    
#61楼 2008-07-26 13:18 | lvxuwen      
写的非常不错,最近也要学习F#,希望博主能够写一个系列
  回复  引用  查看    
#62楼 2008-07-26 15:28 | 斯克迪亚      
F#是函数式编程,F#与C#就类似唯物主义与唯心主义一样,用不同的方式解释这个世界,用不同的理念支持自己的行为,各位可以搜索一下函数式编程的相关理论文章了解到。
  回复  引用  查看    
#63楼 2008-07-26 15:30 | 斯克迪亚      
C#的Lamada表达式即是由函数式编程引进的技术
  回复  引用  查看    
#64楼 2008-07-26 16:51 | AndyHai      
OMG,这还是编程么?我觉得的我大脑的沟回开始不够用了……
  回复  引用    
#65楼 2008-07-26 17:18 | zzzvvv [未注册用户]
SICP,做题做得一把鼻涕一把泪
  回复  引用  查看