C/C++知识点之C++模版编程实现Haskell的函数模式匹配特性[图]
小标 2019-04-22 来源 : 阅读 1306 评论 0

摘要:本文主要向大家介绍了C/C++知识点之C++模版编程实现Haskell的函数模式匹配特性[图],通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了C/C++知识点之C++模版编程实现Haskell的函数模式匹配特性[图],通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。


大神 Bartosz Milewski 在2009年写了一篇文章《What Does Haskell Have to Do with C++?》,使用C++实现Haskell函数式编程语言的一些特性。【传送门在文末】
其中有这样一段例子:
// code 1
1.templateclass fact {
2.public:

  1. staticconstint value = n * fact::value;
    4.};

  2. 6.template<>class fact<0>{// specialization for n = 0
    7.public:

  3. staticconstint value =1;
    9.};
    注:原文中使用的是struct关键字,这里改为class并加上了public
    我猜,你没看懂。没关系,我们先跳过上面这一段有着【令人恐怖的语法】的C++模版代码。
    上面的例子想干嘛呢?其实它只是想计算n的阶乘。

    如果你在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.templateclass fact {
    2.public:
    / 第3行代码声明了一个静态整型常量
    成员 value。而 value 的值是使用
    递归模版表示的
    /

  4. C/C++知识点之C++模版编程实现Haskell的函数模式匹配特性[图]

  5. staticconstint value = n * fact::value;
    4.};

  6. / 第6行代码是“特化”类模版fact,
    也就是显式地给出某种类型参数的
    类模板的一个实例的代码,而非由
    编译器生成。
    在这里,是给出了参数n为0时模板
    fact的代码。这样,编译器不会再
    根据类模版fact生成n=0时的代码
    关于模版特化,详见文末链接
    /
    6.template<>class fact<0>{// specialization for n = 0
    7.public:

  7. static const int value = 1;

  8. };
    / 根据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

  9. fact 0=1

  10. fact n = n * fact (n -1)
    上面两行代码定义了函数fact。fact是函数名,fact的后面、等号的前面是函数的参数。等号后面是函数体,函数体的计算结果就是fact函数的返回值。

    当程序员调用【fact 8】的时候(参数是8,因为Haskell函数调用一般不像C++那样给参数加括号),Haskell会将之匹配到上面代码的第2行。谁动了我的奶酪读书笔记(//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++说:你欺负人!

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程