语言的底层技术抽象

可能你用过很多语言,也可能你对他们很熟悉,那么对于开发者而言,语言的底层技术是什么?

c是一个语言的最小集合,如果你去看最早一版的c教程《The C Programming Language》,你会发现它的几个特点:

  1. 最接近机器的语言
  2. 语言的最小+最全集合

其它的语言,比如:java,python,lua,php,都是在c语言的基础上构建起来的,当然,它们提供了更多的语言特性,比如:元数据、反射、容器等。

那么,c的核心是什么?大概是函数。

假设我们定义了2个函数:

void a() {…}

void b() {…}

单从需求上来讲,可以将函数拓展成lambda表达式、或者是右值(被赋值给某个变量)、当作某个类的方法(本质上也是函数,只是函数名称有它新的规则)。

如果考虑a 调用b,那么这个就会变得有趣:

a调用b 它是由3部分组成:a、调用、b(a和b都可以是一组函数、调用可以认为是引用)。

对于a,b而言,这里面有要分两种情况:

如果b先出现,比如:有一组接口实现字符串的接口,那么a直接参考接口文档,调用即可。

如果a先出现,比如:chrome浏览器,它是可以写插件的,它的方式就是插件必须按照某种方式来写(协议)才能被集成到chrome里面;spring boot 容器,如果想注入到spring boot 里面,必须使用注解注入,比如:@Bean,@Controller,@Service等。

本质上来讲,a能成功调用b,是遵循某种协议的,一点协议有了,其实a和b谁先出现都可以。若是没有协议,那么显然会变得有些复杂。这里面体现了接口协议设计的重要性。

对于调用来讲,就比较有意思了。你会发现调用这个操作上也能做手脚,变得复杂。调用只能被拦截(AOP),否则就会影响a 和b,给它们增加负担。

无论拦截做到a,还是b端,ab至少有一个是被自动加载的(假设加载者为容器,所谓自动加载,就是生命周期被托管,只有这样,ab的容器,才能对调用做手脚。

一般对调用做手脚,应用场景为:b调用前后的日志打印、调用b的性能监控等;这里面有几种方案:b上加注解(spring boot)、按b的名字的前后缀(测试用例),b所在的包名称等等,主要是基于b的属性找规律;如果是加注解,则需要语言支持反射功能(java很早就有反射功能,真是有远见)。

总之,现在你看到的很多语言的特性,都可以抽象为a调用b这个场景,只是复杂化了。

生命的最小单位是生物

本文内容源自《人体简史》对细胞的介绍,纯靠脑洞展开。

生命的定义:生命的最小单位是生物,生物是由一个或多个细胞组成,能够新陈代谢,维持恒定性,可以成长,回应刺激,可以繁殖甚至演化,以适应外界环境,继续繁殖并产生后代[1]

人体由30亿个细胞组成,细胞是人体的最小单元。从细胞这么小的个体(细胞的平均直径在5—200微米之间。),组成人这么大的个体,绝对不是量变到质变那么简单。

拿汽车举例子,汽车没有生命,但是它是由很多个零件组成,小到螺丝,大到轮胎、底板,那些零件和细胞比,唯一的差别就是它们的大小相差太大,而且细胞小且有生命。既然是生命,就会和汽车零件有天壤之别。

汽车零件的组成方式是符合机械工程、力学等原理,但是多个细胞的拼装,生物学上尚未知晓其内在原理。这里面可以看出几点:

  1. 细胞的拼装,不像汽车零件的组装那么简单,一是由于细胞本身内部结构比较复杂,不像汽车零件(基本就是集中化学元素的叠加)。二是细胞之间的组合形式不像汽车零件靠的是力的传导。
  2. 细胞的尺度属于微观世界。微观世界有它不一样的运作规律,大尺度上的一些理论对它们不适用。其实,从细胞这个尺度往下,它们的工作方式已经不是那么显而易见了。或许,大尺度上你可以用公式推导,但是小尺度上,一个是确实比较复杂,另外一个就是,实验或者观察的装置到达了他们的极限。

如果想了解,细胞及细胞堆的工作原理,可能需要从下面几个方面着手:

  1. 改进实验的仪器。毕竟,微观上我们是“可以”观察的,但也许细胞级别的尺度,是人类的极限,不过不要紧,我们还有其它办法。
  2. 对细胞从宏观上做不同的实验,以推测微观上的原理。如果第1步行不通,那么只能“另辟蹊径”了。
  3. 科技的发展,给了我们有能力更好用计算机模拟细胞的工作。此办法原理就是基于抽象的公式推导,大胆的猜想,就好比天文学,不用做实现,纯想象。