驳“反驳老赵之“伪”递归”

简介: 晚上看到鹤冲天的“反驳老赵之“伪”递归”,大概看了一下,主要是反驳老赵提出的“伪”递归的概念,特别是“伪”,看起来说的都很有道理,但我个人认为,老赵说的没有错,Lambda这种看上去是递归的方式,根本不算是递归。

晚上看到鹤冲天的“反驳老赵之“伪”递归”,大概看了一下,主要是反驳老赵提出的“伪”递归的概念,特别是“伪”,看起来说的都很有道理,但我个人认为,老赵说的没有错,Lambda这种看上去是递归的方式,根本不算是递归。

我引用鹤冲天的递归概念:

一个过程或函数在其定义或说明中又直接或间接调用自身的一种方法

我觉得这句话说的很明白,通俗点就是自己调用自己,鹤兄说递归应该不仅仅是过程还是函数,应该包括匿名方法和lambda。我同意匿名方法应该算一种,但因为是匿名方法,我们在开发中无法知道方法名,故我们无法去调用它,但lambda(和委托)算不算一种递归呢?

我们都知道lambda构建的是一个委托,委托只是对一个方法的应用,lambda表达式只是构建了一个匿名方法体,并没有去执行,只有在使用的时候根据需求来延迟加载,但其中是有陷阱的,老赵先前写了一篇“.NET中*延迟*特性的几个陷阱”,其中介绍的非常清楚。那如何反驳鹤兄呢?从他的程序来讲吧。代码:

public static readonly Func<int, int> fac = x => x <= 1 ? 1 : x * fac(x - 1);
static void Main(string[] args)
{
	int x = 5;
	Console.WriteLine(fac(x));
	Console.Read();
}

为了看清楚些,我索性执行了,照鹤兄所说,fac调用了fac就应该属于一种递归形式,但你知道它其中执行了什么吗?Look 反编译:

internal class Program
{
// Fields
	public static readonly Func<int, int> fac;
// Methods
	static Program()
	{
		if (CS$<>9__CachedAnonymousMethodDelegate1 == null)
		{
			CS$<>9__CachedAnonymousMethodDelegate1 = new Func<int, int>(null, (IntPtr) <.cctor>b__0);
		}
		fac = CS$<>9__CachedAnonymousMethodDelegate1;
	}
	private static void Main(string[] args)
	{
		Console.WriteLine(fac.Invoke(5));
		Console.Read();
	}
}

这样我们能清楚些,当我们执行委托的时候,会使用Invoke(args)来调用方法体,看清楚,是Invoke方法,并不是委托自己哦,这一点已经偏离了递归的概念了。

再来看下我们原先的递归方法:

static int  Fac(int i)
{
	return i <= 1 ? 1 : i * Fac(i - 1);
}

反编译的代码:

private static int Fac(int i)
{
	return ((i <= 1) ? 1 : (i * Fac(i)));
}

大家看清楚了吧,调用的是它自己哦。

继续说鹤兄的代码,就算鹤兄说委托调用自己委托属于一种递归,但存在着一个“延迟特性的陷阱”,这一点老赵已经说明,每一次调用的是方法体,其中的参数是从外部传进来的,并不是方法自身往下传的,老赵也在“使用Lambda表达式编写递归函数”进行了叙述,什么意思呢?就是我们在委托调用委托的时候,“递归”还没有结束的情况下,如果改变了外部这个参数值,就会影响到“递归”的结果,这也是闭包的一个陷阱。鹤兄用了readonly来让委托只读,想以此来构造一个递归的委托,但真正需要绑定的不是方法体,还需要绑定参数的,你的参数值能通过外部进行改变的,而在传统递归中,第二次调用的时候,参数值都是第一次调用说传入的,外部是无法改变的,这一点是最能说明问题所在的。

总结

太晚了,也不想写太多了,我想懂的人应该明白吧。最后说一下,虽然世界变化的很快,但编程的一些基础还是经的起考验的,并不是说有了匿名方法,委托等就能改变递归的定义,因为从它的诞生之日起,已经有很多人研究过,为什么没有把它定义为委托,肯定有一定道理在里面的。老赵说是一种“伪”递归,这是从代码层面来说的,严格来说,绝对不是递归,我也不是老赵的拥护者,老赵也说了他的SelfApplicable<T, TResult>也不是递归,所以这种驳论觉得没有什么意义。

不过有讨论总归比不讨论要好,我也不知道自己说的对不对,拿出来大家一起讨论,欢迎拍砖。

相关文章
|
关系型数据库 Serverless 分布式数据库
1.4亿人都在用|伊对APP x 阿里云PolarDB:这一对,天生配
PolarDB以其出色的性能和稳定性为伊对APP提供了强大的支持
1.4亿人都在用|伊对APP x 阿里云PolarDB:这一对,天生配
|
监控 前端开发 Cloud Native
解决WebSocket通信:前端拿不到最后一条数据的问题
解决WebSocket通信:前端拿不到最后一条数据的问题
763 0
|
程序员 Linux Ruby
Mac安装并使用telnet命令操作
Mac安装并使用telnet命令操作
18663 1
Mac安装并使用telnet命令操作
|
NoSQL 安全 Java
2.2k star 单点登录框架揭秘!主流SSO太重?SpringBoot轻量级Smart‑SSO轻松接入·分布式·强踢人
Smart-SSO 是一个基于 SpringBoot 的轻量级单点登录框架,采用 OAuth2 授权码与 RBAC 权限设计,解决跨域认证、单点退出、令牌过期等痛点。支持自动续签、强制踢人、按钮级权限控制及分布式部署,适合中小团队快速构建高可用认证中台。项目已获 2.2k Star,代码开源,接入简单,是企业级应用的理想选择。[详情见 GitHub](https://github.com/a466350665/smart-sso)。
696 23
|
数据采集 人工智能 编解码
2025年颠覆闭源大模型?MonkeyOCR:这款开源AI文档解析模型,精度更高,速度更快!
还在依赖昂贵且慢的闭源OCR工具?华中科技大学开源的MonkeyOCR文档解析模型,以其超越GPT4o的精度和更快的推理速度,在单机单卡(3090)上即可部署,正颠覆业界认知。本文将深入解析其设计哲学、核心突破——大规模自建数据集,并分享实测体验与避坑指南。
2619 87
|
Linux iOS开发 MacOS
【已解决】ModuleNotFoundError: No module named ‘IPython‘
【已解决】ModuleNotFoundError: No module named ‘IPython‘
|
Ubuntu 网络协议 Linux
快速部署WSL(Windows Subsystem for Linux)
WSL提供了一种轻量级的方法,使开发者能够在Windows上无缝运行Linux环境。通过本文介绍的步骤,可以快速安装、配置和使用WSL,以满足开发和测试的需求。
3371 8
|
SQL 存储 分布式计算
大数据-157 Apache Kylin 背景 历程 特点 场景 架构 组件 详解
大数据-157 Apache Kylin 背景 历程 特点 场景 架构 组件 详解
443 9
|
机器学习/深度学习 IDE 数据挖掘
使用VScode的几点感受,对比Pycharm、Jupyter优劣势
使用VScode的几点感受,对比Pycharm、Jupyter优劣势
2363 5
|
负载均衡 前端开发 安全
BFE 初探
BFE 初探
552 9

热门文章

最新文章