C++ 是否可以用C++;?

C++ 是否可以用C++;?,c++,recursion,scheme,language-lawyer,continuations,C++,Recursion,Scheme,Language Lawyer,Continuations,在阅读Friedman和Felleisen的《小阴谋家》时,我发现了连续体,为了实践这个概念,我编写了一个简单的代码,给出一个整数列表,删除偶数并返回赔率之和 这是我的方案代码: (定义nil'()) ; s是整数列表,op是运算符。 (定义(rem_添加操作) (条件((空值)(操作零0)) ((偶数) (rem_添加(cdr s) (lambda(l n)(op l n))) (其他 (rem_添加(cdr s) (lambda(l n)(op(cons(cars s)l)(+n 1()()

在阅读Friedman和Felleisen的《小阴谋家》时,我发现了连续体,为了实践这个概念,我编写了一个简单的代码,给出一个整数列表,删除偶数并返回赔率之和

这是我的方案代码:

(定义nil'())
; s是整数列表,op是运算符。
(定义(rem_添加操作)
(条件((空值)(操作零0))
((偶数)
(rem_添加(cdr s)
(lambda(l n)(op l n)))
(其他
(rem_添加(cdr s)
(lambda(l n)(op(cons(cars s)l)(+n 1()())))
(定义(计数s和n)
(条件((空?s)0)
(其他(+(车辆)(计数(cdr s)n()())))
(定义s(列表1 2 3 4 5))
(显示(rem_添加计数))
我用chicken scheme编译了它,并按预期工作,生成了输出9

<> >我尝试重写C++中的相同代码,如下:

#包括
#包括
#包括
int rem_add(常数标准::设置与设置,自动操作){
如果(s.empty()){
返回op(s,0);
}
std::set s2(++s.cbegin(),s.cend());
如果(*s.cbegin()%2==0){
返回rem_add(s2,
[op](常数标准::集合与集合,整数n){
返回op(l,n);
});
}否则{
返回rem_add(s2,
[&s,op](常数标准::集合与集合,整数n){
std::集q(l);
q、 插入(*s.cbegin());
返回op(q,n+1);
});
}
}
//从s中删除偶数元素,并返回奇数元素之和。
int main(){
std::集s{1,2,3,4,5};
std::函数
计数=[count](常数std::set&s,int n)
{if(s.empty()){返回0;}
std::set s2(++s.cbegin(),s.cend());
返回*s.cbegin()+计数(s2,n);
};
自动求和赔率=rem加(s,计数);

STD::CUT< P>是的,在C++中,可以写续写。 有关示例,请参见此示例

下面的代码对您建议的示例使用连续传递样式(CPS):

#include<functional>
#include<iostream>
#include<vector>

int main() {

    auto calc = [](auto&& k1, auto&& k2, auto V){ return k1(k2(V,0));};

    std::function<std::vector<int>(std::vector<int>, int)> get_odd;
    get_odd = [&get_odd](auto V, int pos)
    {
        if(pos == V.size()) return V;
        if(V[pos] % 2 == 0)
        {
            V.erase(V.begin()+pos);
            return get_odd(V,pos);
        }
        else
            return get_odd(V,++pos);
    };

    std::function<int(const std::vector<int>&)> sum;
    sum = [&sum](const std::vector<int>& V)
    {
        if (V.empty()) return 0;
        std::vector<int> W(++V.begin(), V.end());
        return V[0] + sum(W);
    };

    std::vector<int> v1{1,2,3,4,5};   
    std::cout << calc(sum, get_odd, v1) << std::endl;

    return 0;
}

享受
C++
的强大功能。一些宏魔法,几乎与原始版本相同

#include <functional>
#include <iostream>
#include <vector>

using Set = std::vector<int>;
using Op = std::function<int(const Set &, int n)>;
int car(const Set &s) { return *s.cbegin(); }
Set cdr(const Set &s) { return Set(++s.cbegin(), s.cend()); }
bool even(int x) { return (x % 2) == 0; }
bool null(const Set &s) { return s.empty(); }
Set cons(int x, const Set &s) { Set r = s; r.push_back(x); return r; }

#define DEFINE_OP(name, s, op) int name(const Set &s, Op op) {
#define DEFINE_N(name, s, n) int name(const Set &s, int n) {
#define DEFINE_S(name, ...) auto name = Set{__VA_ARGS__};
#define COND_START if (false) {}
#define COND(expr, result) else if (expr) { return result; }
#define ELSE(result) else { return result; } }
#define LAMBDA(l, n, body) [s, op](const Set &l, int n) { return body; }
#define DISPLAY(func, s, count) int main() { std::cout << func(s, count) << std::endl; return 0; }

// here is the implementation

DEFINE_S(nil)

DEFINE_OP (rem_add, s, op)
  COND_START
    COND (( null ( s ) ), ( op (nil, 0) ))
    COND (( even ( car(s) )),
            ( rem_add (cdr (s),
                 LAMBDA (l, n, ( op (l, n) ) ))))
    ELSE (
            ( rem_add (cdr (s),
                 LAMBDA (l, n, ( op ( cons ( car (s), l), n + 1) )))))

DEFINE_N (count, s, n)
  COND_START
    COND ( (null (s)), (0))
    ELSE ( (car (s) + count (cdr (s), n - 1 ) ))

DEFINE_S(s, 1, 2, 3, 4, 5);
DISPLAY(rem_add, s, count)
#包括
#包括
#包括
使用Set=std::vector;
使用Op=std::函数;
int car(const Set&s){return*s.cbegin();}
Set cdr(const Set&s){返回集(++s.cbegin(),s.cend());}
布尔偶数(int x){return(x%2)==0;}
bool null(const Set&s){返回s.empty();}
集合cons(int x,const Set&s){Set r=s;r.push_back(x);return r;}
#定义定义_OP(name,s,OP)int name(const Set&s,OP){
#定义\u N(名称,s,N)int name(常量集&s,int N){
#define define_S(name,…)auto name=Set{{uuuu VA_ARGS};
#如果(false){}定义条件启动
#定义COND(expr,result)else if(expr){return result;}
#定义ELSE(结果)ELSE{return result;}}
#定义LAMBDA(l,n,body)[s,op](const Set&l,int n){return body;}

#定义显示(func,s,count)int main(){std::cout可能是递归模板扩展(在参数声明中使用
auto
类似于创建模板)。查看clang-live中的错误:@RichardCriten确实,如果我将参数列表中的
auto
替换为
std::function
,那么编译几乎立即完成。但是,运行可执行文件会产生分段错误。可能某个地方有错误。我担心这超出了我的能力。可能需要添加[语言律师]tag?@RichardCritten我仍然认为允许使用普通函数语法通过
auto
隐式定义函数模板是一个严重的错误。我非常喜欢你的代码,但是你如何将
calc
sum
都作为递归函数来定义呢?实际上,稍微修改一下你的代码,使之成为
calc
recursive(如图所示)返回原始问题中的分段错误。我修改了代码,使两个相关函数是递归的。代码运行如您所见。我是否应该使用此注释中的代码修改原始答案?是的,请。我认为保留原始问题中的递归lambda将LD对未来读者更有用。很多人会说使用宏不是惯用的C++(例如Scott Myers的有效C++)。,但无论如何:您的代码是否由预处理器通过编译时替换规则解析递归?如果是,这将无法回答问题。COND_START的目的是什么?另外,为什么在
计数的定义中递减n?此代码与scheme snippet的作用完全相同。预处理器是我们ED隐藏LAMBDAS的丑陋C++语法,如果ELSIF语句也被隐藏。如果你用代码替换预处理器指令,你会看到发生什么。问题的答案是“是”。C++支持继续。前面的片段显示了如何。回到代码> N<代码>,它是未被使用的。我不记得为什么我会减少它。大概认为它表示容器的大小。您可以将count定义为递归lambda函数,它将起作用。诀窍是首先需要将count声明为
Op count;
,然后将其定义为
count=[&count](…)
。通过这种方式,编译器知道声明并可以捕获它。不是每个人都可以奢侈地使用比
c++11
更高的标准。如果没有正向声明,它在
c++14
之前将无法工作。
9
#include <functional>
#include <iostream>
#include <vector>

using Set = std::vector<int>;
using Op = std::function<int(const Set &, int n)>;
int car(const Set &s) { return *s.cbegin(); }
Set cdr(const Set &s) { return Set(++s.cbegin(), s.cend()); }
bool even(int x) { return (x % 2) == 0; }
bool null(const Set &s) { return s.empty(); }
Set cons(int x, const Set &s) { Set r = s; r.push_back(x); return r; }

#define DEFINE_OP(name, s, op) int name(const Set &s, Op op) {
#define DEFINE_N(name, s, n) int name(const Set &s, int n) {
#define DEFINE_S(name, ...) auto name = Set{__VA_ARGS__};
#define COND_START if (false) {}
#define COND(expr, result) else if (expr) { return result; }
#define ELSE(result) else { return result; } }
#define LAMBDA(l, n, body) [s, op](const Set &l, int n) { return body; }
#define DISPLAY(func, s, count) int main() { std::cout << func(s, count) << std::endl; return 0; }

// here is the implementation

DEFINE_S(nil)

DEFINE_OP (rem_add, s, op)
  COND_START
    COND (( null ( s ) ), ( op (nil, 0) ))
    COND (( even ( car(s) )),
            ( rem_add (cdr (s),
                 LAMBDA (l, n, ( op (l, n) ) ))))
    ELSE (
            ( rem_add (cdr (s),
                 LAMBDA (l, n, ( op ( cons ( car (s), l), n + 1) )))))

DEFINE_N (count, s, n)
  COND_START
    COND ( (null (s)), (0))
    ELSE ( (car (s) + count (cdr (s), n - 1 ) ))

DEFINE_S(s, 1, 2, 3, 4, 5);
DISPLAY(rem_add, s, count)