文档章节

C++模版编程实现Haskell的函数模式匹配特性[图]

 原创小博客
发布于 2018/07/18 15:57
字数 1148
阅读 5
收藏 0

C++模版编程实现Haskell的函数模式匹配特性[图]:
大神 Bartosz Milewski 在2009年写了一篇文章《What Does Haskell Have to Do with C++?》,使用C++实现Haskell函数式编程语言的一些特性。【传送门在文末】
其中有这样一段例子:
// code 1
1.template<int n>class fact {
2.public:
3.     staticconstint value = n * fact<n -1>::value;
4.};
5.
6.template<>class fact<0>{// specialization for n = 0
7.public:
8.     staticconstint value =1;
9.};
注:原文中使用的是struct关键字,这里改为class并加上了public
我猜,你没看懂。没关系,我们先跳过上面这一段有着【令人恐怖的语法】的C++模版代码。
上面的例子想干嘛呢?其实它只是想计算n的阶乘。

C++模版编程实现Haskell的函数模式匹配特性[图]
如果你在C语言里面学过递归,应该知道下面这段计算阶乘的递归函数
// code 2
int fact(int n){
if(0== n )
return1;  //0阶问题答案。0! 等于1
else
return( n * fact( n -1)); //问题降阶:n阶->n-1阶
}
它的效果就等于下面的代码
// code 3
int fact2(int n){ // 用 for 循环计算阶乘
int p =1;
for(int i=n; i >=1; i--) 
p *= i;
return p;
}
那么,第一段代码(code1)与第二段代码(code2)的区别在哪里呢?
区别在于,code1是在编译时(由编译器)计算的,code2是在运行时(就是代码运行的时候)计算的。
现在来解释一下code1 (部分根据Bartosz Milewski文中的说法)
// code 1
/* 第1行代码声明了一个类模版 fact。
这个模版接受一个“非类型参数”n,
n是整数。
*/
1.template<int n>class fact {
2.public:
/* 第3行代码声明了一个静态整型常量
成员 value。而 value 的值是使用
递归模版表示的
*/
3.     staticconstint value = n * fact<n -1>::value;
4.};
5.
/* 第6行代码是“特化”类模版fact,
也就是显式地给出某种类型参数的
类模板的一个实例的代码,而非由
编译器生成。
在这里,是给出了参数n为0时模板
fact的代码。这样,编译器不会再
根据类模版fact生成n=0时的代码
关于模版特化,详见文末链接
*/
6.template<>class fact<0>{// specialization for n = 0
7.public:
8.    static const int value = 1;
9. };
/* 根据C++规范,模版特化的代码必须
放到模版声明之后。
因此上面的代码看上去好像先处理了
由n阶到n-1阶的降阶问题,然后再给
出了0阶的解答
这可不像code2。code2中有if/else,
因此可以把降阶代码与0阶解答代码调
换先后次序(当然if条件得改)。
*/
那么这个用模版计算阶乘的代码(类?)该怎么用呢?如下: 
cout <<"Factorial of 0 = "<< fact<0>::value << endl;
其中,C++编译器会为“fact<0>::value”这个调用匹配最合适的模版代码,也就是code1中的第6-9行代码。
如果用非零参数调用呢?
cout <<"Factorial of 8 = "<< fact<8>::value << endl;
其中,C++编译器会为“fact<8>::value”这个调用匹配code1中的第1-4行代码。
前面blahblhaaaaaaaaaaaah讲了一大堆,其实都不是正经事儿。
正经是下面的Haskell代码:
//code 4
1. fact 0=1
2. fact n = n * fact (n -1)
上面两行代码定义了函数fact。fact是函数名,fact的后面、等号的前面是函数的参数。等号后面是函数体,函数体的计算结果就是fact函数的返回值。
当程序员调用【fact 8】的时候(参数是8,因为Haskell函数调用一般不像C++那样给参数加括号),Haskell会将之匹配到上面代码的第2行。谁动了我的奶酪读书笔记(http://www.simayi.net/dushubiji/6208.html)摘抄好词好句及感悟赏析,这种参数匹配,是Haskell特有的函数声明与调用方式。
所以前面的code1中C++模版代码,就是在模仿 code4 中的Haskell代码。
下面给出一个完整的Haskell程序
moduleFactwhere
importSystem.IO
fact::Integer->Integer
fact0=1
fact n = n * fact (n-1)
main::IO()
main=do
putStrLn $"8!  = "++ show (fact 8)
putStrLn $"88! = "++ show (fact 88)
上面的代码输出结果是:
8!  = 40320
88! =185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000 
Haskell对C++说:我能算88!,你行吗?
C++说:你欺负人!

© 著作权归作者所有

共有 人打赏支持
粉丝 12
博文 251
码字总数 540906
作品 0
宜昌
私信 提问
提升 C++ 技能的 7 种方法

本文由伯乐在线 -精算狗 翻译,艾凌风 校稿。未经许可,禁止转载! 英文出处: Jonathan Boccara。欢迎加入 翻译组。 夏天时常会谈到大海、太阳、沙滩、大山或者你的家庭住宅。更充裕的时间也...

伯乐在线
2017/08/24
0
0
从 C++98 到 C++17,元编程是如何演进的? | 技术头条

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/csdnnews/article/details/86297148 作者 | 祁宇 责编 | 郭芮 出品 | CSDN(ID:CSDNnews) 不断出现的C++新的...

CSDN资讯
01/11
0
0
TensorFlow架构与设计:会话生命周期

TensorFlow的系统结构以C API为界,将整个系统分为「前端」和「后端」两个子系统: 前端系统:提供编程模型,负责构造计算图; 后端系统:提供运行时环境,负责执行计算图。 前端系统主要扮演...

刘光聪
2017/03/04
0
0
系统级编程语言性能大PK的笑话-Go语言

喜欢和不喜欢Go语言的都喜欢拿性能PK说事. 流传比较广的是benchmarksgame的PK数据: http://benchmarksgame.alioth.debian.org/u64q/go.php 在 benchmarksgame测试中, Go语言的性能已经由之前...

chai2010
2013/08/06
0
7
为什么 Go 不是一款好的编程语言

我喜欢 Go. 常用它实现各种功能(包括在写本文时的这个博客). Go 很实用,但不够好。 不是说它有多差, 只是没那么好而已。 一门编程语言, 也许会用上一辈子, 所以选择的时候要注意。 本文专...

oschina
2014/12/03
32.9K
158

没有更多内容

加载失败,请刷新页面

加载更多

kubernetes 二进制包安装

环境 角色 主机名 内网 IP 集群 IP 操作系统 服务 执行目录 部署机 k8s-master master120 10.0.4.120 - CentOS kube-apiserver kube-scheduler kube-controller-manager /opt/kubernetes/ et......

Colben
刚刚
0
0
瑞达利欧的《原则》读后感作文2400字

瑞达利欧的《原则》读后感作文2400字: 拿到同事送的书读了几十页后,我意识到自己犯了一个错误:之前以为像《原则》这个书名,配上最成功的对冲基金经理、受用终身的教诲、傅盛引用并盛赞,...

原创小博客
17分钟前
0
0
java内存占用异常问题常见排查流程(含堆外内存异常)

先初步介绍一下内存组成: java进程占用内存 约等于 Java永久代 + Java堆(新生代和老年代) + 线程栈+ Java NIO,其它部分占用内存较小, 详细可以参考这篇文章 https://my.oschina.net/h...

小海bug
24分钟前
0
0
成为架构师需要学习哪些技能?阿里P9架构师为你解答

不想当将军的兵不是好兵,就程序猿不想当架构师就不是好的程序员! Java架构师主要需要做哪些工作呢? 1、负责设计和搭建软件系统架构(平台、数据库、接口和应用架构等),解决开发中各种系...

别打我会飞
27分钟前
0
0
使用xtrabackup备份数据库

使用xtrabackup备份数据库 提供一个参考文档:http://xtra.aminglinux.com mysqldump对于导出几个G的数据库或几个表,还是不错的,速度并不慢。一旦数据量达到几十上百G,无论是对原库的压力...

wzb88
43分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部