【北京网站制作】函数式编程很难 这就是你应该学习的理由
  • 更新时间:2024-05-07 05:51:52
  • 网站建设
  • 发布时间:1年前
  • 525

函数式编程很难,这正是你要学习它的原因

本文翻译自文章Functional Programming Is Hard, That's Why It's Good。

奇怪的是没有,很少有人每天使用函数式编程语言。如果您使用Scala、Haskell、Erlang、F# 或Lisp 的某些方言进行编程,很可能没有公司愿意雇用您。这个行业的绝大多数人使用面向对象的编程语言,如Python、Ruby、Java 或C# ——,他们觉得这些语言很舒服。是的,您可能偶尔会使用一两个“函数式语言特性”,例如“块”,但人们不进行函数式编程。

然而,多年来,我们一直被教导说函数式编程语言很好,很棒。我还记得第一次阅读ESR 关于学习Lisp 的著名论文时的困惑。或许大多数人都比较熟悉Paul Graham 的《Beating The Averages》 文章:

使用Lisp 开发使我们能够如此快速地迭代我们的开发周期,有时当竞争对手在一两天后的新闻发布会上推出他们的新功能时,我们能够复制相同的功能。当报道产品发布会的记者打电话给我们时,我们的产品已经具有相同的功能。

那些皈依函数式编程的人中,一直常见的考虑是:学习这种新的、函数式的语言“对你有好处”;就像是某些人建议说每天30分钟的健身房活动会“让你的身体健康”一样。但这也同时暗示了这样做的难度和需要的付出。Lisp语言跟Haskell、Ocaml和Scala语言不同,被认为是出了名的难学,可以说是臭名昭著。优雅的人说这是Lisp语言“深度和广度”的体现。粗俗的人说这是“下流”或“玩学术”或干脆“不要”。在我看来,它的难易程度与你是否熟悉它有关,而这个难易程度是一个重要的指标:学习这样一门语言会让你更有效率,更有能力进行编程。

它给你的初次印象不友善

我7 岁时开始编程,在郊区漫长而无聊的夏天里,我在祖父的电脑上闲逛。我学习了BASIC 并用它在屏幕上画了一个弹跳球。我学习了Pascal 并用它编写了一个通过PC 扬声器播放音乐的程序。我大约10 岁时学习了C,但直到我上高中时才碰上了我无法逾越的墙。那就是:指针。即使没有这些该死的指点,我在写作、阅读、学习和实践中也遇到了无数次失败。我把祖父的硬盘毁了两次(一次是不小心),结果不得不自己重装操作系统很多次。我失败了,一次又一次地失败。

也许你的故事与我的相似,也许完全不同。但是我想几乎每个学过编程的人都经历过困难。我们在学习了一些基础知识之后,难免会遇到一些公认的概念障碍,比如“指针”。许多计算机科学教授会在他们的课程中将指针描述为过滤器。如果你想成为一名优秀的程序员,你必须了解指针。很少有人能轻易掌握它们。包括我在内的大多数人都需要实践和示例来理解指针是什么以及它们为什么重要。

这种艰难的努力过程并非偶然,而是几乎普遍存在的现象。指针是一个非常强大且具有基本功能的概念。学习它会让你成为更好的程序员,并让你更直观地思考。即使你使用的语言不提供像指针这样的特性,数据结构和类似于指针的概念也比比皆是。 (北京网出品)

新奇事物

一旦你学会了几种语言,所有的语言都会开始变得相似。会Python的人学习Ruby可能不会有太多问题,而会Java的人会觉得C#很熟悉。是的,也有惊喜。 Ruby 爱好者在学习Python 时会对它的理解感到惊讶,而Java 用户会对C# 中的委托感到困惑。再一次,如果你只看一眼它们,它们都是相似的。我可以肯定地说,如果您还没有学习过Lisp 语言,您会发现所有Lisp 变体都是相似的。

据说大多数人在第一次使用Haskell 或Ocaml 时完全不知所措。见鬼,在Haskell 中连分号都不一样。这不是语法问题; Haskell 和ML 语言完全基于不同的概念,一种新的语言范式。您需要以不同的方式开发应用程序,以不同的方式组织应用程序,并以不同的方式扩展应用程序。

许多这些新概念都非常强大。有

kell里的Monads 是跟指针一样基础且强大的概念(你很可能在不知道它叫什么的情况下就已经使用过它们了)。所以,跟学了Java后再学C#不一样,有志向学习函数式语言的人需要往回走的更远,去学习更加基础的概念后才能接下去学习。就像是完全再学习一次指针。并且,就像是当年我们刚开始学习编程一样,一些很大的概念看起来会让人迷惑茫然,让人沮丧,直到你去攻克(以及失败)它们。

吃下你的药丸,找到你的药剂师

尽管不好学,但我坚信,学习这些函数式编程语言会在职业上对你有好处。我相信有些人读到这点时会眼睛翻起来向天看,很难想象出这些monoids 或 monad 会对他们在使用Java或C#时有用处。对我而言,我已经不惊奇于由于这样的思维而阻止他们学习函数式语言的现象;他们需要学习一种跟指针和递归一样基础的新概念。他们需要有一种只有专业人员在完成清晰的商业目标时才具有的耐心和斗志。很少人能在过了可塑的年龄后还受得了挫折——一次又一次的挫折——否则我们现在都早成专家了,不是吗?

还有更复杂的东西,有大量的语言和算法研究都是用函数式语言实施的(尤其是Haskell)。你很容易会被这些不熟悉的概念——例如分类学理论, half-finished abstractions,一些失败的研究——弄的迷失方向。没有一个清晰的指导(比如由一个实用主义的作者写的一本好书),本来已经很困难的学习任务变的更加可怕。

这些叠加起来的复杂因素导致了不出意外的结果:很多人不情愿在函数式编程学习中投入时间。很容易理解这种不情愿,“我干嘛不把花在学习这些东西的时间用在实现什么东西上呢?”但这种思路也表明了你永远不愿意在任何新技术上浪费时间(只用自己熟悉的)。在一个像软件技术这样日新月异的产业里,我不认为这是正确的判断。

眼见为实

学习一种函数式编程语言最显而易见的好处是,你能学会这种类型语言中的函数式概念。它能帮助你的大脑,让它具有能非常清晰的思考和处理一些惊人的重大概念的能力。这并不是函数式编程具有魔法;各种语言和范式的出现都是为了应对某一特定类别的问题。函数式编程的杀手锏正是应对了当今世界上日益增长的并行性编程和元数据编程趋势。

例如,我们研究一个简化的、本地版本化的Google著名的MapReduce范例。用函数式方式描述这种范例是不可思议的清晰简洁:

  1. mapReducer data partitioner mapper reducer =  
  2.               let partitions = partitioner data  
  3.               in reduce reducer (map mapper partitions) 

让这样的代码支持并行计算或分布式并行计算是轻而易举的(对于本地并行计算,很多的功能包都支持“pmap”和“preduce“——只需要利用函数式语言的一些简单特性)。像maps, partitions, generators, streams, reductions, folds, 已以及 function chaining等概念在各种的函数式编程语言中都大同小异,所以,任何对Lisp,Haskell,OCaml,甚至带点函数式语言特征的语言——Python和Ruby熟悉的人,都会很容易的理解这里面的思想精华。

让我们花点时间考虑一下,如何用一种面向对象的语言,以一种常见的面向对象的模式来清楚的描述这种架构。至少你需要做的事情是定义用来描述mapper和reducer的声明。如果你有好奇心,请试着用你喜欢的面向对象语言描述一个最小化的“面向对象”的MapReduce。我发现那是非常罗嗦的。如果使用Java风格的语言,它会像这样:

  1. interface Mapper {  
  2.    B map(A input);  
  3.  }  
  4.  
  5.  interface Reducer {  
  6.    Y reduce(X a, X b);  
  7.  }  
  8.  
  9.  abstract class MapReduce {  
  10.    private Mapper mapper;  
  11.    private Reducer reducer;  
  12.  
  13.    public MapReduce(Mapper map, Reducer reduce) {  
  14.      // ...  
  15.    }  
  16.  
  17.    public run(SeqenceType data) {  
  18.      // ...  
  19.    }  
  20.  } 

即使是没有加入循环逻辑,这种缺乏函数式模式中常见的名词和动词的使用,使得MapReduce这种技术很难被定义。这种定义方式几乎是滑稽可笑的,但它能让你想到函数式概念。另外一个好例子是Scala语言如何利用完备的Java Fork/Join 类库,把它轻松的集成的自己的自有语法中。

各有所求

所以,我鼓励任何想进步的程序员:请考虑学习一种函数式语言。Haskell和OCaml都是极好的选择,F#和Erlang也相当的不错。它们都不好学,但也许这是个好事。努力弄清楚你遇到的复杂的概念,看看是否有其他人正在利用这些概念;经常的,你会在寻找这些不熟悉的概念的真正用意的时候实现思想上的突破。

当你开始学的时候,请注意,不要过于在意。就像其他任何需要你花时间和精力的事情一样,过度的在函数式编程上进行精力上的投资是很危险的。掉进了认知能力的陷阱后你的投资会血本无归。你很容易会忘掉世界上还有无数种计算模型,你更容易忘掉有多少种优秀的软件根本没有使用任何的函数式概念。

学习的道路会越来越难走,但从另一方面说,在你日常的编程中,你会发现有越来越多的可以使用的重要概念和模型。对于这样紧凑的编程风格你会越来越适应,必然,你也会对如何成为一名更好的软件工程师有了新的认识。

补充

有不少校对这篇文章的人在看完文章后都问了我一个同样的问题:“听起来不错,大卫,可是我应该学习那种语言呢?”当然,这是他们给我出的难题。

我想,如果你是一个很有经验的程序员,这最能“应付”这个问题的答案是:“选一种符合你的需求的”。如果你需要在JVM上工作,选择Scala或Clojure。如果你想能快速的开发大型分布式软件系统,选择Erlang。如果你想要一种具有超强编译器的超能干活的语言,请选择Haskell或RCaml。如果你想要一种比Ruby或Python更有能力的原型工具,选择Scheme。

请记住,我们在这里要做的这些目的是为了实际的技能和自我进步。如果你能腾出时间学这些,就走出你的安逸环境,挑战自己。

因为我已经学习了Lisp和Erlang,而且使用OCaml做专业工作,我决定研究一下Haskell,这完全是另外一个世界。我发现唯一能帮助我参透这种语言的途径是依赖Learn You A Haskell和 Real World Haskell 这两本有用的指导材料。这些书写的非常好,很有价值,而且可以免费在网上找到。如果你想试一下Haskell,这些书可以当作你的寻宝图。(高端网站建设)

我们专注高端建站,小程序开发、软件系统定制开发、BUG修复、物联网开发、各类API接口对接开发等。十余年开发经验,每一个项目承诺做到满意为止,多一次对比,一定让您多一份收获!

本文章出于推来客官网,转载请表明原文地址:https://www.tlkjt.com/web/13822.html

在线客服

扫码联系客服

3985758

回到顶部