作为此处评论讨论的结果,我想知道您是否可以学习C语言中的函数式编程?
作为此处评论讨论的结果,我想知道您是否可以学习C语言中的函数式编程?
Answers:
显然,您可以使用C 进行函数式编程。从理论上讲,您还可以学习使用C进行函数式编程的原理,但是这种语言并不容易。
我假设您至少有一些OOP背景知识;如果这样做,您应该意识到OOP可以在C语言中完成,包括多态性,getter / setter,可见性规则等,但是这样做非常痛苦,而且您需要在内部了解OOP和C语言,拿出来。与FP几乎相同。
您应该做的是首先学习一种函数式编程语言(其中大多数具有令人惊讶的简单语法规则;不是使它们难以学习的语法),然后让您新获得的智慧影响您编写C的方式。
根据要求,您可以从FP中学习一些内容,然后将其应用到C,C ++或Java中:
可以破解C提供一些功能概念:
这个StackOverflow问题将告诉您更多信息。但是,尽管似乎可以用C进行函数式编程(或其中的很大一部分),但是黑客和编译器扩展以及任何并非学习概念的最佳方法。
要真正学习函数式编程,最好的选择就是著名的函数式编程语言之一,例如Lisp及其方言(Clojure,Scheme),Erlang和Haskell。这些工具中的任何一种都是在功能性编程思想中起作用的完美工具。 如果您具有.Net背景,F#也是一个不错的选择,但是它是一种多范式语言,而不是严格的功能编程语言。
正如tdammers在评论中指出的:
实际上,LISP,clojure和scheme也是多范式。Haskell虽然纯净且默认是惰性的,但它也允许在单子上下文中进行命令式编程,并且它对并发处理具有广泛的支持。所有这些机制都实现了OOP世界中所收集的大部分智慧,包括封装,继承,单一职责,组合等。它是关于哪种范式构成语言的起点的。
据我所知,Lisp及其方言和Erlang比F#更好,因为它们鼓励在其他范式上进行函数式编程,而tdammers很好地将其称为语言的起点。F#确实包含函数式编程,但是不鼓励它比其他受支持的范例,命令式和oo编程好。
您不能学习C语言中函数编程的所有方面。但是,可以肯定的是,您可以使用任何命令式语言开始函数式编程。这些起始位是-“如何在编程时保持纯净”。也可以用C完成。查看此博客文章以了解详细信息-
http://www.johndcook.com/blog/2011/07/24/get-started-functional-programming/
函数式编程是关于闭包及其应用的。除非有人能够向您展示C的后代关闭库,否则请忘记使用C学习函数式编程。
函数式编程的基本概念是闭包(closure)的概念,闭包粗略地说是捕获函数以及变量绑定。除了普遍使用闭包之外,函数式编程还具有其他一些独特的特征,例如使用递归函数和不可变值(两者共同发挥作用)。这些特征比任何其他问题更是文化问题,并且几乎没有任何语言使用它们都没有技术障碍,这就是为什么我在回答中关注闭包:并非每种语言都允许轻松创建闭包。
闭包的典型用法是隐私机制的实现。例如,Javascript代码–在示例中,我选择Javascript是因为它是一种具有所谓“类似于C的语法”的功能语言,并且您的问题表明您熟悉C:
create_counter = function()
{
var x = 0;
var counter = function()
{
++x;
return x;
};
return counter;
}
然后用
a = create_counter();
b = create_counter();
我们有两个功能a
并b
计算不相交的集合。该示例的要点是变量x
由定义counter
闭包的闭包捕获,并且每次获取新的counter
闭包is instantiated by the function, it gets its fresh own idea of what
x` 时都将捕获。
闭包的另一种典型用法是定义函数的部分应用程序。假设我们有一个类似于syslog
实现功能的报告工具
var log = function(priority, message) {
…
};
这里的参数priority
,并message
预计将字符串,第一个是一个"debug"
,"info"
等。我们可以这样定义一个日志工厂:
var logWithPriority = function(priority) {
return function(message) {
log(priority, message);
};
};
并使用它来定义我们的日志工具的专用版本:
var debug = logWithPriority("debug");
var info = logWithPriority("info");
…
这非常有用,因为for
与其像这样编写容易出错的-loop,
for(i = 0; i < journal.length; ++i) {
log("info", journal[i]);
}
我们可以写出更清洁,更短和更简单(没有i
,那多好):
journal.forEach(logWithPriority("info"));
闭包的第三个重要应用领域是懒惰评估的实现–请注意,特殊语言支持可以提供更好的实现。
惰性函数代替执行直接计算,而是返回一个闭包,可以将其称为(或用懒惰的术语“强迫”)执行问题。这样做的动机是将准备计算和执行计算分开。一个实际的例子是正则表达式编译:如果程序在启动时编译了许多正则表达式,则将需要很多时间才能启动。相反,如果我们懒惰地编译正则表达式并根据需要强制使用它们,则程序可以快速启动。当然,这里的正则表达式可以用任何需要大量初始化时间的结构代替。
这是使用闭包实现惰性评估的方法。考虑arrayMax函数的经典实现,该函数返回数组中的max:
function arrayMax(array) {
return array.reduce(function(a, b) {
return Math.min(a, b);
};
}
惰性变体为:
function arrayMax(array) {
var memo = null;
function actuallyCompute() {
if(memo === null) {
memo = array.reduce(function(a, b) {
return Math.min(a, b);
});
}
return memo;
}
return actuallyCompute;
}
返回的值是一个闭包,可以用来计算该值,或者如果已经计算过,则可以再次获取它。
对于这三个示例,我们应该相信闭包及其应用程序是功能编程的核心。
学习函数式编程意味着学习如何使用闭包进行编程。因此,当寻找一种语言来研究函数式编程时,应考虑允许对闭包进行简单操作的语言,尤其是部分函数的应用。相反,闭包不易操作的语言将是错误的选择。
我认为您使用的工具会极大地影响您的学习。学习您所使用的编程语言没有提供使用方法的编程概念几乎是不可能的。当然,您总是可以学习一些东西,但是您不能正确地学习它。
但这无论如何都是学术性的,因为正如Martinho在他的评论中所说,即使您可以学习函数式编程,也不应尝试这样做,因为在某些语言中这要容易得多。