y组合器和C预处理器

时间:2013-01-18 14:48:22

标签: c functional-programming

据我所知,如果你想在没有明确使用递归的情况下编写递归函数,组合器很有用。 C预处理器不支持递归。我们可以在C预处理器中实现y组合器以支持递归吗?

感谢。

2 个答案:

答案 0 :(得分:2)

Y组合器是一个高阶函数,它需要语言中的高阶函数支持来实现显式递归替换。因此,对于特定任务,这可以在Scheme,SML和其他功能语言中完成。

让我们稍后讨论C预处理器,但是C本身呢?可以在C中使用高阶函数,因为我们可以将函数引用作为函数参数传递,并返回它们来模拟高阶函数。但是,语言中缺少闭包支持不允许实现Y组合。

由于预处理器比C更具限制性,因此无法实现基于lambda演算概念的Y组合器。 Y组合器的应用只能在具有高阶函数全功能支持的函数式编程语言中实现。

C预处理器非常简单,因为它只在文本中进行字符串替换。我不会尝试将lambda演算和函数式编程中的任何概念应用到它。

答案 1 :(得分:2)

实际上这是完全可能的,请参阅我的项目CSP Git Repo,这是一个在C macro预处理器上实现的LISP解释器COMPLETELY,当然你可以在它上面实现Y组合。

如果您对此感兴趣,希望您和一些测试/示例。

这是最相关的部分。 (来自csp.h) 它成功实现了闭包和lambda,为实现定点组合器提供了支持。

#define EVAL_e(x) x
#define _be(y) y)
#define ZIP(x)   _n() (x,_be

#define _PAIR(x,y) _e( __PAIR(x,y))
#define __PAIR(x,y) _E COND((NULL SAFE_CDR(x)((SAFE_CAR(x) SAFE_CAR(y))))((T)((SAFE_CAR (x) SAFE_CAR (y)) _e(_PAIR2(_e SAFE_CDR(x),_e SAFE_CDR(y))))))

#define _PAIR2(x,y)  _E COND((NULL SAFE_CDR(x)((SAFE_CAR(x) SAFE_CAR(y))))((T)((SAFE_CAR (x) SAFE_CAR (y)) _e(_PAIR3(_e SAFE_CDR(x),_e SAFE_CDR(y))))))

#define _PAIR3(x,y)  _E COND((NULL SAFE_CDR(x)((SAFE_CAR(x) SAFE_CAR(y))))((T)((SAFE_CAR (x) SAFE_CAR (y)) _e(_PAIR4(_e SAFE_CDR(x),_e SAFE_CDR(y))))))

#define _PAIR4(x,y)  _E COND((NULL SAFE_CDR(x)((SAFE_CAR(x) SAFE_CAR(y))))((T)((SAFE_CAR (x) SAFE_CAR (y)) _e(DELAY_INT_54(__PAIR_R) ()(SAFE_CDR(x) SAFE_CDR(y))))))
#define __PAIR_R() _$pair
#define TEST_R() TEST
#define TEST(x) test
#define _PAIR_e(x) x
#define _$pair(x) _PAIR_e(_PAIR ZIP x)
#define PAIR_EVAL(...) PAIR_EVAL2(PAIR_EVAL2(PAIR_EVAL2(__VA_ARGS__)))
#define PAIR_EVAL2(...) PAIR_EVAL3(PAIR_EVAL3(PAIR_EVAL3(__VA_ARGS__)))
#define PAIR_EVAL3(...) PAIR_EVAL4(PAIR_EVAL4(PAIR_EVAL4(__VA_ARGS__)))
#define PAIR_EVAL4(...) PAIR_EVAL_E(PAIR_EVAL_E(PAIR_EVAL_E(__VA_ARGS__)))
#define PAIR_EVAL_E(...) __VA_ARGS__
#define $pair(x) PAIR_EVAL(_$pair(x))

#define $zipped_evlis_R() $zipped_evlis
#define EVLIS_e_R() EVLIS_e
#define EVLIS_e(x) x
#define _EVLIS_ZIP(...) _n() (__VA_ARGS__,_BE
#define _BE(...) __VA_ARGS__)
#define _EVLIS_R() _EVLIS
#define _EVLIS_E(...) __VA_ARGS__
#define _EVLIS_N(...)
#define _EVLIS_B _EVLIS_E (_EVLIS_N,_EVLIS_E(_EVLIS_N,_EVLIS_N))
#define ___EVLIS(a,b,k,...) k($zipped_eval((b),(a)) DELAY_INT_2(_EVLIS_R)()(a))
#define __EVLIS(a,b,...) ___EVLIS(a,b,__VA_ARGS__ _EVLIS_E)
#define _EVLIS_EVAL_E(...) __VA_ARGS__
#define _EVLIS_EVAL_5(...) _EVLIS_EVAL_E(_EVLIS_EVAL_E(_EVLIS_EVAL_E(__VA_ARGS__)))
#define _EVLIS_EVAL_4(...) _EVLIS_EVAL_5(_EVLIS_EVAL_5(_EVLIS_EVAL_5(__VA_ARGS__)))
#define _EVLIS_EVAL_3(...) _EVLIS_EVAL_4(_EVLIS_EVAL_4(_EVLIS_EVAL_4(__VA_ARGS__)))
#define _EVLIS_EVAL_2(...) _EVLIS_EVAL_3(_EVLIS_EVAL_3(_EVLIS_EVAL_3(__VA_ARGS__)))
#define _EVLIS_EVAL(...) _EVLIS_EVAL_2(_EVLIS_EVAL_2(_EVLIS_EVAL_2(__VA_ARGS__)))

#define _EVLIS(x) __EVLIS _EVLIS_ZIP(x)
#define $zipped_evlis(x,y) _EVLIS_EVAL(_EVLIS y x (_EVLIS_B))

#define $zipped_eval_R() $zipped_eval
#define $zipped_eval(e,a) /**sth irrelevant**/
        ($eq(SAFE_CAR SAFE_CAR e (lambda))\
        (DELAY_INT_26(EVAL_e_R)() DELAY_INT_23($zipped_eval_R)()(\
        EVAL_e(EVAL_e(EVAL_e(EVAL_e(SAFE_CAR SAFE_CDR SAFE_CDR SAFE_CAR e)))),\
        EVAL_e(APPEND DELAY_INT_13($pair_R)()(EVAL_e(EVAL_e(EVAL_e(SAFE_CAR SAFE_CDR SAFE_CAR e)))\
                                              (DELAY_INT_19($zipped_evlis_R)()(EVAL_e(_e EVAL_e(SAFE_CDR e)), a)))a)))\
        /**end of eval recursion**/

#define $pair_R() $pair
#define EVAL_e_R() EVAL_e
#define $eval_E(...) __VA_ARGS__
#define $eval_expand5(...) $eval_E($eval_E($eval_E(__VA_ARGS__)))
#define $eval_expand4(...) $eval_expand5($eval_expand5($eval_expand5(__VA_ARGS__)))
#define $eval_expand3(...) $eval_expand4($eval_expand4($eval_expand4(__VA_ARGS__)))
#define $eval_expand2(...) $eval_expand3($eval_expand3($eval_expand3(__VA_ARGS__)))
#define $eval_expand(...) $eval_expand2($eval_expand2($eval_expand2(__VA_ARGS__)))
#define $zeval(x,y) $eval_expand($zipped_eval(x,y))