【发布时间】:2010-09-06 15:50:31
【问题描述】:
在我大学的第二年,我们“教”了 Haskell,我对此几乎一无所知,对函数式编程更是一无所知。
什么是函数式编程,为什么和/或我想在哪里使用它而不是非函数式编程,我认为 C 是一种非函数式编程语言是否正确?
【问题讨论】:
标签: functional-programming paradigms glossary
在我大学的第二年,我们“教”了 Haskell,我对此几乎一无所知,对函数式编程更是一无所知。
什么是函数式编程,为什么和/或我想在哪里使用它而不是非函数式编程,我认为 C 是一种非函数式编程语言是否正确?
【问题讨论】:
标签: functional-programming paradigms glossary
我更喜欢使用函数式编程来节省自己的重复工作,方法是制作一个更抽象的版本,然后改用它。让我举个例子。在 Java 中,我经常发现自己创建映射来记录结构,并因此编写 getOrCreate 结构。
SomeKindOfRecord<T> getOrCreate(T thing) {
if(localMap.contains(thing)) { return localMap.get(thing); }
SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(thing);
localMap = localMap.put(thing, record);
return record;
}
这种情况经常发生。现在,我可以用函数式语言编写
RT<T> getOrCreate(T thing,
Function<RT<T>> thingConstructor,
Map<T,RT<T>> localMap) {
if(localMap.contains(thing)) { return localMap.get(thing); }
RT<T> record = thingConstructor(thing);
localMap = localMap.put(thing,record);
return record;
}
我再也不用写新的了,我可以继承它。但是我可以做得比继承更好,我可以在这个东西的构造函数中说
getOrCreate = myLib.getOrCreate(*,
SomeKindOfRecord<T>.constructor(<T>),
localMap);
(其中 * 是一种“保持此参数打开”表示法,这是一种柯里化)
然后本地的 getOrCreate 与我在一行中写出整个内容时完全一样,没有继承依赖关系。
【讨论】:
我觉得What Is Functional Programming? 很有用
函数式编程是关于编写纯函数,关于删除 尽可能隐藏输入和输出,这样我们的 代码尽可能只描述输入和之间的关系 输出。
首选显式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;
}
函数式语言对副作用非常不利。副作用是复杂性,复杂性是错误,错误是魔鬼。函数式语言也可以帮助您避免副作用。
【讨论】:
什么是函数式编程
当今常用的“函数式编程”有两种不同的定义:
较早的定义(源自 Lisp)是函数式编程是关于使用一等函数进行编程,即函数被视为任何其他值,因此您可以将函数作为参数传递给其他函数,并且函数可以在它们之间返回函数返回值。这最终导致使用诸如map 和reduce 之类的高阶函数(您可能听说过mapReduce 是Google 大量使用的单个操作,毫不奇怪,它是近亲!)。 .NET 类型 System.Func 和 System.Action 使 C# 中的高阶函数可用。尽管 currying 在 C# 中不切实际,但接受其他函数作为参数的函数很常见,例如Parallel.For 函数。
较年轻的定义(由 Haskell 推广)是函数式编程也是关于最小化和控制包括变异在内的副作用,即编写通过组合表达式来解决问题的程序。这通常被称为“纯函数式编程”。这可以通过称为“纯功能数据结构”的数据结构的完全不同的方法来实现。一个问题是,将传统的命令式算法转换为使用纯函数式数据结构通常会使性能降低 10 倍。 Haskell 是唯一幸存的纯函数式编程语言,但这些概念已经通过 .NET 上的 Linq 等库进入主流编程。
我想在哪里使用它而不是非函数式编程
无处不在。 C# 中的 Lambda 现在已经展示了主要的好处。 C++11 有 lambda。现在没有理由不使用高阶函数。如果您可以使用像 F# 这样的语言,您还将受益于类型推断、自动泛化、柯里化和部分应用程序(以及许多其他语言功能!)。
我认为 C 是一种非函数式编程语言是否正确?
是的。 C是一种过程语言。但是,您可以通过在 C 中使用函数指针和 void * 来获得函数式编程的一些好处。
【讨论】:
John the Statistician 的示例代码没有显示函数式编程,因为当您进行函数式编程时,关键是代码没有分配(record = thingConstructor(t) 是分配),并且没有副作用(@987654323 @ 是一个有副作用的语句)。由于这两个约束,函数所做的一切都被它的参数和返回值完全捕获。如果您想使用 C++ 模拟一种函数式语言,请按照它的外观重写 Statistician 的代码:
【讨论】:
如果您正在 F# 上寻找好的文本
Expert F# 由 Don Syme 共同撰写。 F#的创造者。他专门研究 .NET 中的泛型,以便创建 F#。
F# 以 OCaml 为模型,因此任何 OCaml 文本都可以帮助您学习 F#。
【讨论】:
函数式语言的一个关键特性是一等函数的概念。这个想法是您可以将函数作为参数传递给其他函数并将它们作为值返回。
函数式编程涉及编写不改变状态的代码。这样做的主要原因是对函数的连续调用将产生相同的结果。您可以使用任何支持一流函数的语言编写函数式代码,但是有些语言(例如 Haskell)不允许您更改状态。事实上,你根本不应该产生任何副作用(比如打印文本)——这听起来可能完全没用。
Haskell 采用了不同的 IO 方法:monads。这些对象包含要由解释器的顶层执行的所需 IO 操作。在任何其他级别,它们只是系统中的对象。
函数式编程提供了哪些优势?函数式编程允许以更少的潜在错误进行编码,因为每个组件都是完全隔离的。此外,使用递归和一等函数可以简单地证明正确性,这通常反映了代码的结构。
【讨论】:
Why do we want successive calls to a function to yield the same result. What is the problem with the way things are in C? I never understood this.
是的,您认为 C 是一种非函数式语言是正确的。 C 是一种过程语言。
【讨论】:
可能值得在最近发布的 CoDe Mag 上的 F# "101" 上查看这篇文章。
另外,Dustin Campbell has a great blog 在那里他发布了许多关于他的冒险与 F# 速度的文章..
我希望你觉得这些有用:)
另外,补充一点,我对函数式编程的理解是,一切都是函数,或函数的参数,而不是实例/有状态对象。但我可能错了 F# 是什么我很想进去,但就是没有时间! :)
【讨论】: