c++模版编程实现Haskell的函数模式匹配特性(图)

  

c++模版编程实现Haskell的函数模式匹配特性[图]:
大神Bartosz Milewski在2009年写了一篇文章《Haskell和c++什么?》,使用c++实现Haskell函数式编程语言的一些特性。【传送门在文末】
其中有这样一段例子:
//代码1
1. template类事实{
2.公众:

     <李> staticconstint价值=https://www.yisu.com/zixun/n * n <1>::价值;
4。};李   <李>   ,

6. template<的在类fact<0祝辞{//专业化为n=0
7.公众:

  李   <李> staticconstint价值=https://www.yisu.com/zixun/1;
9。};
注:原文中使用的是struct关键字,这里改为类并加上了公共
我猜,你没看懂,没关系,我们先跳过上面这一段有着【令人恐怖的语法】的c++模版代码。
上面的例子想干嘛呢?其实它只是想计算n的阶乘。
 C + +模版编程实现Haskell的函数模式匹配特性[图]”> <br/>如果你在C语言里面学过递归,应该知道下面这段计算阶乘的递归函数<br/>//代码2 <br/> int事实(int n) {<br/>如果(0==n) <br/> return1;//0阶问题答案0 !等其他于1 <br/> <br/>返回(n <em>事实(n - 1));//问题降阶:n阶→n - 1阶<br/>} <br/>它的效果就等于下面的代码<br/> 3 <br/>//代码int fact2 (int n){//用循环计算阶乘<br/> int p=1; <br/> (int i=n;我在=1;我——)<br/> p </em>=我;<br/>返回p; <br/>} <br/>那么,第一段代码(code1)与第二段代码(code2)的区别在哪里呢? <br/>区别在于,code1是在编译时(由编译器)计算的,code2是在运行时(就是代码运行的时候)计算的。<br/>现在来解释一下code1(部分根据Bartosz Milewski文中的说法)<br/>//代码1 <br/>/<em>第1行代码声明了一个类模版事实。<br/>这个模版接受一个“非类型参数“n, n <br/>是整数。<br/> </em>/<br/> 1. template<int n>类{<br/> 2。公众:<br/>/<em>第3行代码声明了一个静态整型常量<br/>成员的价值。而值的值是使用<br/>递归模版表示的<br/> </em>/</李>
  <李> staticconstint价值=https://www.yisu.com/zixun/n * n <1>::价值;<br/> 4。};李</>
  <李>
  <p>/<em>第6行代码是“特化”类模版,<br/>也就是显式地给出某种类型参数的<br/>类模板的一个实例的代码,而非由<br/>编译器生成。<br/>在这里,是给出了参数n为0时模板<br/>事实的代码。这样,编译器不会再<br/>根据类模版事实生成n=0时的代码<br/>关于模版特化,详见文末链接<br/> </em>/<br/> 6. template<祝辞类fact<0祝辞{//专业化为n=0 <br/> 7.公众:</p>
  李</>
  <李>静态常量int值=https://www.yisu.com/zixun/1;李</>
  <李>};<br/>/<em>根据c++规范,模版特化的代码必须<br/>放到模版声明之后。<br/>因此上面的代码看上去好像先处理了<br/>由n阶到n - 1阶的降阶问题,然后再给<br/>出了0阶的解答<br/>这可不像code2.code2中有if/else, <br/>因此可以把降阶代码与0阶解答代码调<br/>换先后次序(当然如果条件得改)。<br/> </em>/<br/>那么这个用模版计算阶乘的代码(类)该怎么用呢?如下:<br/> cout & lt; & lt;“Factorial (0=? lt; & lt;fact<0祝辞::价值& lt; & lt;endl; <br/>其中,c++编译器会为“fact<0祝辞:价值”这个调用匹配最合适的模版代码,也就是code1中的第6 - 9行代码。<br/>如果用非零参数调用呢? <br/> cout & lt; & lt;“阶乘8=? lt; & lt;fact<8祝辞::价值& lt; & lt;endl; <br/>其中,c++编译器会为“fact<8祝辞:价值”这个调用匹配code1中的第1 - 4行代码。<br/>前面blahblhaaaaaaaaaaaah讲了一大堆,其实都不是正经事儿。<br/>正经是下面的Haskell代码:<br/>//代码4李</>
  <李>事实0=1 </李>
  <李>事实n=n * (n - 1) <br/>上面两行代码定义了函数fact.fact是函数名,事实的后面,等号的前面是函数的参数。等号后面是函数体,函数体的计算结果就是事实函数的返回值。
  <pre> <代码>当程序员调用【8】事实的时候(参数是8,因为Haskell函数调用一般不像c++那样给参数加括号),Haskell会将之匹配到上面代码的第2行,谁动了我的奶酪读书笔记(http://www.simayi.net/dushubiji/6208.html)摘抄好词好句及感悟赏析,这种参数匹配,是Haskell特有的函数声明与调用方式。</代码> </pre>
  <p>所以前面的code1中c++模版代码,就是在模仿code4中的Haskell代码。<br/>下面给出一个完整的Haskell程序<br/> moduleFactwhere <br/> importSystem.IO <br/>的事实::整数→整数<br/> fact0=1 <br/>事实n=n * (n - 1) <br/>主要::主要IO () <br/>=<br/> putStrLn“美元;8 !=? +显示(8)<br/> putStrLn“美元;88年!=? +显示(88)<br/>上面的代码输出结果是:<br/> 8 !=40320 <br/> 88 !=185482642257398439114796845645546284380220968949399346684421580986889562184028199319100141244804501828416633516851200000000000000000000 <h2 class=c++模版编程实现Haskell的函数模式匹配特性(图)