function编程和非function编程
在大学的第二年,我们被“教”了Haskell,我对它几乎一无所知,甚至不了解函数式编程。
什么是函数式编程,为什么和/ xor我想在哪里使用它,而不是非函数式编程,我正确地认为C是一种非函数式编程语言?
function语言的一个关键特征是一streamfunction的概念。 这个想法是,你可以将函数作为parameter passing给其他函数,并将其作为值返回。
函数式编程涉及编写不改变状态的代码。 这样做的主要原因是,连续调用函数将产生相同的结果。 你可以使用任何支持一stream函数的语言编写function代码,但是有一些语言,比如Haskell,它们不允许你改变状态。 事实上,你不应该做任何副作用(如打印文本) – 这听起来可能是完全无用的。
Haskell采用了不同的方法来处理IO:单子。 这些对象包含所需的IO操作,由解释器的顶层执行。 在任何其他级别,它们只是系统中的对象。
函数式编程提供了什么好处? function编程允许用较less的潜在错误编码,因为每个组件都是完全隔离的。 此外,使用recursion和一stream的function允许简单的正确性certificate,通常反映代码的结构。
什么是函数式编程?
今天常用的“函数式编程”有两种不同的定义:
较早的定义(起源于Lisp)是函数式编程是关于使用一级函数进行编程的,也就是说,函数被视为任何其他值,所以您可以将函数作为parameter passing给其他函数,并且函数可以在返回值之间返回函数。 这最终导致使用map
和reduce
等更高级的函数(您可能已经听说过mapReduce
是Google经常使用的单一操作,毫不奇怪,它是一个近亲!)。 .NETtypesSystem.Func
和System.Action
使C#中的高阶函数可用。 虽然在C#中currying是不切实际的,但接受其他函数作为参数的函数是常见的,例如Parallel.For
函数。
较年轻的定义(Haskell推广)是函数式编程也是关于最小化和控制包括变异在内的副作用,即编写通过组合expression式来解决问题的程序。 这通常被称为“纯函数式编程”。 对于被称为“纯粹function的数据结构”的数据结构来说,这是非常不同的。 一个问题是,将传统的命令式algorithm转换为使用纯粹function性的数据结构通常会使性能下降10倍。 Haskell是唯一幸存的纯函数式编程语言,但是这些概念已经悄悄进入了像.NET上的Linq
这样的库的主stream编程。
我想在哪里使用它,而不是非function性编程
到处。 C#中的Lambdas现在已经certificate了主要的好处。 C ++ 11有lambdaexpression式。 现在没有理由不使用高阶函数。 如果你可以使用F#这样的语言,你还可以从types推断,自动泛化,curl和部分应用(以及其他许多语言特性!)中受益。
我正确地认为C是一个非函数式编程语言?
是。 C是一种程序语言。 但是,通过在C中使用函数指针和void *
,可以获得函数式编程的一些好处。
可能值得看看这篇关于最近发布的CoDe Mag上的F#“101”的文章。
此外, 达斯汀·坎贝尔还有一个很棒的博客 ,他已经发表了许多关于F#游戏的文章。
我希望你find这些有用的:)
编辑:
此外,只是补充一点,我的function编程的理解是, 一切都是一个函数,或一个函数的参数,而不是实例/有状态的对象..但我可能是错误的F#是我渴望得到,但只是不要有时间! 🙂
约翰统计学家的示例代码没有显示函数式编程,因为当你正在进行函数式编程时,关键是代码没有做ASSIGNMENTS( record = thingConstructor(t)
是一个赋值),它没有任何影响( localMap.put(record)
是一个副作用的声明)。 作为这两个约束的结果,一个函数所做的所有事情都被其参数和返回值完全捕获。 如果你想用C ++来模拟一个函数式语言,那么重写统计学家的代码就不得不看看它的样子:
RT getOrCreate(const T的东西, const Function <RT <T >> thingConstructor, const Map <T,RT <T >> localMap){ 返回localMap.contains(t)? localMap.get(t): localMap.put(T,thingConstructor(T)); }
由于没有副作用规则,每个语句都是返回值的一部分(因此return
值是第一个 ),每个语句都是一个expression式。 在执行函数式编程的语言中,隐含了return
关键字, if语句的行为与C ++的?:
操作符相同。
另外,一切都是不可变的,所以localMap.put
必须创build一个localMap.put
的新副本并返回它,而不是像普通的C ++或Java程序那样修改原始的localMap 。 根据localMap的结构,副本可以将指针重新用于原始数据,减less了需要复制的数据量。
函数式编程的一些优点包括:函数式程序更短,修改function性程序更容易(因为没有隐藏的全局效应要考虑),而且更容易使程序正确第一名。
然而,function程序往往运行缓慢(因为所有的拷贝都要做),而且它们往往不能与其他程序,操作系统进程或者操作系统交互,这些程序在处理内存地址,小端字节块和其他机器特定的非function位。 不可操作性的程度往往与function纯度的程度和types系统的严格程度成反比。
更stream行的function语言有真正严格的types系统。 在OCAML中,甚至不能混合整数和浮点math,或者使用相同的运算符(+用于添加整数,+用于添加浮点数)。 这可能是一个优点,也可能是一个劣势,取决于你高度重视types检查器捕捉某些types错误的能力。
函数式语言也往往有非常大的运行时环境。 Haskell是一个例外(在编译时和运行时,GHC可执行文件几乎和C程序一样小),但SML,Common Lisp和Scheme程序总是需要大量的内存。
是的,你认为C是一种非function性语言是正确的。 C是一种程序语言。
我更喜欢使用函数式编程来保存自己的重复工作,通过制作更抽象的版本,然后使用它。 让我举个例子。 在Java中,我经常发现自己创build地图来logging结构,从而编写getOrCreate结构。
SomeKindOfRecord<T> getOrCreate(T thing) { if(localMap.contains(t)) { return localMap.get(t); } SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(t); localMap = localMap.put(t,record); return record; }
这经常发生。 现在,我可以写一个函数式语言
RT<T> getOrCreate(T thing, Function<RT<T>> thingConstructor, Map<T,RT<T>> localMap) { if(localMap.contains(t)) { return localMap.get(t); } RT<T> record = thingConstructor(t); localMap = localMap.put(t,record); return record; }
我再也不用再写这些新的东西了,我可以inheritance它。 但是我可以做一个更好的inheritance,我可以在这个东西的构造函数中说
getOrCreate = myLib.getOrCreate(*, SomeKindOfRecord<T>.constructor(<T>), localMap);
(其中*是一种“离开此参数打开”表示法,这是一种currying)
然后本地的getOrCreate与我在一行中写出整个事件的过程完全一样,没有inheritance依赖关系。
如果你正在寻找一个好的F#
专家F#由Don Syme合着。 F#的创build者。 他专门研究.NET中的generics,所以他可以创buildF#。
F#是在OCaml之后build模的,所以任何OCaml文本都可以帮助你学习F#。
我发现什么是函数式编程? 有用
函数式编程是关于编写纯函数,尽可能去除隐藏的input和输出,以便尽可能多的代码描述input和输出之间的关系。
param when
首选显式
public Program getProgramAt(TVGuide guide, int channel, Date when) { Schedule schedule = guide.getSchedule(channel); Program program = schedule.programAt(when); return program; }
过度
public Program getCurrentProgram(TVGuide guide, int channel) { Schedule schedule = guide.getSchedule(channel); Program current = schedule.programAt(new Date()); return current; }
function语言对副作用是主动的。 副作用是复杂性和复杂性是错误和错误是魔鬼。 function语言也会帮助你对副作用产生敌意。
在计算机科学中,函数式编程是一种编程范式 – 一种构build计算机程序结构和元素的风格 – 将计算看作是对math函数的评估,并避免了c 状态和可变数据 。 这是一个声明性的编程范例,这意味着编程是通过expression式来完成的。 在函数式代码中,函数的输出值只依赖于input到函数中的参数,所以用参数x的相同值调用函数f两次将会每次产生相同的结果f(x) 。 消除副作用,即不依赖于函数input的状态变化,可以使得更容易理解和预测程序的行为,这是函数式编程发展的关键动机之一。 在wiki中查看更多详细信息。 函数式编程语言的一些例子就像scala,javascript …等等