2017-02-23 118 views
15

所以我碰到这个旅游F#的跑:https://docs.microsoft.com/en-us/dotnet/articles/fsharp/tourF#功能VS C# “功能” 蒸发散

...男孩你好是F#有趣!游览的最初阶段定义了一个示例函数,它看起来非常简单:

/// You use 'let' to define a function. This one accepts an integer argument and returns an integer. 
/// Parentheses are optional for function arguments, except for when you use an explicit type annotation. 
let sampleFunction1 x = x*x + 3 

所以这对我有意义。它定义了功能是什么,所以如果我是通过一些数字到这个东西,它的广场,并增加了3到这一结果,通过巡视的下一行所见:

/// Apply the function, naming the function return result using 'let'. 
/// The variable type is inferred from the function return type. 
let result1 = sampleFunction1 4573 

给这几个后思考更多的时间,我想出了C#可以做到这一点的结论!我确实很喜欢C#。这看起来像在C#上面有哪些,据我可以告诉:

 Func<int, int> sampleFunction1 = x => x*x + 3; 
     var result = sampleFunction1(4573); 

所以我的主要问题是,是什么之间我在C#写的什么F#的游向我展示了有什么区别?子问题是:即使它是相同的CLR,IL代码是否有任何不同?我将通过C#使用F#的几个原因是什么?

+2

只因为编译器使用完全不同的语言,因此有不同的优化,解释,翻译等,IL可能会有所不同。您需要找到熟悉这两种语言的人,以确切地告诉您但是使用IL反汇编工具(如[ILSpy](http://ilspy.net/)),您可以轻松打开可执行文件/ DLL并自行探索。 – Abion47

+1

你不会注意到一个班轮的功能有很大的不同。实际上,.NET BCL的许多调用在C#和F#中都会完全相同。但是,如果您构建更复杂的东西,您将从语法和结构的角度开始看到F#的优点。特别是如果你想要离开OO范例并减少项目中的可变(移动)部分。 – s952163

回答

27

从技术上讲,这些是等同的。 IL可能有点不同,只是因为它们是不同的编译器,但并不多。本质上这些都是以相同的方式编译的。

但是C#不能做刚好那。你有没有注意到你前面写了Func<int,int>?但这只是一个非常小的玩具功能。更实际的情况会发生什么?观察:

// F# 
let f x m = Map.find (x, x+1) m |> Seq.map ((+) 1) 

// C# 
Func<int, IDictionary<Tuple<int, int>, IEnumerable<int>>, IEnumerable<int>> f = (x, m) => m[Tuple.Create(x, x+1)].Select(i => i+1); 

很好玩,不是吗?
这被称为“类型推断”。如在F#中能够根据使用的东西推断推断类型的东西。您几乎可以编写完整的程序,并且永远不会使用类型注释。 C#也有这个,在一定程度上。这就是我能够打电话给.Select(i => i+1)的原因,而C#知道iint,因为.Select之前发生的任何事情都是IEnumerable<int>。但它非常有限,几乎没有那么强大。

类型推断只是一个 F#的许多好处。我选择了它,因为你看着它而没有看到它。但还有更多。编译顺序,缺少空值,默认为不变性,代数数据类型,自动卷曲和部分应用......实际上,比适合SO的答案更重要。

那些希望发现一般功能编程和F#的精彩和令人兴奋的世界的人,我通常会马上发送到https://fsharpforfunandprofit.com/,转到Wlaschin先生善良且有能力的手中。一个美妙的资源,阅读一切。

+2

我注意到巡演中的不变性,我非常喜欢这个!我也喜欢你的例子,说明C#中func的外观。您对C#7中的新Tuple元素如何改变有何看法? –

+4

不多。它会使类型符号缩短一些,但是你仍然需要编写它。使用C#的事情是,无论它获得多少闪亮的特性,都无法解决一些基本问题(例如空值,可变性)而不破坏旧代码。如果你打破旧的代码,那么这是一种新的语言,在这种情况下,你可以移动到F#。 –

+3

我认为部分应用程序在答案中应该有更多的覆盖范围。 OP使用'let sampleFunction1 x = ...'而不是'let sampleFunction1 xy = ...'作为例子是纯粹的意外事件,并且C#相当于后者将是'Func >而不是'Func '绝对是值得注意的,至少可以说。 – ildjarn