范型编程-函数式编程

Posted 李伯虎

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了范型编程-函数式编程相关的知识,希望对你有一定的参考价值。

上次说到,integral_constant是整个type_traits的基类,今天继续上回,从编程技巧的角度来阐述范型编程。


很多同学都使用过函数式编程,lisp,前几年比较火的erlang,以及scala等,函数式的语言众多,也不一一列举。erlang,大名鼎鼎的rabitmq,就是使用erlang语言实现的。就以erlang为例子,展示一下范型编程与函数编程的相似之处和c++的面向对象的特殊情况。


看一段erlang的代码片段,

1: list_length([]) ->    0;    

2: list_length([First | Rest]) ->    1 + list_length(Rest).


这段代码是定义了一个erlang列表长度的函数,函数的参数如果是一个空列编,则可以返回0,否则,计算列表长度并返回。这里erlang的语法细节和编程技巧细节不多解释,也不得不赞一下erlang这个语言,快速排序只用一行代码,而且利用尾递归还不会占用很多栈空间。


重点是list_length函数的实现和调用,在传统的c++里,如果函数名相同,第一印象就是函数重载了,重载的函数式通过不同的参数类型或者数量来区分,在erlang里,参数类型和数量式完全相同的。这也是函数式语言的一大特点,也是

c++范型编程与c++传统面向对象编程的不同。


函数式编程思维与命令式语言思维(c++):

函数式编程关注数据映射关系,命令式语言关注解决问题的过程方法。


从数学角度讲,函数式语言关注的是代数之间的关系。比如说,一个代数域,函数式语言可能分为四个基础计算(加减乘除)的匹配关系,命令式语更注重每个元素通过计算决定元素的归属。这一属性,也是函数语言另外一个特点决定了,函数式语言的变量,虽然有“变”,然而不可变。函数式语言的函数,也并非等同于命令式语言的函数,函数式语言的函数更侧重于描述数据之间的映射关系。


回到我们的主题,c++的编程思想是面向对象。抽象一点,c++的编程的思路是通过抽象事物,总结一类事物的特点,形成类,这些类能解决这一类事物的问题。这是对传统c++编程方法的描述。在c++11,甚至c++1y的横空出世,改变的不仅仅是语言的特性,编程的思想也在逐渐的变化。语言的特性也引入了部分函数式编程语言的特点。函数式编程的思维在c++98/03上也有一部分的应用。知识体现的不是那么的明显。或者说是确实在用,认知还未到。下面看一个例子:


template <bool bCondition, class ConditionIsTrueType, class ConditionIsFalseType>

struct type_select { typedef ConditionIsTrueType type; };


template <typename ConditionIsTrueType, class ConditionIsFalseType>

struct type_select<false, ConditionIsTrueType, ConditionIsFalseType> { 

    typdef ConditionIsFalseType type; 

};


这段代码也是一段很简单的代码,原理是通过三个模版参数,确定最终选择是哪一个类型(ConditionIsTrueType or ConditionIsFalseType )作为最后选择的类型。

第一部分,定义type_select类型,默认返回true type,接下来第二部分,特化bool模版参数为false,定义类型为 false type。


如果不是注明是c++的程序,是否会以为是新发明的函数式语言。。。。


再看一个列子


template <typename T> struct is_const_value                    : public wsl::false_type{};

template <typename T> struct is_const_value<const T*>          : public wsl::true_type{};

template <typename T> struct is_const_value<const volatile T*> : public wsl::true_type{};


template <typename T> struct is_const : public wsl::is_const_value<T*>{};

template <typename T> struct is_const<T&> : public wsl::false_type{};


这个例子的功能是判断输入的类型是否是带有const修饰。来解析一下这个例子,默认继承自false_type, 自然,默认就是非const类型,当遇到下列情形时,为真。

  1. 输入类型是const *

  2. 输入类型是const volatile *

另外一个特例,输入类型是T&时是false(引用类型)


通过前面两个例子,可以看到,c++范型编程思想的核心,关于模版类型的映射。

结合第一篇的所讲,先抛出一个结论,c++范型编程思想的核心:

面向对象的思维设计模式,函数式语言的思想解决问题。


怎么理解上面的话呢。在整个工程层面,使用面向对象的思想,设计整个工程类的继承,聚合等关系。在某一个类或者或函数实现,解决具体问题的时,使用函数式语言的思维解决具体的问题。


具体来说,前一篇提到intrgral_constanst这个类是所有type_traits类的大基类,这个设计是基于面向对象的思维去考虑,一切 “是” 与 ”非“的问题,通过这个基类来表述。如上面的例子,is_const,继承于false_type,实际上,false_type是integral_constant的一个特化。在判断具体是否是const修饰的时,具体问题使用的是函数式编程,代数映射的思想。


说到const ,想起一个面试题,const int *ptr与 int* const ptr,用is_const判断,分别是什么,提示一下,关注const的全局性。有兴趣的同学可以试机代码操作验证一下。


啰里八嗦写了一堆,限于本人最近嗓子哑了,严重影响语言天赋的发挥,或者也没说明白,再次总结一下。范型编程的核心思想 数据结构的映射关系!


下期预告:

 内存分配器是stl中很重要的一个环节,在目前流行的stl实现中,分配器都在使用操作系统提供的malloc接口实现。下一篇穿插一篇内存分配器的讨论,相关内容:

  1. malloc

  2. tcmalloc

  3. jemalloc

  4. *****

第四部分是stl中的实现,敬请期待,一定不会让你失望~

以上是关于范型编程-函数式编程的主要内容,如果未能解决你的问题,请参考以下文章

编程范式:范型编程函数式编程面向对象

IOS函数响应式编程开发简析

函数式编程的历史

Javascript 中的函数式编程

python之函数式编程与函数闭包

Python快速入门3--函数式编程