递归(Recursion),搞计算机的人熟悉无比,外人却听起来就觉得陌生诡异,弟子规?
但递归解释起来很简单,甚至可以用一句话说明:递归就是指在定义一个概念和过程时,又用到了本身。
很多人小时候听过的这个无厘头故事就有递归的风味:从前有座山,山上有座庙,庙里有个老和尚对小和尚讲故事:从前有座山,山上有座庙,庙里有个老和尚对小和尚讲故事:从前有座山……
对递归的直观感觉是两重的,第一是简单,第二是荒谬。
简单,一句话就能解释清楚的东西。(可是计算机科学却把它当成一个宝,还整个这么别扭的名字,弄的多么高深似的,故弄玄虚,大气功师太极拳啊?)
荒谬,用自己定义自己,那不成了同义反复、循环定义了么,这在逻辑上都是有错的啊!一个过程自己包含自己,这个过程若执行起来的话,那不没完了么?
递归的妙用,恰恰就源自它看起来的荒谬之处。如果一个过程中又包含自身,那么这个过程就可以无穷地展开,不会在有穷的步骤后停止。但是描述这个过程只需要有穷的指令。以有穷表现无穷。
同时,又有办法控制这种似乎要停不下来的无穷过程。有效的递归过程中调用的自身,其实并不是完全相同的自身,而是一个“缩减版”的自身。多次递归反复调用后,这个自身可以渐次缩减成一个 base condition 或者说 base case ,不再继续递归,而返回一个确定的结果。这个“缩减”过程和 base condition 的不同设置,可以让递归过程展现出千姿百态(这也是使用递归的最大有趣之处,更有趣的是,这种设置的只言片语的改动能让运行结果有天壤之别)。
如此处理,让递归消除了看起来的荒谬之处,同时保留了“以有穷驭无穷”的巨大威力。难怪它会成为计算机科学中倍受喜爱的一个东东。 Alan Perlis 有言:
Recursion is the root of computation since it trades description for time.
递归的威力,实际上有更深刻的来源。
都知道计算机有一个理论模型——图灵机。随之而来的“图灵机等价”的概念,让人心智为之震撼。现在所有的计算设备,不管是强大的超级计算机还是玩具中几毛钱的小小芯片,理论上都可以归约为图灵机,都是“图灵机等价”的。它们本质上的计算能力都是一样的,一个设备可以被另一个设备模拟,无非是算的快点慢点。计算机之外,分子生物学本质上就是计算机科学, DNA 控制生命体生成的过程类似图灵机的运行,所以说,生命就是图灵机(?)。神圣的人脑是不是也只是一个更复杂的图灵机?很多人质疑,但也有很多人也相信是。有人甚至猜测,是不是万物都是图灵机?(有兴趣的人可以看一下 Charles Petzold 的《Annotated Turing》,这本书后面有一章的标题就是 Is Everything a Turing Machine?)
有意思的是,还有两个与图灵机等价(甚至更优秀?)的计算机理论模型:lambda 演算;递归。。。函数(递归又出现了!)。这种等价性在上世纪三十年代得到了数学上的证明,是当时数学上的一个重要成就。这种等价性意味着,图灵机具有的能力,递归函数也同样有,前面说的图灵机的种种,同样适用于递归函数!
那么,既然说图灵机不局限于计算机,万物都有可能是图灵机,递归是不是也不局限于计算机,万物中都有可能有递归现象?甚至,法律?
引子有点长,终于到达正题,下面说说两个我见过的法律中的递归现象(可能还有更多)。
一、判断公司股权是不是国有股
做中国境内公司法业务的律师都知道,这可是个十分重要的问题。公司股权一旦沾了国有色彩,与之有关的交易立刻笼罩着一种有毒的氛围,让参与者欲仙欲死。
但是长期以来,这个问题却一直处于晦暗不明的状态,有时让一些有经验的律师也拿不准。一些简单的情况当然没有任何疑问,比如三桶油各自总公司的股份,当然是国有股;但是一旦涉及到下层的子公司、孙公司、十八代孙公司,其中又混入了非国有投资,问题就变得不那么 trivial 了。
我一直认为,这个问题让人拿不准,除了因为法律法规的明文规定不够清晰(在 2016 年的《企业国有资产交易监督管理办法》出台后好多了),还在于判断规则中有递归的影子,让人们不太习惯。
判断某股权是不是国有股,等同于判断此股权的所有者是不是具有“国有资产所有者”的资格和属性。那么, 如何判断某个主体是不是“国有资产所有者”呢?规则如下:
- 如果此主体本身就是国家(某级政府本身或者代表政府行权的行政部门等非企业单位),则是;
- 如果此主体的控股股东(所谓控股股东是指合计持股比例超过 50% 的一个或者多个股东,或者持股比例虽未超过 50% 但属于第一大股东且可以实际支配此主体的股东)属于按照本规则判断的“国有资产所有者”,则是。
- 否则不是。
可以看到,规则第 2 步中调用了规则本身,属于递归。
如果写成python代码,那就是:
def is_state_asset_owner(entity):
if is_state_entity(entity): # 此主体是“国家单位”(政府或代其行权的非企业单位)
return True
else:
# 是否有合计持股比例超过 50% 的股东都是按本函数确定的“国有资产所有者”
for shareholder_combination in shareholders_combinations_of(entity):
if sum(share_percentage(shareholder, entity) for shareholder in shareholder_combination) > 50%:
if all(is_state_asset_owner(shareholder) for shareholder in shareholder_combination):
return True
# 是否存在某一本身是国有资产所有者的股东,其持股比例虽未超过 50% 但属于第一大股东,而且可以实际控制公司
for shareholder in all_shareholders_of(entity):
if is_state_asset_owner(shareholder) and is_top_shareholder(shareholder, entity) and able_to_control(shareholder, entity):
return True
return False
这个函数中用到的大部分子函数都很平凡,顾名思义就好了,不具体实现了;但是 shareholders_combinations_of 这个函数特别,需要解释一下。
为什么要用它呢?因为规则里需要用到控股股东这个概念,同时规则允许控股股东可以是多个股东的集合。那么就必须对全部股东进行各种可能的组合,对所有组合形成的股东集合作为可能的控股股东进行判断(这么说,这个算法的复杂度还是 O(N!) 呢,N 为此主体的股东数量)。这个函数的 python 代码如下:
import itertools
def shareholders_combinations_of(entity):
combinations = []
all_shareholders = all_shareholders_of(entity)
for combination_size in range(1, len(all_shareholders) + 1):
combinations.extend(list(itertools.combinations(all_shareholders, combination_size)))
return combinations
同时 is_top_shareholder 也实现一下:
def is_top_shareholder(shareholder, entity):
all_shareholders = all_shareholders_of(entity)
return share_percentage(shareholder, entity) >= max(all_shareholders, key=lambda x: share_percentage(x, entity))
以上规则和代码并非我信口开河,立法者有法规条文为证:
《企业国有资产交易监督管理办法》
第三条 本办法所称企业国有资产交易行为包括:
(一)履行出资人职责的机构、国有及国有控股企业、国有实际控制企业转让其对企业各种形式出资所形成权益的行为(以下称企业产权转让);
(二)国有及国有控股企业、国有实际控制企业增加资本的行为(以下称企业增资),政府以增加资本金方式对国家出资企业的投入除外;
(三)国有及国有控股企业、国有实际控制企业的重大资产转让行为(以下称企业资产转让)。
第四条 本办法所称国有及国有控股企业、国有实际控制企业包括:
(一)政府部门、机构、事业单位出资设立的国有独资企业(公司),以及上述单位、企业直接或间接合计持股为100%的国有全资企业;
(二)本条第(一)款所列单位、企业单独或共同出资,合计拥有产(股)权比例超过50%,且其中之一为最大股东的企业;
(三)本条第(一)、(二)款所列企业对外出资,拥有股权比例超过50%的各级子企业;
(四)政府部门、机构、事业单位、单一国有及国有控股企业直接或间接持股比例未超过50%,但为第一大股东,并且通过股东协议、公司章程、董事会决议或者其他协议安排能够对其实际支配的企业。
以上规则和代码实际上翻译了规定第四条的各项。不同的是,规定第四条的第(二)项与第(三)项实际可以合并,就合并处理了。
在头脑里模拟运行一下上面的代码,可以发现:对一个待判断主体,会通过递归逐渐追溯到它的“根股东”。这实际上正是现实中律师做法律尽职调查时理清股权结构、进行股东溯源的过程。
二、判断文物是不是可以合法交易的文物
即使不是律师或者潘家园古董贩子或者马亲王伯庸,可能也会有点模糊的印象:文物是个特殊的东西,买卖受很多限制,很容易就成了违法交易。
但是说文物完全不能交易呢,好像也不是。那么,什么样的文物可以合法交易?界限在哪里?判断规则是什么?有意思的是,在这个判断规则中,递归又出场了。
政府对文物交易的控制通过一定程度上的许可专营来实现,尽量把文物交易集中在经许可和监管的文物交易专门机构(文物商店或者拍卖行),在此之外的民间文物交易也不是完全禁止,但要求文物的来路必须正。
由此判断一件文物是否可以合法交易的规则是:
- 国有和馆藏的文物(即文物的所有者是国家或者文物收藏单位)不可交易。
- 文物交易专门机构(文物商店或者拍卖行)出售的文物视为可以合法交易的文物(当然前提是假设这些单位都守规矩)。
- 个人和其他单位的文物要合法交易,必须传承有序有据。要么是祖传,要么是从合法的前一手传承(买卖、互换、受赠)而来(想通过先占无主物原始取得文物所有权的人不用想了。就如同 49 年之后动物就不能成精一样,49 年之后新发现的文物默认归国家所有,不存在无主文物了,呵呵)。
那么这里就有一个问题:怎么判断是合法的前一手?也就是说怎么判断文物在前一手手中时是可以合法交易的?
仔细想想,那不就又回到了问题本身吗?
解决的方法很简单,就是调用这个规则本身!递归来拯救。
有人可能会问,这行吗?这不是循环论证吗?
并不是。
调用这个规则本身对前一手的合法性进行判断,这个过程中可能又对前一手的前一手也触发调用这个规则本身……似乎会无穷无尽。但是在这个链条的任何一个环节,如果能遇到 base condition(规则 1、规则 2 和规则 3 中的继承情形),这个链条就会中止,直接得出一个是否合法的结果,这个结果逐级反馈到最外层的规则调用中,最终得到了对当前所有者的判断结果。
所以,对循环论证的担心是不必要的,这个方法是有效的。
再上 python 代码:
def is_tradable_relic(relic, owner):
if isinstance(owner, 文物收藏单位 or 国家):
return False
elif isinstance(owner, 文物商店 or 拍卖行):
return True
elif acquire_way(relic, owner) in legal_non_trading_ways: # 继承等
return True
else:
prev_owner = previous_owner(relic, owner)
return is_tradable_relic(relic, prev_owner)
同样的有法规条文为证:
《文物保护法》
第五十条 文物收藏单位以外的公民、法人和其他组织可以收藏通过下列方式取得的文物:
(一)依法继承或者接受赠与;
(二)从文物商店购买;
(三)从经营文物拍卖的拍卖企业购买;
(四)公民个人合法所有的文物相互交换或者依法转让;
(五)国家规定的其他合法方式。
文物收藏单位以外的公民、法人和其他组织收藏的前款文物可以依法流通。
第五十一条 公民、法人和其他组织不得买卖下列文物:
(一)国有文物,但是国家允许的除外;
(二)非国有馆藏珍贵文物;
(三)国有不可移动文物中的壁画、雕塑、建筑构件等,但是依法拆除的国有不可移动文物中的壁画、雕塑、建筑构件等不属于本法第二十条第四款规定的应由文物收藏单位收藏的除外;
(四)来源不符合本法第五十条规定的文物。
三、其他
待各位读者发现并报告。。。
我发现,通过对这些规则的总结提炼和代码化,自己对这些法律规定的理解也更加精确深入了,这也再次应了 Alan Perlis 的这句话:
You think you know when you learn, are more sure when you can write, even more when you can teach, but certain when you can program.
来源:知乎 www.zhihu.com
作者:董成良
【知乎日报】千万用户的选择,做朋友圈里的新鲜事分享大牛。
点击下载