为什么函数式编程是重要的 --1

声明: 本译文只是为了提高个人英语阅读能力, 网上有更多精彩的翻译.
对于我这个英语水平极差的人來说, 翻译是十分痛苦的, 希望体谅.
原文请见 ^_^

Why Functional Programming Matters

这篇文章的数据来自 1984年, 作为 Chalmers 的备忘录传播多年.
稍微改变的版本出现在 1989年 和 1990 年. 这个版本是建立在原来
Chalmers 备忘录的基础上, 轻微地用 LaTeX 改动 使得它更接近发布
版本.

概要

一个软件变得越来越复杂, 那么对他组织得好就变得越来越重要. 好的结构
使更容易去写程序, 更容易去调试程序, 并且提供一个 能够重用的模块的集合
來减少未来的编码支付. 传统的语言在 模块化上有 概念上的限制.
(Conventional languages place concetual limits on the
way problems can be modularised.) 函数式语言没有这些限制, 他能
做到更大限度的模块化. 比如, 我们处理链表和树, 编写几个数值算法, 并且处理
alpha-beta 启发式 (一个人工只能的算法, 用于游戏编程中). 自从模块化成为
编程的关键, 函数式语言对现实世界是及其重要的.

介绍

这篇文章目的是证明 函数式编程 对于 现实世界是及其重要的 并且通过清楚的指出函数式语言
的优点帮助函数式编程的程序员探索他的全部优点.

之所以叫函数式编程是因为一个程序全部由函数组成. 主程序被写成一个來接受程序的输入作为
他的参数并且传递程序的输出作为他的结果的函数.

代表性的是主函数由其他函函定义, 其他函数轮流被其他函数定义, 直到底部函数是原始的语言.
这些函数更像是原始的数学函数, 并且在这篇文章中将会通过原始的等式定义. 我们的符号标记
来自 Turner 的语言 Miranda(TM), 但对于没有函数式语言基础的读者也是可读的.

函数式编程的特殊和优点经常被或多或少的总结出如下几点:函数式编程没有赋值语句, 所以
编程, 一旦我们给了一个值, 就不会被改变. 更通常的来说, 函数式编程没有副作用. 一个
函数调用除了计算他的值之外没有其他作用. 这消除了主要 bugs 的根源, 并且由于没有副作用
來改变表达式的值也让程序的执行和顺序无关, 因为他能够在任何时候被计算. 这减轻了编程的
所规定的控制流的负担. 由于表达式能在任何时候被求值, 我们能自由地用变量的值來取代变量,
反之也成立. 程序是引用透明的, 这种自由能帮助函数式程序更容易数学上的控制比其他传统的
语言.

这些优点都是很好的, 但我们也不会惊讶如果外行人对此毫不在乎. 听起来很多关于函数式编程的
是他所没有的 (没有赋值, 没有副作用, 没有控制流) 但没有更多关于他有什么. 函数式程序员
听起来像是和尚, 禁绝了乐趣的生活希望他们变得高尚. 对于那些对追求表面利用的人来说, 这些
"优点" 好像没有什么值得信服的.

函数式程序员会争论道 函数式编程能带来很多的 利益. 函数式程序员比其他类型语言的程序员
更高产, 因为函数式程序更短小. 为什么这是正确的? 一个好像有道理的原因是传统的程序由
90% 的赋值语句, 但是在函数式程序中, 这些赋值能被省略. 这是明显可笑的. 如果省略赋值
语句能带来如此大的收获, 那么 FORTRAN 程序员20年前早就这样做了. 逻辑上, 让一个语言
省略赋值语句來使得它变得强大也是不可能的, 不论这是多么糟糕的设计的.

甚至一个函数式程序员应该不满意这些优点, 因为这对帮助他们探索函数式语言的能力是没帮助的.
我们不可能写出一个完全缺少赋值语句的程序或者完全引用透明. 这不是衡量一个程序的质量,
因此把目标放在这里是没用的.

明显地, 这种描述函数式编程的特性是不够充分的. 我们必须找到一些不只是解释函数式编程的
威力的东西, 并且我们必须指出函数式编程该努力方向.

和结构化编程的类比

指出函数式编程和结构化编程的对比是十分有帮助的. 在过去, 结构化编程的特性和优点或多或少
被总结如下: 结构化程序没有 goto 语句. 语句块没有更多的入口和出口. 结构化程序比非结构
化结构程序更容易进行数学上的操作 (more tractable mathematically). 我们在早期发现
这些特性和函数式编程有很大的相似性. 这些本质上都是否定的, 从而导致太多没有结果的争论
"goto必不可少"等.

显而易见的是 结构化编程的这些属性虽然有帮助, 但是不能解决问题的核心. 结构化编程和
非结构化编程的最大不同是 结构化程序被设计成模块化. 模块化提高了生产力. 首先, 小模块
能够被快速和容易的编写. 其次, 一般的目标模块能够被重用, 使我们能够更快的产生子程序.
第三, 程序模块能够被独立测试, 帮助花费在调试的时间.

不使用 "goto" 等都是几乎没有作用的, 起到关键作用的是 模块化. 像 Modula-II, Ada,
ML(不是make love) 等语言, 都包括提高模块化的功能. 然而, 有一点关键的地方一直被
忽略. 当编写一个模块化程序的时候, 首先要分解问题成子问题, 然后解决子问题并且合并
解决方法. 分解问题的方式直接影响到粘合解决方式. 因此, 观念上提高模块化能力, 必须
在程序语言中提供新的粘合方法. 复杂的作用域规则 和 支持分块编译 仅仅起到一点点的帮助,
他们没有提供新概念上的工具來分解问题.

通过对在工匠上类比, 我们了解到粘合的重要性. 一张椅子通过-坐垫, 脚, 背等并且通过正确的
组合他们之后能被轻易的做成. 但这由木板和插口的连接能力决定. 缺少这个能力, 只能通过
雕刻坚固的木块的來做成. 这十分困难. 这个例子证明了模块化的巨大能力和有正确的黏合剂的
重要性.

现在让我们回到函数式编程. 在剩下的文章里我们将要讨论函数式编程提供给我们的两个新的
非常重要的黏合剂. 我们将会给出许多程序例子來证明函数式编程能用新的方法來模块化, 并且
更简单. 这是函数式编程的关键. 他让我们大大地提供了模块化. 这也是函数式编程的追求目标--
更小, 更简洁, 更具模块化, 用我们将要描述的新的黏合剂去组合.

时间: 2024-12-20 01:09:41

为什么函数式编程是重要的 --1的相关文章

Python学习笔记八:文件操作(续),文件编码与解码,函数,递归,函数式编程介绍,高阶函数

文件操作(续) 获得文件句柄位置,f.tell(),从0开始,按字符数计数 f.read(5),读取5个字符 返回文件句柄到某位置,f.seek(0) 文件在编辑过程中改变编码,f.detech() 获取文件编码,f.encoding() 获取文件在内存中的编号,f.fileno() 获取文件终端类型(tty.打印机等),f.isatty() 获取文件名,f.name() 判断文件句柄是否可移动(tty等不可移动),f.seekable() 判断文件是否可读,f.readable() 判断文件是

PYTHON修饰器的函数式编程

转自:http://coolshell.cn/articles/11265.html Python修饰器的函数式编程 Python的修饰器的英文名叫Decorator,当你看到这个英文名的时候,你可能会把其跟Design Pattern里的Decorator搞混了,其实这是完全不同的两个东西.虽然好像,他们要干的事都很相似--都是想要对一个已有的模块做一些"修饰工作",所谓修饰工作就是想给现有的模块加上一些小装饰(一些小功能,这些小功能可能好多模块都会用到),但又不让这个小装饰(小功能

函数式编程

函数式编程 函数式编程的三大特性: immutable data 不可变数据 first class functions 尾递归优化 函数式编程的准则:不依赖于外部的数据,而且也不改变外部数据的值,而是返回一个新的值给你. 如何变得functional: 1. 没有共享变量 2.通过参数和返回值传递数据 3. 函数里没有临时变量 对现有的代码进行重构(refactoring) 使得代码具有functional programming的优点 lambda a, x: x(a) lambda函数可以

Python学习:映射函数(map)和函数式编程工具(filter和reduce)

在序列中映射函数map map函数会对一个序列对象中的每一个元素应用被传入的函数,并且返回一个包含了所有函数调用结果的一个列表. 例1: def sum(x):     return x + 10 L1 = [1,2,3,4,5,6,7] L = map(sum, L1) #结果为[11, 12, 13, 14, 15, 16, 17] map还有更高级的使用方法,例如提供了序列作为参数,它能够并行返回分别以每个序列中的元素作为函数对应参数得到的结果的列表.如例2所示. 例2: def sum(

javaScript函数式编程-包含闭包、链式优化及柯里化

本文着重介绍个人理解的函数式编程. 函数式编程个人理解为:以函数为主要载体的编程方式. 好处: 语义更加清晰 可复用性高 可维护性好 作用域局限.副作用少 基本函数式编程: //实现数组中每个单词首字母大写 //一般写法 const arr = ['apple','orange','pear']; for(const i in arr) { const c = arr[i][0]; arr[i] = c.toUpperCase() + arr[i].slice(1); //slice()从已有的

javascript - Underscore 与 函数式编程

<Javascript函数式编程 PDF> # csdn下载地址http://download.csdn.net/detail/tssxm/9713727 Underscore # githubhttps://github.com/jashkenas/underscore # 中文官方网站http://www.css88.com/doc/underscore/ # CDN<script src="https://cdn.bootcss.com/underscore.js/1.8

LUA 函数式编程demo

什么是函数式编程 http://www.zhihu.com/topic/19585411/hot 函数式编程的本质函数式编程中的函数这个术语不是指计算机中的函数(实际上是Subroutine),而是指数学中的函数,即自变量的映射.也就是说一个函数的值仅决定于函数参数的值,不依赖其他状态.比如sqrt(x)函数计算x的平方根,只要x不变,不论什么时候调用,调用几次,值都是不变的.在函数式语言中,函数作为一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数和返回值,可以对函数进行组合.

[Java] 函数式编程相关概念 - 笔记1

Java 8 引入了 lambda 表达式,以及函数式编程风格.在了解函数式编程过程中,做了些笔记,摘录于本文. 嵌套函数( Nested Function ) 1. 嵌套函数,是指在另一个函数里面定义的一个函数.外层的函数,这里简称为外层函数. 2. 函数的嵌套可以是多层嵌套.嵌套函数可以看到其全部的外层函数的非局部变量.在实际程序中,嵌套的层数一般很少.下面是一个三层嵌套的例子, innerOfInner 也可以访问在 outer 函数体重定义的变量 x . function outer()

python_way.day7 模块(configparser,xml,shutil,subprocess)、面向对象(上)(创建类,类的构成,函数式编程与面向对象编程的选择,类的继承)

python_way.day7 1.模块 configparser,xml,shutil,subprocess 2.面向对象(上) 创建类,类的构成,函数式编程与面向对象编程的选择,类的继承 1.模块 configparser 用于处理特定格式的文件,其本职上使用open来操作,只能是  [test1] 特定的格式 [test1] k1 = 123 k2 = True [test2] k1 = 123 k2 = v1 文件内容 1.获取 import configparser #打开文件找到文件

为什么函数式编程在Java中很危险?

摘要:函数式编程这个不温不火的语言由来已久.有人说,这一年它会很火,尽管它很难,这也正是你需要学习的理由.那么,为什么函数式编程在Java中很危险呢?也许这个疑问普遍存在于很多程序员的脑中,作者Elliotte对此发表了一些见解,我们一起来看看他是怎么说的. 在我的日常工作中,我身边的开发者大多是毕业于CS编程顶级院校比如MIT.CMU以及Chicago,他们初次涉及的语言是Haskell.Scheme及Lisp.他们认为函数式编程是一种自然的.直观的.美丽的且高效的编程样式.但奇怪的是,我和我