因为 Bilibili 莫名其妙吃回复,那就在这里存档。
原始内容见这里。
如无另行指定,默认回复 @LanceMoe。
预备 +TODO 改换文体,+FAQ 。
https://www.bilibili.com/video/BV16y41187mX/ | |
是否使用目录结构部署相对只是个次要的细节。但其它方面越想越罄竹难书,还是记个笔记(其实可以写技术报告,这里也就是提纲)吧。 | |
其实技术上来讲,现有的通用软件安装部署方案基本都是乐色,不是这里缺了一块就是那里多了一块,都不能满足全面一些的需求场景。 | |
还有PC和移动设备其实本来就不应该在这种层次上搞煋闻,除了嘲讽之前的方案残废然后搞了自己新的残废(TODO:插入xkcd多少来着.png)和刻意制造分裂形成生态护城河的错觉外完全没有技术意义。 | |
预测一下以后正常的方式吧:大概就是基于nix/guix store的形式集中分配存储池,然后mount出来目录。这样能精确控制权限,确保就算拉屎范围也有限保证用户(系统管理员)可控,开发测试规模部署都容易自动化,同时满足部署到不同物理安装介质的需求。 | |
现在这些屎的体验主要体现在以下一些方面: | |
1. 部署后映像和配置分离基本完全靠开发者自觉,然后多数开发者的素质难以支撑起这种自觉。 | |
大多数情况下,乱拉屎直接就是开发者不自觉的问题。失误了拉错地方是很少见的。 |
@Suddoo 你还真是 you can you up 惯了啊,是会自己做 λvC calculi(哦,你 Java 还不大配,没提供 continuations )的作业的程度所以自信爆棚了么?
不好意思,我都无中生有重新发明过 lexical-scoped FEXPR,还真看不上 lambda
当 primitive 的语言,更别说什么还要搞 object calculi 的煋闻的,特别还还要特设语法,居然默认还没 first-class function ……算了,给你科普太麻烦,省略鄙视链到 Java 的中间环节若干。
没点专业常识就闭嘴,OK ?
当然鄙视你不如鄙视 Gosling ,至少鄙视一些偏执设计思路(比如消灭多继承却无视 mixin 的需求)对大众有一些破除迷信伪劣权威的教宜,你就算被充分鄙视了又算老几能有啥影响?但是中间仍然有若干鄙视链差距,比如说也不如鄙视好歹还会承认 feel educated 的 GvR 。
挂婊这种程度的设计居然还需要打工?你打的什么黑工?
破案了。
TL;DR:
https://www.bilibili.com/video/BV1EW411u7th | |
12 集开始的一些讲法是给外行看的,实际上效果非常反计算机科学(姑且算是科学的话),尽管很多科班也是这么被误导的…… | |
注意抽象的目的不是为了提供一道从外面看起来简单的套娃,更重要的是相同的高层次接口可以对应底层不同的实现(最直接的做法:在 spec 里写上 unspecified ),允许 non-trivial equational reasoning ,使预期普遍的性质不会被破坏。例如,大部分情况下,(因为体系结构方法上的困难)具体的精确性能指标是一个计算机系统中没法纠结而被抽象掉的,这不会使计算机系统上的其它一些设计(例如支持的编程语言)失效。 | |
这个系列的视频没有澄清这个目的,所以容易让观众形成“高层的抽象仅仅是为了简化底层的实现”的错误认知。而实际的情况正好相反。像“程序”“算法”之类的概念,是数学模型定义的对象,机器的实现只是其中的一种。知道了一种实现,并不表示理解实质。 | |
这在个别概念上看起来不会有很大麻烦,但是在一个系统的课程中就很有问题。 | |
例如,“变量”基于指令式(imperative) 语言这种范型(paradigm) 讲解,会让人误认为变量一定能储存可变(mutable) 的值。这种讲法犯了缩小外延的错误,且并不是很难找到反例——例如 Haskell 的类型变量就不可变。“变量”的“变”是指变量绑定可变(variable) ,也就是一个变量名可以对应不固定的实体,而非储存的值可被修改——这也是传统上(数学)“变量”的含义。 | |
再如,“函数”被指令式语言的过程实现这种方式来讲,有很微妙的问题。更地道一点地用所谓计算机科学的讲法,应该是 lambda abstraction 这样的基本(primitive) 操作引入的结果。 | |
所谓的 loop 之类的 control operator ,而是组合 primitive 得到的 derivations 。从抽象的目的而不是实现上来讲,这应该是函数之后引入的东西。然而很遗憾,大部分语言是没有受过严格训练也没有多少想象力的计算机科学外行设计和实现的,这些语言提供的抽象往往弱到不足以让用户直接实现这样理所当然的组合(除非另外发明语言写解释器之类),所以以这样的语言入门的用户,在足够的补课之前,在这里很容易存在理解偏差。 |
imgui 不算正经的 retaining style GUI ,和图形库本身差距小,容易移植……代价是用户写 GUI 不爽了。 | |
https://www.zhihu.com/question/267602287 | |
咦汝装ice也是受害者、、、 | |
【抖M】幻の上帝 20:29:12 | |
…… | |
的确神烦、、 | |
【弱受】被子飞了 20:31:42 | |
“幻の上帝 20:29:37 查看原文 |
实现上我很难给出精确的具体标准。
但对适合“项目”维护和运营的基准,首先可以有一些普适的基本原则。
评价工具的理想程度,可以通过作为项目的主要产出而间接地适用。
幻の上帝 20:51:42 | |
* 模块化是模块化设计的单位,不必然是程序组织的单位。 | |
* 即便是程序中的实体,不同种类的抽象可以当作模块:函数、类、翻译单元…… | |
* 语言设计中直接抽象单一的模块不应该阻止用户使用不同层次的抽象实现模块化设计;并且,不应当添加心智包袱。 | |
* 这个意义上,语言中添加叫做“模块”的特性,本身就一种动机上的混乱。 | |
幻の上帝 20:53:35 | |
* 语言可以有模块系统,但根本上,至少在适合通用目的领域的语言中,匹配模块的粒度应该让用户而不是语言设计者替用户选择,因此所谓的模块至少不能作为内建的特性提供。 | |
* 通用目的语言可以有辅助构建模块系统的特性。这样的特性应该是可编程的,并且尽量对已有的特性友好——包括复用已有的特性,而不是引入新的、特设的(ad-hoc) 复杂规则。 | |
幻の上帝 20:53:41 | |
C艹这里反正统统不合格。 |
模块化设计的工具链(toolchain) 能适配多种源语言和多种目标语言。其中把源代码翻译成目标代码的工具统称为编译器(compiler) 。 | |
对现代的优化编译器(optimizing comipler) 来讲,基本原理是管道-过滤器(pipe-filter) 模式的代码变换(code transformation) 。 | |
典型简单情况下,从源语言的输入到目标语言的输出的流程是线性的,有相对固定的步骤。 | |
除了输入输出,这些步骤处理的形式统称 IR (intermediate representation,中间表示)。 | |
源语言一般是高级语言。适配源语言的编译器组件统称前端(frontend) 。前端把源语言翻译成能让编译器剩余流程接受的 HIR (high-level IR,高级 IR ) 。 | |
适配目标语言的编译器组件统称后端(backend) 。后端接受 LIR (low-level IR),输出目标语言代码。 | |
目标语言也可以是高级语言,不过更常见的,翻译成体系结构相关的硬件 ISA (instruction-set architecture ,指令集架构)支持的本机代码(native code) 。因为是硬件实现的, ISA 支持的二进制代码一般也叫机器码(machine code) 。 | |
粗略地说, ISA 指定了各种不同的硬件指令集,如 IA-32(x86) 、x86-64(Intel 64/AMD64)、IA-64(Itanium) 、ARM 、MIPS 等(实际上经常得适配指令集扩展)。 | |
编译器前端和后端之间的步骤有很大部分可以重用,不依赖前端也不依赖后端的逻辑独立出来成为单独的组件,称为中端(middle end) 。 | |
GCC 一开始是给 C 编译器 GNU C compiler ,不过后来逐渐支持不同的语言,因此需要不同的前端,改叫 GNU Compiler Collection ,里面是前端中端后端都有。 GCC 使用的 IR 有 GENERIC 和 GIMPLE 等。GCC 4 以来使用 SSA(static single assignment) 形式的 IR 进行优化。 |