函数式编程的优与劣

如今函数式编程越来越流行。越来越多的编程语言支持函数式编程风格,人们学习如何使用它们。函数式编程已不像以前那么小众——现在Ruby,Java和JavaScript都使用了函数式编程思想。

这些语言都有函数式的特性,但不是函数式语言。我的经验之谈,函数式语言,如Erlang或ML拥有其他主流语言缺少的特性,能让编程更加安全的特性。其中之一便是使用递归和参数模式匹配(argument pattern matching)控制循环。你也可以将这些设计用于流控制( flow control)。另一个便是认真对待常量赋值。我这里提到常量赋值因为在这些语言中,一旦你给变量绑定一个值,直到离开作用域前会一直绑定。这个特性带来的弊端就是学习如何使用它们开发软件很困难。对于我们这些用强类型语言的开发者,尤其困难。

递归和模式匹配

函数式编程语言特性是运行期优化递归。使用尾调用优化,运行期提供高效的回调环境,使每个回调用相同的栈帧(stack frame)。再加上参数模式匹配,你可以像写归纳法证明(高中数学的归纳法)那样写表达式函数。你有一个基础步骤和归纳步骤。基础步骤结束递归,归纳步骤重复递归。通过这种方式,你可以定义函数处理列表或集合。函数的每个变量在每次调用中绑定,这使得变量绑定更易于管理。下面是个伪代码例子:

这里,我们定义了一个函数looper()对列表内容求和。

第一个步骤是基础步骤——如果列表为空,我们返回0。第二个步骤是归纳步骤——如果列表有头元素和尾元素,然后我们把尾元素通过递归调用looper()方法求和。如果列表中只剩一个元素,这个元素绑定到变量t,递归调用匹配基础步骤(因为变量h为空),然后递归展开。

在函数式语言中,尾调用优化确保了栈帧重复使用,所以本质上结构和for、while循环一样,比如C语言。

如果你在Ruby或JavaScript中使用它,你必须确保在使用函数循环列表前尾递归优化是可用的。如果没有,你将在递归中遇到性能问题。你在Ruby或JavaScript中只需要把基础步骤放在归纳步骤前面就行。

常量赋值

这点在函数式语言中很难实现。毕竟用不可变的值表示可变的状态非常困难。你又该怎么办呢?

记住,变量赋值只在当前作用域有效。所以你如何应对这种情况?你让作用域很小,只在函数调用时绑定必须的变量。你不能编写修改状态的代码,比如在一系列循环中。你只能在函数调用时绑定状态,然后递归。通过这种方式,你可以维护状态改变,在绑定状态变量值时很难出现错误。

不要使用全局变量。它会跑到作用域外。

相比那些所谓拥有函数式编程的语言,这就是你将在真正函数式语言中看到的两点关键不同点。函数式程序设计让你的重用能力更上一层楼,使代码更清晰,不过在没有优化的运行环境中会有潜在的性能代价。

原文发布于微信公众号 - java一日一条(mjx_java)

原文发表时间:2016-07-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏数据科学与人工智能

【Python环境】Python函数式编程指南(1):概述

1. 函数式编程概述 1.1. 什么是函数式编程? 函数式编程使用一系列的函数解决问题。函数仅接受输入并产生输出,不包含任何能影响产生输出的内部状态。任何情况下...

23260
来自专栏龙首琴剑庐

Java总论及三大特性理解

1、对象(object)     万物皆为对象(根类Object类)。     程序是对象的集合(面向对象程序设计语言OOP)。     每个对象都有自己的由其...

31560
来自专栏Python小白进阶之旅

记录一个python里面很神奇的操作,对一个包含列表的元组进行增量赋值

今天记录一个很神奇的操作。关于序列的增量赋值。如果你很熟悉增量赋值,你也不妨看下去,我想说的是有关于增量赋值和元组之间一种神奇的操作。来自 **《流畅的Pyth...

12220
来自专栏向治洪

迭代器模式

迭代器模式(Iterator): 提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。 用途:在软件构建过程中,集合对象内部结构常常变化各异。...

198100
来自专栏机器学习算法与Python学习

6个鲜为人知的 Python 语法,你知道几个?

所有人(好吧,不是所有人)都知道 Python 是一门用途广泛、易读、而且容易入门的编程语言。

14340
来自专栏鸿的学习笔记

Python中__str__和__repr__方法的区别

在stackoverflow有一个很精辟的回答解释这两个内置方法的区别,简单来说,__str__方法是表现给使用者使用的,而__repr__方法是给程序员用的...

11520
来自专栏C/C++基础

C++智能指针

C++中,动态内存的管理是通过一对运算符来完成的,new用于申请内存空间,调用对象构造函数初始化对象并返回指向该对象的指针。delete接收一个动态对象的指针,...

31510
来自专栏WeTest质量开放平台团队的专栏

【《Effective C#》提炼总结】提高Unity中C#代码质量的21条准则

我们知道,在C++领域,作为进阶阅读材料,必看的书是《Effective C++》。 而《Effective C#》之于C# ,是类似《Effective C+...

13130
来自专栏我是攻城师

你不知道的Java的split的小问题

28760
来自专栏Java学习网

Java 8的函数式编程学习

Java 8的函数式编程学习 函数式编程语言是什么? 函数式编程语言的核心是它以处理数据的方式处理代码。这意味着函数应该是第一等级(First-class)的...

27770

扫码关注云+社区

领取腾讯云代金券