duangsuse::Echo
583 subscribers
4.12K photos
118 videos
579 files
6.13K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
https://ray-eldath.me/programming/three-important-ideas/ #statement #PLT
Ray: 我的一位朋友如此评论这些文章:他说真正理解抽象的唯一方式是通过抽象本身,而不是通过并不准确的类比。
「为了充分地("有用处"地)学习这些抽象,你必须去学数学,而不是通过一些糊里糊涂的文章,它们除了类比还是类比」
Dr: 要找到 “哪些代码遵循此抽象” 并不是必须的。像 Monad 这样的概念是非常抽象和通用的:它是一个描述了一套广泛的编程模式、数据结构、库和 API 的概念,其强大之处在于它们,是对如何设计和使用这种抽象的指导原则
成为高效的程序员并不需要理解全部的联系。其他人自然会强烈反对 :-)

Ray: "可仅仅知道 JavaScript 里的 Promise 本质上是 Monad,而 Functor “又是一个盒子” 并不能帮助你成为更好地程序员,而在你自己的库中使用这些词语只会让你的下游觉得不舒服"

...概念是非常抽象和通用的
等等,
逻辑学告诉我,抽象是通用的反面,就像社会是丛林的反面: 您的知识若是通用的,它一定能与各应用领域紧密联系,学生如何觉得它抽象!

人们就是讨厌空谈,所以设计各种简洁而通用的API;人民就是讨厌丛林,所以组织出了社会。 现在竟有人觉得存在通用抽象和丛林社会?? 这就像是说javadoc等机翻的玩意,比各种demo, test甚至产品更能展示项目的价值!
“靠代码行数来衡量软件功能的进度,就像是凭零件重量来衡量飞机制造的进度——Gates
靠知识点的难度衡量价值,同理。😅

我看这种观念者,确实是够抽象。 “类比”的本质是抽象,而「学习」只是用自己领域的思维,去「组合」「代换」出别人说的那种东西,带给你工具和知识图谱上的价值。
大家来到世上都是白痴,没有谁拥有无法被代换给别人的知识「原子」。写文爱用「未定义就使用的概念」,想设计新的抽象,却不谈理由?那就是 lier
无论我们用什么领域的「原子」组合出了CS的知识点,那都是潜在的价值,为空洞的术语绑定了新的语意,更摒弃了其中被“凭空捏造”的哲学。让IT人说话,天塌不下来!

难者,不会也。作者已死,凭什么说的道你就是「高等抽象」,大家能跟上的就是"糊里糊涂"的抽象? Einstein, Feynman 说物理的最前沿应该教高中生搞懂,难道你们的方法论比爱翁还科学?
人们给车设计的引擎,能达到原理极限的98%,那么 #CS 对IT的指导,除了让空指针反复造成十亿美元bug,就是让功能不变的软件,随着更新越来越臃肿和慢? 这算什么CS

Monad很图论,很优雅啊! 但它能从 x+1==2 得出x=1吗? does it run backwards?
数学的精度是无限的、数学的等号是有交换律的。 #Haskell 里有模式匹配,但有"Var(x)作为值"吗?
只要变量是值,模式匹配、类型推理、响应式,甚至函数的编译,就真是小孩都会写的栏大街了。让 let(['x','y'],a) 生成 x=a[0],y=a[1] 谁不会啊 也配叫语言特性
FP们连正反函数如 show-out(1, "1"); show(res, "1"); res==1 都没建模,无精度int、向量、矩阵和微分都不如numpy sympy,也好意思谈数学性? 起码把Fortran的矩阵搞明白再说吧

https://arendjr.nl/blog/2024/07/post-architecture-premature-abstraction-is-the-root-of-all-evil/#:~:text=achieved%20through%20a%20much%20simpler%20function
费曼家有一套《大英百科全书》,父亲常让费曼坐在他的膝上,给他念里边的章节。

有一次念到恐龙,书里说,“恐龙的身高有 25 英尺, 头有 6 英尺宽。” 父亲停顿了念书, 对费曼说,
“唔,让我们想一下这是什么意思。这也就是说,要是恐龙站在门前的院子里,那么它的身高足以使它的脑袋凑着咱们这两层楼的窗户,可它的脑袋却伸不进窗户,因为它比窗户还宽呢!”

就是这样, 他总是把所教的概念变成可触可摸, 有实际意义的东西。

“个体的经历,不过是一个庞大的(形式主义)系统下极其表面化的闪烁而已”

可那个闪烁对某一天的用户来说就是一切。 自然原理,亘古不变。如果只是发现他们就能改变世界? 工业革命可以提早数百年。
人一思考,上帝就发笑。 你们的抽象,永远概括不了现实的领域、具体的人所提供独有的组合与可能性。

知其变,守其恒,为天下式?
穷其变,悟不穷,以明我志!
不能为每个人产生普世价值,是理论的悲哀。
duangsuse::Echo
https://ray-eldath.me/programming/three-important-ideas/ #statement #PLT Ray: 我的一位朋友如此评论这些文章:他说真正理解抽象的唯一方式是通过抽象本身,而不是通过并不准确的类比。 「为了充分地("有用处"地)学习这些抽象,你必须去学数学,而不是通过一些糊里糊涂的文章,它们除了类比还是类比」 Dr: 要找到 “哪些代码遵循此抽象” 并不是必须的。像 Monad 这样的概念是非常抽象和通用的:它是一个描述了一套广泛的编程模式、数据结构、库和…
#PLT #learn 文中提到一个Futa对应关系(第一类二村映射 first Futamura projection), 展开讲讲还蛮有趣 🙉
首先,js人都会写计算器的,和 echo input/server 一样的难度

1+2*3
十(1, X(2,3)) -7

十=(A,B)=>A+B

这被称为「前缀式polish notation」,是Lisp的国是
教个小诀窍:js里函数只是一种字面常量,可以被for生成
Object.entries("十一Xノ").forEach(([i,x])=>
this[x]=eval(`(A,B)=>A${"+-*/"[i]}B`))


为了更像“语言”,可以用列表(进一步就是"1+2"的代码)实现语法,便于糖化
Eval([十,1, X,2,3]) -7
Eval=([f,...x])=>(!f.call)? [f,x] : //基线返回两项,递归就都是两项
(([A,b]=Eval(x),[B,c]=Eval(b))=>[f(A,B), c] )()


Monadic递归下降是这样AbBc的,因为不能右移流指针。不如逆波兰好看!不过这种程度的递归可以学学。

再看下「解释器interpreter」比计算器强在哪: 能够“在调用时传值”,也就是要有 argument[0] 这种“环境变量”
很厉害!现在有常数外的“语法”了,有变量了,高阶了!或许你需要学动态作用域(原型链?)、调用栈call-ret、惰性求值如&&|| blabla,还有深不可测的编译优化呢!

不就加一个箭头么。
十=(A,B)=> (env=>A(env)+B(env)) //现在知道为啥该用for生成函数?
Lit=x=> env=>x
Arg=i=> env=>env[i] //PHP写作 $x, 模仿bash的$1~$*
Fun=(n,f)=>f(Array(n).fill(0).map((x,i)=> Arg(i)))


env被称为运行时,它可以是JVM, import dis 或者别的bytecode解释器,这能减少tree-walk对递归栈的频繁依赖
这种 formSytanx.bind(consts=lit/arg/global/Types..) 的"部分传参"函数,称为编译器,而它的返回就是classFile等类型。
编译器并不需要与DSL这些技巧隔离,如果我们把 env=>x 写作 JSON(x) 而 env=>env[i] 写作$i ,既 Lit=x=> gcc? CBor.dumps(x) : (env=>x)
以这种人类或机器可读的结构序列化一些函数被"bind"到的lit,就得到了对应的代码。jvm的 lconst 1, aload_0 this参数, iadd (2->1)甚至是自动分配参数寄存器的!
https://www.yinwang.org/blog-cn/2014/01/04/authority#:~:text=partial%20evaluator。其实并不是特别神奇的东西,只需要在普通解释器里面改一两行代码就行,可是有人

二段求值。代码是流动的数据,内存是暂停的程序。本文甚至比赢王更直观: https://www.yinwang.org/blog-cn/2012/08/01/interpreter
定义个“元循环加法”吧?
十1=Fun(1, ([A])=>十(A, Lit(1)))
十1([232]) -233

//[Lit(f),x] 补丁下Eval"解析器"。计算器、解释器、编译器间,其实并非泾渭分明
Eval([十,1, X,2,X,1,3])[0]([2]) -7


如果你乐意,还可以支持基于全局表的递归 fib=f(x)=x<2? 1 : f(x-1)+f(x-2)
这一切都不会突破以上的定义框架。 If 不会,Call(f,x-1) 不会.. 这就是java的反射嘛。
我不想再写什么了。 我看过许多“编译原理书”,他们连这个=>都写不明白。 更何谈用Visitor实现(反)序列化 这些既理论又实践的approach
#haskell data Val=L Int|Op Char Val Val deriving(Show)
(Op '+' (L 1) (Op '*' (L 2) (L 3) ))

这类基于list或class{子类多型} 的 Eval(e=^^, env={proto:{..}}),与本文使用的闭包法是等价的。「闭包是穷人的对象」,Promise 给它暴露到了 obj.then(Continuation)

> 高阶的思想或许是本文的所有思想中最为重要的那一个 https://ray-eldath.me/programming/three-important-ideas/
你们知道函数的函数、类型的类型、语言的语法,却难以创造「语言中的语言」—跨越用途与界限而一致的语意。
我看numpy和 taichi-lang.org 就用的很好,比LLVM好一个世代
顺带一提,上文还使用了 Tagless FinalDe Bruijn 索引 😇 。只是…… 你甚至不需要知道它们的名字。([A])=> 经常被实现为KV["A"],但点明它的本质,却比写解释器更简单!

说到底,元编程也只是编程。就像“学会学习”只是一种策略,它对学习而言,并非例外情况。难者,不会也,譬如在谈"bind(x=1)后函数值字面是否改变"时提起「颗粒化curryArg」 当然会让人迷糊
node,graal会编译js,jvm代码(这也是为何Chrome页偶尔会segfault); JVM会使用汇编模板+JIT 的混合式优化,Cython则把“甜妹语言”翻译到C,LLVM则是个伪装成NodeGraph虚拟机的codegen
如果只用"是否该调用javac"来区分语言,认为C类型总比python更快的话,你会发现程序员钟意的都是freak!

宏,macro码可揉,是传入与生成class{}等字面的函数。和+-*/一样只是函数,而函数、类型,只是值,别被“静态分析”骗了,它们送你的class只是病态类型。
入,lambda栏目答,看x,A,B等栏目回答的算式
这点篇幅放前言都觉得寒碜吧? 可就是没人做到啊。 扶她投影?不知道的还以为是HP projector 的娘化版呢。。
PLT能对dev点化到的可谓寥寥, 但100%都是必要且急需的知识和"抽象",像Prolog的模板与响应式html编程("FRP") 什么的。 Monadic错误处理我不想吐槽什么,只能说不怕不识货,只怕和Kotlin比!

跑题了。当然,聪明的你会发现Fun的返回违背了"基线指明了递归的类型"这一原则,没生成 env=>
那C语言函数指针是这样的,env由*rbp[0:2]=[retRbp,retAddr]这些CPU变量提供,但JS里的闭包可以从env偷变量(Var作为值,mut ref),所以说「闭包是穷人的(单方法)对象」

C里还有"函数符号",那是由ld.so实现的全局表,让.o对象能先被mmap到任意地址,再去回填calls
真正的那个全局表叫 $PATH: ,以及没定义main的对象的 $LD_LIBRARY_PATH 。