关于范例:函数式编程和非函数式编程

关于范例:函数式编程和非函数式编程

Functional programming and non-functional programming

在大学的第二年,我们被"教"了Haskell,我对它几乎一无所知,更不用说函数式编程了。

什么是函数式编程,为什么和/ xor我想在哪里使用它而不是非函数式编程?我认为C是非函数式编程语言是正确的吗?


功能语言的一个关键特性是一流功能的概念。这个想法是你可以将函数作为参数传递给其他函数并将它们作为值返回。

函数式编程涉及编写不改变状态的代码。这样做的主要原因是对函数的连续调用将产生相同的结果。您可以使用支持第一类函数的任何语言编写功能代码,但有些语言(如Haskell)不允许您更改状态。事实上,你根本不应该产生任何副作用(比如打印文本) - 听起来它可能完全没用。

相反,Haskell采用了不同的IO方法:monads。这些对象包含由解释器顶层执行的所需IO操作。在任何其他级别,它们只是系统中的对象。

函数式编程有哪些优点?功能编程允许编码具有较少的错误潜力,因为每个组件都是完全隔离的。此外,使用递归和第一类函数可以简单地证明正确性,这通常反映了代码的结构。


What is functional programming

目前常用的"函数式编程"有两种不同的定义:

较旧的定义(源自Lisp)是函数式编程是关于使用第一类函数进行编程,即函数被视为任何其他值,因此您可以将函数作为参数传递给其他函数,函数可以在返回值之间返回函数。这最终会导致使用高阶函数,例如mapreduce(你可能已经听说过mapReduce作为谷歌大量使用的单一操作,不出所料,它是一个近亲!)。 .NET类型System.FuncSystem.Action使C#中的高阶函数可用。尽管在C#中currying是不切实际的,但是接受其他函数作为参数的函数是常见的,例如, Parallel.For功能。

较年轻的定义(由Haskell推广)是函数式编程也是关于最小化和控制包括变异在内的副作用,即编写通过组合表达式来解决问题的程序。这通常被称为"纯函数式编程"。这可以通过称为"纯功能数据结构"的数据结构的完全不同的方法实现。一个问题是将传统的命令式算法转换为使用纯功能数据结构通常会使性能提高10倍。 Haskell是唯一幸存的纯函数式编程语言,但是这些概念已经悄悄进入主流编程,使用像.NET上的Linq这样的库。

where would I want to use it instead of non-functional programming

到处。 C#中的Lambdas现在已经证明了主要的好处。 C ++ 11有lambdas。现在没有理由不使用高阶函数。如果您可以使用像F#这样的语言,您还将受益于类型推断,自动泛化,currying和部分应用(以及许多其他语言功能!)。

am I correct in thinking that C is a non-functional programming language?

是。 C是一种程序性语言。但是,通过使用函数指针和C中的void *,您可以获得函数式编程的一些好处。


可能值得在CoDe Mag最近发布的F#"101"上查看这篇文章。

此外,达斯汀坎贝尔有一个很棒的博客,他发布了很多关于他的F&F速度的文章。

我希望你找到这些有用:)

编辑:

另外,仅仅补充一下,我对函数式编程的理解是,所有东西都是函数,或函数的参数,而不是实例/有状态对象。但我可能是错的F#是我渴望进入的东西,但只是不有时间! :)


John the Statistician的示例代码没有显示函数式编程,因为当你进行函数式编程时,关键是代码没有任何分配(record = thingConstructor(t)是一个赋值),它没有副作用(localMap.put(record)是一个有副作用的陈述)。作为这两个约束的结果,函数所做的一切都由其参数及其返回值完全捕获。如果您想使用C ++模拟函数语言,请按照必须查看的方式重写Statistician的代码:

1
2
3
4
5
6
7
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的结构,副本可以重复使用指向原始的指针,从而减少必须复制的数据量。

函数式编程的一些优点包括功能程序更短,更容易修改功能程序(因为没有隐藏的全局效果需要考虑),并且更容易使程序正确第一名。

但是,功能程序往往运行缓慢(因为他们必须进行所有复制),并且它们不倾向于与处理内存地址的其他程序,操作系统进程或操作系统良好地交互,little-endian字节块,以及其他特定于机器的非功能位。非互操作性程度倾向于与功能纯度的程度和类型系统的严格性成反比关系。

更流行的函数式语言具有非常非常严格的类型系统。在OCAML中,您甚至不能混合整数和浮点数学,或使用相同的运算符(+用于添加整数,+。用于添加浮点数)。这可能是优点还是劣势,具体取决于您对类型检查器捕获某些类型的错误的能力的重视程度。

功能语言也往往具有非常大的运行时环境。 Haskell是一个例外(GHC可执行文件几乎和C程序一样小,无论是在编译时还是运行时),但SML,Common Lisp和Scheme程序总是需要大量的内存。


我更喜欢使用函数式编程来保存自己重复的工作,通过制作一个更抽象的版本,然后使用它。让我举个例子吧。在Java中,我经常发现自己创建映射来记录结构,从而编写getOrCreate结构。

1
2
3
4
5
6
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;
}

这经常发生。现在,我可以写一种函数式语言

1
2
3
4
5
6
7
8
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;
}

而且我再也不必再写一个新的,我可以继承它。但是我可以做一个更好的继承,我可以说在这个东西的构造函数中

1
2
3
getOrCreate = myLib.getOrCreate(*,
                                SomeKindOfRecord< T >.constructor(< T >),
                                localMap);

(其中*是一种"保持此参数打开"符号,这是一种曲线)

然后本地getOrCreate与我在一行中写出整个事件时没有继承依赖关系的情况完全相同。


是的,你认为C是一种非功能性语言是正确的。 C是一种程序性语言。


如果你正在寻找关于F#的好文章

专家F#由Don Syme共同撰写。 F#的创造者。他专门研究.NET中的泛型,因此他可以创建F#。

F#是在OCaml之后建模的,因此任何OCaml文本都可以帮助您学习F#。


我发现什么是功能编程?有用

Functional programming is about writing pure functions, about removing
hidden inputs and outputs as far as we can, so that as much of our
code as possible just describes a relationship between inputs and
outputs.

更喜欢明确的when param

1
2
3
4
5
6
7
public Program getProgramAt(TVGuide guide, int channel, Date when) {
  Schedule schedule = guide.getSchedule(channel);

  Program program = schedule.programAt(when);

  return program;
}

过度

1
2
3
4
5
6
7
public Program getCurrentProgram(TVGuide guide, int channel) {
  Schedule schedule = guide.getSchedule(channel);

  Program current = schedule.programAt(new Date());

  return current;
}

A functional language is actively hostile to side-effects. Side-effects are complexity and complexity is bugs and bugs are the devil. A functional language will help you be hostile to side-effects too.


推荐阅读

    探探语言设置|探探怎么设置语言

    探探语言设置|探探怎么设置语言,,1. 探探怎么设置语言打开探探软件,然后就有消息提示的红点,点开就行了!其实这些软件都是挺简单的操作的,都是

    git设置编码|git语言设置

    git设置编码|git语言设置,,git设置编码点击cap4j搜索从git直接链接上拉代码。git语言设置Git是一个开源的分布式版本控制系统,可以有效、高

    区域语言设置|区域语言设置工具

    区域语言设置|区域语言设置工具,,区域语言设置工具你好,大致的方法如下,可以参考:1、按下键盘的windows 图标,再开始菜单中单击“设置”;出现的

    c4d语言设置|c4d汉语设置

    c4d语言设置|c4d汉语设置,,1. c4d汉语设置mac版的C4D是这样的,中文字体是有的,但是是以拼音的形式存在,比如黑体就是ht。中文字体以拼音方式

    电脑宣传语|电脑宣传语言

    电脑宣传语|电脑宣传语言,,1. 电脑宣传语言1.我做好了与你过一辈子的打算,也做好了你随时要走的准备,2.每段青春都会苍老,但我希望记忆里的你

    office语言设置|微软office语言设置

    office语言设置|微软office语言设置,,微软office语言设置一、首先点击桌面左下角“WIN键”。二、弹出选项内点击“所有程序”。三、接着点

    小米设置日语|小米设置日语语言

    小米设置日语|小米设置日语语言,,1. 小米设置日语语言MIUI系统文字目前只支持简体中文、繁体中文、英文、藏文和维吾尔文,不支持日文 2. 小

    易语言开发电脑系统|易语言电脑版

    易语言开发电脑系统|易语言电脑版,,1. 易语言电脑版首先编译——是将程序编译为exe文件,只能在有易语言的机子上运行,独立编译——是将程序