You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将SICP中基于函数的Scheme(Lisp) cons/car转换为C#

用C#实现SICP中的函数式cons和car

在《计算机程序的构造和解释》(SICP)中,作者用纯函数封装的方式重写了构造整数对的cons和提取首元素的car,对应的Lisp代码如下:

(define (cons x y)
  (lambda (m) (m x y)))

(define (car z)
  (z (lambda (p q) p)))

这段代码的核心逻辑是:cons返回一个等待接收双参处理函数的函数,它会把内部封装的两个值传给这个处理函数,最终返回处理结果;而car则是给这个返回的函数传入一个"只返回第一个参数"的处理函数,从而拿到整数对的首元素。

作为C#开发者,要实现这个逻辑,关键是搞对Cons方法的返回类型:它不是Func<int, int, int>(这是处理函数的类型),而是接收一个双参处理函数、返回该函数执行结果的函数,也就是Func<Func<int, int, int>, int>。

针对整数的实现

直接对应SICP逻辑的C#代码如下:

// 构造函数:返回一个接收处理函数的函数
static Func<Func<int, int, int>, int> Cons(int x, int y)
{
    return processFunc => processFunc(x, y);
}

// 提取首元素:传入"取第一个参数"的处理函数
static int Car(Func<Func<int, int, int>, int> pair)
{
    return pair((first, second) => first);
}

// 调用示例
var myPair = Cons(10, 20);
Console.WriteLine(Car(myPair)); // 输出 10

泛型通用版

如果想摆脱整数的限制,实现更通用的版本,可以用C#泛型:

// 通用构造函数,支持任意类型的参数和返回值
static Func<Func<T1, T2, R>, R> Cons<T1, T2, R>(T1 x, T2 y)
{
    return processFunc => processFunc(x, y);
}

// 通用首元素提取函数
static T1 Car<T1, T2>(Func<Func<T1, T2, T1>, T1> pair)
{
    return pair((first, second) => first);
}

// 调用示例
var stringPair = Cons("Hello", "World");
Console.WriteLine(Car(stringPair)); // 输出 Hello

关键说明

你之前的困惑在于混淆了"处理函数的类型"和"cons返回的函数类型":

  • cons内部的m是处理函数,类型是Func<int, int, int>(输入两个int,输出int)
  • 而cons本身返回的是接收这个处理函数并执行它的函数,所以类型是Func<Func<int, int, int>, int>

只要理清这层嵌套关系,就能写出可编译的代码了。

内容的提问来源于stack exchange,提问作者Avrohom Yisroel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 01:15:07