功能编程和非功能编程
在大学的第二年,我们被"教"了Haskell,我对此几乎一无所知,甚至对函数式编程一无所知。
什么是函数式编程,为什么和/或者在什么地方我想用它代替非函数式编程?我是否认为C是一种非函数式编程语言是正确的?
解决方案
回答
也许值得在CoDe Mag上最近发布的F" 101"上查看这篇文章。
另外,达斯汀·坎贝尔(Dustin Campbell)拥有一个出色的博客,他在该博客上发表了许多有关他的F#入门历程的文章。
我希望我们觉得这些有用:)
编辑:
另外,仅补充一点,我对函数式编程的理解是,一切都是函数或者函数的参数,而不是实例/有状态的对象。.但是我可能是错的。时间! :)
回答
是的,我们认为C是一种非功能性语言是正确的。 C是一种过程语言。
回答
功能语言的一个主要功能是一流功能的概念。这个想法是,我们可以将函数作为参数传递给其他函数,然后将它们作为值返回。
函数式编程涉及编写不会更改状态的代码。这样做的主要原因是,对函数的连续调用将产生相同的结果。我们可以使用任何支持一流功能的语言编写功能代码,但是有些语言(例如Haskell)不允许我们更改状态。实际上,我们根本不应该产生任何副作用(例如打印文本),这听起来可能完全没有用。
Haskell相反地对IO采用了另一种方法:monads。这些对象包含要由解释器的顶层执行的所需IO操作。在任何其他级别上,它们只是系统中的对象。
函数式编程提供什么优势?由于每个组件都是完全隔离的,因此函数式编程可以减少潜在的错误编码。同样,使用递归和一流的功能还可以提供简单的正确性证明,这些证明通常反映了代码的结构。
回答
我更喜欢使用函数式编程来保存自己的重复工作,方法是制作一个更抽象的版本,然后使用它。让我举个例子吧。在Java中,我经常发现自己创建映射来记录结构,从而编写了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; }
而且我永远不必再写一个新的,我可以继承它。但是我可以做一个比继承更好的事情,我可以在这个东西的构造函数中说
getOrCreate = myLib.getOrCreate(*, SomeKindOfRecord<T>.constructor(<T>), localMap);
(其中*是一种"将此参数保持打开状态"表示法,这是一种多变的现象)
然后,本地的getOrCreate与如果我将整个内容写成一行而没有继承依赖性的情况下完全相同。
回答
如果我们正在寻找有关F#的好的文字
由Don Syme共同撰写的Fis专家。 F#的创建者。他专门研究.NET中的泛型,因此可以创建F#。
Fis是按照OCaml建模的,因此任何OCaml文本都可以很好地学习Fas。
回答
统计学家的示例代码John并未显示函数式编程,因为在进行函数式编程时,关键是该代码没有赋值(`record = somethingConstructor(t)是赋值),并且没有任何副作用( localMap.put(record)是带有副作用的语句。由于这两个约束,函数的所有操作都被其参数和返回值完全捕获。如果我们想使用C ++模拟功能语言,请按照看起来的方式来重写Statistician的代码:
RT getOrCreate(const T thing, const Function<RT<T>> thingConstructor, const Map<T,RT<T>> localMap) { return localMap.contains(t) ? localMap.get(t) : localMap.put(t,thingConstructor(t)); }
由于没有副作用规则的结果,每个语句都是返回值的一部分(因此,return
首先出现),并且每个语句都是一个表达式。在执行功能性编程的语言中,隐含了" return"关键字,并且if语句的行为类似于C ++的?:
运算符。
而且,一切都是不可变的,因此localMap.put
必须创建一个新的localMap副本并返回它,而不是像普通的C ++或者Java程序那样修改原始的localMap。根据localMap的结构,副本可以将指针重新使用到原始副本中,从而减少了必须复制的数据量。
函数式编程的一些优点包括以下事实:函数式程序更短,并且更容易修改函数式程序(因为没有要考虑的隐藏全局影响),并且更容易在函数式编程中正确设置程序。第一名。
但是,功能性程序往往运行缓慢(因为必须执行所有复制操作),并且它们往往无法与其他程序,操作系统进程或者操作系统进行良好的交互,这些程序处理内存地址(低位字节序)字节块和其他机器特定的非功能性位。非互操作性程度往往与功能纯度和类型系统的严格程度成反比。
较流行的功能语言具有非常非常严格的类型系统。在OCAML中,我们甚至不能混合使用整数和浮点运算,也不能使用相同的运算符(+用于添加整数,+。用于添加浮点数)。根据我们对类型检查器捕获某些类型的错误的能力的重视程度,这可能是优点还是缺点。
函数式语言也往往具有很大的运行时环境。 Haskell是一个例外(在编译时和运行时,GHC可执行文件几乎与C程序一样小),但是SML,Common Lisp和Scheme程序始终需要大量内存。