Allen Lee's Magic

这里没有答案,顶多给你几个值得一试的猜想。

从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标签: C# 3.0,F#

posted on 2008-07-25 19:18 Allen Lee 阅读(4901) 评论(104)  编辑 收藏 网摘 所属分类: 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,做题做得一把鼻涕一把泪   回复  引用    

#66楼 [楼主] 2008-07-26 19:11 Allen Lee      

@小杰
看来你对F#还是了解不少嘛。我想这篇文章的大多数读者都没怎么了解过F#,如果一开始就告诉他们F#支持轻量级(简写)和重量级(完整)两种语法,不知道他们会有什么感觉呢?我没有想过通过这篇文章让我的读者进入F#的大门,相反,如果某些读者看了这篇文章后对F#产生哪怕只有一点儿兴趣,那么我相信他们会找到更好的入门资料的。无论如何,我还是很感谢你在这里提出这点。
  回复  引用  查看    

#67楼 [楼主] 2008-07-26 19:17 Allen Lee      

@mikelij
这么看来,你并不喜欢F#,你大可以继续使用你喜欢的语言,为何非得把F#和所谓的微软的企图关联起来呢?
  回复  引用  查看    

#68楼 [楼主] 2008-07-26 19:23 Allen Lee      

@AndyHai
呵呵,还记得我第一次看到F#的语法时,差点儿晕过去了~~~
  回复  引用  查看    

#69楼 [楼主] 2008-07-26 19:24 Allen Lee      

@zzzvvv
找个开发环境玩一下吧,老是做这种题的话右脑会加速退化的~~~
  回复  引用  查看    

#70楼 [楼主] 2008-07-26 19:52 Allen Lee      

@lvxuwen
与其等我写的,不如我给你推荐一些系列文章吧:
1、Chris Smith的《F# in 20 Minutes》:http://blogs.msdn.com/chrsmith/archive/2008/05/02/f-in-20-minutes-part-i.aspx
2、Matthew Podwysocki的《Adventures in F#》:http://weblogs.asp.net/podwysocki/archive/2008/03/17/adventures-in-f-f-101-part-1.aspx
  回复  引用  查看    

#71楼  2008-07-26 20:08 银河使者      

不管是F#,还是Z#,只要感兴趣,就可以学一学,不一定在实际项目中用,但可以吸收一下新的思想。 记得是哪位大师说过,建议每三个月学一门新语言,不一定精通,但至少可以感受一下计算机科学的快速发展的IT界的飞速变化。 当然,这样也会调节一下单一技术给我们带来的枯燥乏味。 外面的世界总是好的。   回复  引用  查看    

#72楼 [楼主] 2008-07-26 20:44 Allen Lee      

@银河使者
说得好 :)
  回复  引用  查看    

#73楼  2008-07-26 23:47 曲滨*銘龘鶽      

哎:人生最痛苦的事情就是搞不清楚

什么应该放下;什么不能放下;
  回复  引用  查看    

#74楼 [楼主] 2008-07-27 08:54 Allen Lee      

@曲滨*銘龘鶽
呵呵,就我所知,很多做出这种感叹的人背后的真正问题是:理性上明知要放下,感性上却欲罢不能。你觉得呢?
  回复  引用  查看    

#75楼  2008-07-27 09:51 银河使者      

没错,坚持不难,放弃就更容易了,难就难在什么时候应该放弃,什么时候应该坚持。 暂且就把她称为“坚持和放弃的智慧”吧。 这也是一个成功才必须具备的条件之一。 就象炒股,如果把握好什么时候该抛,什么该进,一定会赚钱,否则,后果是不可想象的。   回复  引用  查看    

#76楼 [楼主] 2008-07-27 14:17 Allen Lee      

@银河使者
炒股的话不好说,不会是你被套牢了吧?
  回复  引用  查看    

#77楼  2008-07-28 08:32 安眠花      

F#更适合搞科学工程的人使用。

一般的程序员,像我,有C#就足够了
  回复  引用  查看    

#78楼 [楼主] 2008-07-28 14:05 Allen Lee      

@安眠花
选择你认为适合你的来用就行啦 :)
  回复  引用  查看    

#79楼  2008-07-28 16:21 共同学习,共同进步      

the most important thing for programmer is the thinking.
the best way is that we can extract the valueable knowledge from latest tech.

@Allen Lee
"理性上明知要放下,感性上却欲罢不能" where did you get it.
  回复  引用  查看    

#80楼 [楼主] 2008-07-28 18:27 Allen Lee      

@共同学习,共同进步
What do you mean by 'where did you get it'?
  回复  引用  查看    

#81楼  2008-07-28 18:50 共同学习,共同进步      

@Allen Lee
I mean where did you get this sentence . I think it's very meanful..
  回复  引用  查看    

#82楼 [楼主] 2008-07-28 18:52 Allen Lee      

@共同学习,共同进步
实不相瞒,此话出自鄙人之口,若有雷同,纯属巧合~~~
  回复  引用  查看    

#83楼  2008-07-30 10:38 JacksonLin      

F# 如果是函数式编程
C# 是oop编程
什么语言也好,对程序员关心的只是它节省了多小时间.可扩展还怎么样.
语言不分生死存亡,就存在互相补足.

人的语言能表达清楚.意思从一个人到另一个人.
首先有上下文,接着就是语言的构建.
人的语言好比函数式编程.
函数式能表示oo就像lamba.类似switch语法.
加上IDE智能提示.
文档就是程序,程序生成代码(moss,linq).所有就变得人性化(类似人的交流).

为什么这么做是趋向.
1.UI就是人性化,为什么我们须要美工.
2.产品都人性化提高更好服务.
3.它的确是提高生产力

说在后
ms的F#只是战略一步.linq发展趋使dsl发展.F#语法期望不久会出新版本.
但可能会是C# 4.0而非F# 2.0
无论如何类似新功能moss都首先应用.(moss收钱的)
开发者想享有这种语法除非java竞争对手出了,
或者这种人开源人员share了部分核心就像NBear与linq同父异母.
所以程序员还是要靠自己.






  回复  引用  查看    

#84楼  2008-07-30 11:50 JacksonLin      

对.还有一点.
很久前还有人提出过一个问题.
如上述真能实现.

那么需求变更,测试控制又会怎么样呢?
  回复  引用  查看    

#85楼  2008-07-30 11:54 jasmineou      

如果楼主将program作为一种兴趣去学习的话,这也算是比较有意义,身处其中才能感受到这时代的进步...

另外,我深信一种技术要成为主流或者广被人采用,并不是取决于这个技术本身的好坏,而是取决于这个时代需不需要它,或者说这个时代对它有多眷顾。
  回复  引用  查看    

#86楼  2008-07-31 08:11 colder [未注册用户]

传说中的绝世好文

在这个中文资料稀缺的时候
能够站在C#3.0的角度如此细致的诠释F# 真是难得

我从今年3月开始学习和使用F#
不过我是从其他函数式语言转过来的
甚至对.NET都不太了解的情况下就开始了F#的学习
一开始语法上倒是很顺手
但是对于type却一直是不明了

看了博主的好文
总算又了解的通透了些

Brian正在透露一些产品化的细节
说是夏末会发布
真的很期待 因为有太多的问题等着看最终答案
不知道C#中的partial在F#中是否用type ... with实现
F#的模板会更加OP还是更加FP
标准的语法格式化后是怎么一个样子
  回复  引用    

#87楼 [楼主] 2008-07-31 19:44 Allen Lee      

@colder
这么看来我们的视角刚好互补,以后多多交流啊!
  回复  引用  查看    

#88楼  2008-08-01 15:04 colder [未注册用户]

@Allen Lee

你是 MVP, 还请多指教!
不过有更多的人关注 F#, 我觉得还是好事.

在很多地方, 总会有人问我, F# 是什么? 有什么优势?
我只能回答:"是 C# 的弟弟, 给左撇子设计的语言, 呵呵~"

这是我能想到的最好的比喻.
一家中的老大和老幺总是性格迥异;
而且 F# 好像从没想过要抢得江山半壁.

我觉得绝大部分打听 F# 的人是担心 C# 被取代. 而在我看来, F# 是给那些因为思维方式与类C语言不入流的人一个步入.NET的机会.
  回复  引用    

#89楼 [楼主] 2008-08-01 20:31 Allen Lee      

@colder
你太谦虚了,在FP方面我还是个新手,有很多东西要向你学习呢!

另外,就目前而言,如果你喜欢F#又看好它的话,我建议你尽量避开不必要的争论,把战略目标定在提升F#的能力上(看你博客上的文章,F#还用得挺得心应手的嘛),找些志同道合的人一起研究讨论感兴趣的方面。:)
  回复  引用  查看    

#90楼  2008-08-02 15:10 fox23      

一直比较忙,今天上来认真看完了本文, 的确是精心构思的好文章!可以当作是F#中文版的UM了, 期待Allen的每一篇大作~
Best Regards,

Freesc Huang
  回复  引用  查看    

#91楼  2008-08-02 15:14 fox23      

在F#还在MSR的时候我就尝试过它, 它的诞生不是要取代什么,也不是要成就什么,只是让.NET 程序员多了一个武器而已,你可以用带了实现高效的WPF程序,BI程序,财务计算等.很赞同这句话:
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.

Best regards,

Freesc Huang

--引用--------------------------------------------------
colder: @Allen Lee

你是 MVP, 还请多指教!
不过有更多的人关注 F#, 我觉得还是好事.

在很多地方, 总会有人问我, F# 是什么? 有什么优势?
我只能回答:&quot;是 C# 的弟弟, 给左撇子设计的语言, 呵呵~&quot;

这是我能想到的最好的比喻.
一家中的老大和老幺总是性格迥异;
而且 F# 好像从没想过要抢得江山半壁.

我觉得绝大部分打听 F# 的人是担心 C# 被取代. 而在我看来, F# 是给那些因为思维方式与类C语言不入流的人一个步入.NET的机会.
--------------------------------------------------------
  回复  引用  查看    

#92楼 [楼主] 2008-08-02 16:00 Allen Lee      

@fox23

--引用--------------------------------------------------
fox23: 在F#还在MSR的时候我就尝试过它, 它的诞生不是要取代什么,也不是要成就什么,只是让.NET 程序员多了一个武器而已
--------------------------------------------------------

很高兴你能有此番认识 :)
  回复  引用  查看    

#93楼  2008-08-03 00:25 fox23      

@Allen Lee
:-)
顺便我也提供一个F#入门的链接:
http://msdn.microsoft.com/zh-cn/magazine/cc164244.aspx
不过个人还是比较喜欢Allen的这篇;)
  回复  引用  查看    

#94楼 [楼主] 2008-08-03 08:25 Allen Lee      

@fox23
多看几篇不是坏事,我现在到处找F#的文章看 :)
  回复  引用  查看    

#95楼  2008-08-03 23:28 dk [未注册用户]

楼主很用心,赞一个!   回复  引用    

#96楼 [楼主] 2008-08-04 07:37 Allen Lee      

@dk
谢谢!
  回复  引用  查看    

#97楼  2008-08-05 20:29 virus      

好像和linq to差不多啊
越来越对象化了
  回复  引用  查看    

#98楼 [楼主] 2008-08-06 08:05 Allen Lee      

@virus
你有这种感觉是很正常的,因为这篇文章就是讲C# 3.0的新特性在F#里面是如何体现的,所以在这里呈现的F#给人的感觉就有点偏向于面向对象了。
  回复  引用  查看    

#99楼  2008-08-07 11:25 J [未注册用户]

切片太囧了   回复  引用    

#100楼 [楼主] 2008-08-07 16:56 Allen Lee      

@ J
你的话啥意思呢?
  回复  引用  查看    

#101楼  2008-09-08 11:27 BlackTear [未注册用户]

Function Programming 出现得很早,但是最近才刚刚进入人们的视线。推荐博主也研究一下其他的FP语言,像Erlang,LISP什么的。   回复  引用    

#102楼 [楼主] 2008-09-09 23:04 Allen Lee      

@BlackTear
有机会的话我会去看看的 :)
  回复  引用  查看    

#103楼  2009-01-06 10:14 @xz [未注册用户]

f#我关注了一段时间,几个版本的安装包也装过。

语法倒不是什么大问题。关键是ide的支持还是有很大的问题。

微软说vs2010将正式包含f#,希望那个时候ide的支持能够彻底完善一下
  回复  引用    

#104楼  2009-01-20 16:16 Rexzhou [未注册用户]

去了解了一下lambda表达式和函数编程的数学基础,被深深的震撼。看来要去学习大学时很鄙视的离散数学之类的数学知识了。   回复  引用    


发表评论
姓名 [登录] [注册] 
主页
Email (仅博主可见) 
验证码 *  验证码看不清,换一张
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论   新用户注册   返回页首      

导航: 网站首页 社区 新闻 博问 闪存 网摘 招聘 .NET频道 知识库 找找看 Google站内搜索



China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
China-Pub 计算机绝版图书按需印刷服务

相关文章:

相关链接: