傻子的一生,我们的一生。
“你知道什么是历史?历史就要告诉人什么是对,什么是错。这就是历史!”
作者沃尔夫勒姆利用自己开发的Wolfram语言创造了《降临(2016)》中的外星人语言
如果中间有一个“挤压”(squeeze),迫使一切都通过中间较少的神经元,那么通常可以使用较小的网络。[值得一提的是,“无中间层”(或所谓的〝感知机”)网络只能学习基本线性函数,但是只要有一个中间层(至少有足够的神经元),原则上就始终可以任意好地逼近任何函数,尽管为了使其可行地训练,通常会做某种规范化或正则化。
神经网络,至少以目前的设置来说,基本上是基于数的。因此,如果要用它来处理像文本这样的东西,我们需要一种用效表示文本的方法。当然,我们可以(本质上和 ChatGPT 一样)从为字典中的每个词分配一个数开始。但有一个重要的思想—也是ChatGPT的中心思想——更胜一筹。这就是“嵌入”(embedding)的思想。可以将嵌入视为一种尝试通过数的数组来表示某些东西“本质”的方法,其特性是“相近的事物”由相近的数表示
“计算机网络概论”图解趣味版,挺不错的极简科普书。
译者是周自恒。
附录 网络包的旅程
通过DNS查询IP地址的操作称为域名解析,因此负责执行解析(resolution)这一操作的就叫解析器(resolver)了。
一般来说,应用程序编写的操作内容是从上往下按顺序执行的,当到达需要调用解析器的部分时,对应的那一行程序就会被执行,应用程序本身的工作就会暂停(图1.12①)。然后,Socket 库中的解析器开始运行(图1.12②),完成应用程序委托的操作。像这样,由于调用了其他程序,原本运行的程序进人暂停状态,而被调用的程序开始运行,这就是“控制流程转移”®。
MTU:一个网络包的最大长度,以太网中一般为1500字节。
MSS:除去头部之后,一个网络包所能容纳的TCP数据的最大长度MTU: Maximum Transmission Unit,最大传输单元。—编者注
MSS: Maximum Segment Size,最大分段大小。TCP 和IP 的头部加起来一般是40字节,因此MTU减去这个长度就是MSS。例如,在以太网中,MTU 为1500,因此MSS 就是1460。TCP/IP 可以使用一些可选参数(protocol option),如加密等,这时头部的长度会增加,那么MSS 就会随着头部长度增加而相应缩短。判断要素就是这两个,但它们其实是互相矛盾的。如果长度优先,那么网络的效率会提高,但可能会因为等待填满缓冲区而产生延迟:相反地,如果时间优先。那么延迟时间会变少,但又会降低网络的效率。因此,在进行发送操作时需要综合考虑这两个要素以达到平衡。
尽管以太网经历了数次变迁,但其基本的3个性质至今仍未改变,即将包发送到 MAC 头部的接收方MAC地址代表的目的地,用发送方 MAC地址识别发送方,用以太类型识别包的内容。因此,大家可以认为具备这3个性质的网络就是以太网。
发送和接收同时并行的方式叫作“全双工”,相对地,某一时刻只能进行发送或接收其中一种操作的叫作“半双工”。
实际上,缓存服务器使用的代理机制最早就是放在客户端一侧的,这才是代理的原型,称为正向代理(forward proxy)。
我们前面介绍的服务器端的缓存服务器采用的正是这种方式,这种方式称反向代理(reverse proxy)。
缓存服务器判断转发目标的方法还有一种,那就是查看请求消息的包头部。因为包的IP头部中包含接收方IP地址,只要知道了这个地址,就知道用户要访问哪台服务器了。这种方法称为透明代理(transparent proxy)。
大约在1951年,一种名为“全员生产维护”(Total Productive Maintenance,TPM)的质量保证手段在日本出现。它关注维护甚于关注生产。TPM的主要支柱之一是所谓的5S原则体系。
5S哲学包括以下概念。
整理(Seiri),或谓组织(想想英语中的 sort 一词)。
整顿(Seiton),或谓整齐(想想英文中的systematize 一词)。
清楚(Seiso),或谓清洁(想想英文中的 shine一词)。
清洁(Seiketsu),或谓标准化。
身美(Shitsuke),或谓纪律(自律)。勒布朗(LeBlanc)法则:稍后等于永不(Later equals never.)。
窃以为单字母名称仅用于短方法中的本地变量。名称长短应与其作用域大小相对应。
我们想要让代码拥有自顶向下的阅读顺序。我们想要让每个函数后面都跟着位于下一抽象层级的函数,这样一来,在查看函数列表时,就能循抽象层级向下阅读了。我把这叫作向下规则。
关于实体变量应该放在哪里,争论不断。在C++中,通常会采用所谓剪刀原则(scissors rule),即所有实体变量都放在底部。而在Java中,惯例是放在类的顶部。
我们再次看到这两种定义的本质:它们是截然对立的。这说明了对象与数据结构之间的二分原理:
过程式代码(使用数据结构的代码)便于在不改动既有数据结构的前提下添加新函数;面向对象代码便于在不改动既有函数的前提下添加新类。
反过来讲也说得通:
过程式代码难以添加新数据结构,因为必须修改所有函数;面向对象代码难以添加新函数,因为必须修改所有类。
所以,对于面向对象较难完成的事,对于过程式代码却较容易,反之亦然!
在任何一个复杂系统中,都会有需要添加新数据类型而不是新函数的时候。这时,对象和面向对象就比较适合。另一方面,也会有想要添加新函数而不是数据类型的时候。在这种情况下,过程式代码和数据结构就更适合。著名的得墨忒耳律(The Law of Demeter)认为,模块不应了解它所操作对象的内部情形。如上节所见,对象隐藏数据,曝露操作。这意味着对象不应通过存取器曝露其内部结构,因为这样更像是曝露而非隐藏其内部结构。
更准确地说,得墨忒耳律认,类C的方法f只应该调用以下对象的方法:
• C;
• 由f创建的对象;
• 作力参数传递给f的对象;
• 由C的实体变量持有的对象。
方法不应调用由任何函数返回的对象的方法。换言之,只跟朋友谈话,不与陌生人谈话。最为精练的数据结构,是一个只有公共变量、没有函数的类。这种数据结构有时被称为数据传送对象(Data Transfer Objects,DTO)。DTO 是非常有用的结构,尤其是在与数据库通信或解析套接字传递的消息之类的场景中,在应用程序代码里一系列将原始数据转换为数据库的翻译过程中,它们往往是排头兵。
学习第三方代码很难,整合第三方代码也很难,同时做这两件事难上加难。如果我们采用不同的做法呢?不要在生产代码中试验新东西,而是编写测试来遍览和理解第三方代码。Jim Newkirk把这叫作学习性测试(leaming test)。
谁都知道 TDD 要求我们在编写生产代码前先编写单元测试。但这条规则只是冰山看看下列3条定律。
第一定律 在编写不能通过的单元测试前,不可编写生产代码。
第二定律 只可编写刚好无法通过的单元测试,不能编译也算不通过。
第三定律 只可编写刚好足以通过当前失败测试的生产代码。F.I.R.S.T.
快速(Fast)。测试应该够快。测试应该能快速运行。
独立(Independent)。测试应该相互独立。
可重复(Repeatable)。测试应当可以在任何环境中重复通过。
自足验证(Self-Validating)。测试应该有布尔值输出。
及时(Timely)。测试应及时编写。首先,构造与使用是非常不一样的过程。
软件系统应将起始过程和起始过程之后的运行时逻辑分离开,在起始过程中构建应用对象,也会存在互相缠结的依赖关系。并发是一种解耦策略。它帮助我们把做什么(目的)和何时做(时机)分解开。
Dave Thomas 和 Andy Hunt 称之 DRY 原则(Don't Repeat Yourself,别重复自己)。Kent Beck 将它列为极限编程核心原则之一,并称之“一次,也只一次”。Ron Jeffries 将这条规则列在第二位,地位仅次于通过所有测试。
所有较低层级概念放在派生类中,所有较高层级概念放在基类中。
我使用所谓“单个 switch”规则:对于给定的选择类型,不应有多于一个的switch语句。在那个switch语句中的多个case,必须创建多态对象,取代系統中其他类似的switch语句。
内容没有《编程珠玑(第2版)》好
书中例子主要使用的语言也是Awk,对现代程序员很不友好
Don Knuth给出了Fortran程序许多方面(包括性能监视)的经验研究。该论文中有一个被经常引用(而且常常是被错误地引用)的命题:“一个程序中不到4%的语句通常占用了一半以上的运行时间。”
“尾递归”:递归调用位于子程序的最后。通过把函数调用变成赋值和循环,可以消除尾递归。
测试只能证明程序有错误,而不能证明程序没有错误。—Edsger W. Dijkstra,得克萨斯大学
正确的判断来源于经验,然而经验来源于错误的判断。一Fred Brooks,北卡罗来纳大学
Little定律可以表述为“系统中的东西的平均数目等于这些东西离开系统的平均速度乘以每个东西离开系统所花费的平均时间”。(若系统的总体出入流是干衡的,离开速率也就是进入速率。)
尾递归:调用总是程序的最后一个动作。尾递归的程序总能转换成一个等价的while循环。