duangsuse::Echo
补一句,为什么我那么在乎readXX() 首先,当然是它余缀了,Reader模式、Visitor模式需要加固定前缀是哪群大师教的?? Qt,luaY_parse 都没有这种文明 至少对 enum Op{Add(Op,Op); N(i32)} 写 visitAdd 的人绝对是py ast看多了,overloads不会用。 Java比C最主要的优势就是Type2namespace,居然有人主动添加余缀? 然后,是对编程界毫无进步的无奈。 我最初学编程时(8,9年前吧)改了一些c#小游戏,当时有 https…
duangsuse: #读写线 #bin #FP #algorithm
1.所以我认为这种partial是错的,比如lexer吧,至少把Node的wsPre 保留下来-比如对注释文档,这样rust fmt/doc也会好写很多。
2.你举得例子太tricky了,而且JSON就不是一种minimal dynKV- 它有一大堆无效的;, 需要过滤
3.内存buf问题应该交给linux swap处理,而且用 fit(inoutT参数) 替代read():T 并不会阻止windowing
4.所以只要在pull的回调里注册onmut,就能免费定义出writeback(),当然实践起来确实没那么简单
duangsuse:
冷知识: int** 可以被scanf读取
C是存在静态数组的,i=0..sizeof a/sizeof int
https://blog.csdn.net/GGN_2015/article/details/119902369
我们可以确定一个共识: readXX() 的本质,是通过ret和赋值stack var把file的一部分加载到mem的KV乃至于[]里,这也是为何libc的tcp和inode都是 iostream API --以及为何会jspy的人不懂C移植
因此,虽然它叫IO,却被框在call-return并赋值、 forEach-call并write 的枷锁里,明明只是asn.1那样的databind手段,却被递归下降的样板代码给框住了
但这种模式在C里,就是struct,set_type和set_size的递归下降,可以靠os的vm功能缓存、1次读完 mmap():bytes,当然任何新语言都没有直观对应出这个
如果有些struct var 是不需要读的,完全可以用 isDbg: 来mock自己读到了,然后不实际赋值,反正JS是动态的
对了,你觉得为啥js版bytes(blob,abuf) 都不提供流API
难道它是想让用户手写py structs那样的封装?
py有cString,jvm有Reader,js没有byte流接口;那就是只想read一个二进制header喽?
TextDecoder那个啊,感觉java味大
尤其是async*() ,不得不用State(var)取代吧
https://developer.mozilla.org/en-US/docs/Web/API/Streams_API
最大的功能就是补丁fetch()和onrequest ,其他和WebSocket重叠了
duangsuse:
额。。就是讲用回调的人为何被coro不明觉厉到了,呗
Object的本质就是可扩展的fn.bind()
打包好避免难传递
用回调的人根本没有错,错就错在coro.then为什么那么间接,还没人解读
不同的OOP还是有区别的,虽然大家的实质都是在提供参数N->1和if typeof 这些CLOS都懂的函数式风格的技术
但Java对closureArg 样板化的支持(通过重写和重载)更好,这也是为什么MBPC classdef比lisp的defclass有意义
往大了说语法差异都是没有意义的,无非就是alloca和malloc、递归下降、流水线这些算法嘛
另外,这还有个魔怔的中英emoji双语嵌入式编程支持原型链 def T.class(vars):ret{}
https://gitee.com/chen-chaochen/lpk#https://gitee.com/link?target=https%3A%2F%2Flosu.tech%2Fplayground
1.所以我认为这种partial是错的,比如lexer吧,至少把Node的wsPre 保留下来-比如对注释文档,这样rust fmt/doc也会好写很多。
2.你举得例子太tricky了,而且JSON就不是一种minimal dynKV- 它有一大堆无效的;, 需要过滤
3.内存buf问题应该交给linux swap处理,而且用 fit(inoutT参数) 替代read():T 并不会阻止windowing
4.所以只要在pull的回调里注册onmut,就能免费定义出writeback(),当然实践起来确实没那么简单
duangsuse:
冷知识: int** 可以被scanf读取
C是存在静态数组的,i=0..sizeof a/sizeof int
https://blog.csdn.net/GGN_2015/article/details/119902369
我们可以确定一个共识: readXX() 的本质,是通过ret和赋值stack var把file的一部分加载到mem的KV乃至于[]里,这也是为何libc的tcp和inode都是 iostream API --以及为何会jspy的人不懂C移植
因此,虽然它叫IO,却被框在call-return并赋值、 forEach-call并write 的枷锁里,明明只是asn.1那样的databind手段,却被递归下降的样板代码给框住了
但这种模式在C里,就是struct,set_type和set_size的递归下降,可以靠os的vm功能缓存、1次读完 mmap():bytes,当然任何新语言都没有直观对应出这个
如果有些struct var 是不需要读的,完全可以用 isDbg: 来mock自己读到了,然后不实际赋值,反正JS是动态的
对了,你觉得为啥js版bytes(blob,abuf) 都不提供流API
难道它是想让用户手写py structs那样的封装?
py有cString,jvm有Reader,js没有byte流接口;那就是只想read一个二进制header喽?
TextDecoder那个啊,感觉java味大
尤其是async*() ,不得不用State(var)取代吧
https://developer.mozilla.org/en-US/docs/Web/API/Streams_API
最大的功能就是补丁fetch()和onrequest ,其他和WebSocket重叠了
duangsuse:
额。。就是讲用回调的人为何被coro不明觉厉到了,呗
Object的本质就是可扩展的fn.bind()
打包好避免难传递
用回调的人根本没有错,错就错在coro.then为什么那么间接,还没人解读
不同的OOP还是有区别的,虽然大家的实质都是在提供参数N->1和if typeof 这些CLOS都懂的函数式风格的技术
但Java对closureArg 样板化的支持(通过重写和重载)更好,这也是为什么MBPC classdef比lisp的defclass有意义
往大了说语法差异都是没有意义的,无非就是alloca和malloc、递归下降、流水线这些算法嘛
另外,这还有个魔怔的中英emoji双语嵌入式编程支持原型链 def T.class(vars):ret{}
https://gitee.com/chen-chaochen/lpk#https://gitee.com/link?target=https%3A%2F%2Flosu.tech%2Fplayground
blog.csdn.net
使用C++#define进行循环与递归展开_define 循环-CSDN博客
文章浏览阅读1.8k次。疯狂的递归展开。_define 循环
橘橘橘子汁 & 🍊
https://zhuanlan.zhihu.com/p/707493606 虽然确实是可行的但是这是什么玩意😇
#您知道吗? #cs #dnn #wasm 计科长青树一瞥:递归下降、梯度下降 (1)
*编程的赞歌就是(组合compose)的赞歌,软工的伟大就是(复用reuse)的伟大!*
复用就是腾讯嘛!但,什么是组合?流行乐队是组合?
在《几何原本》里有这样一条公理:“整体”是由部分构造堆上去的。 无论物理的原子分子、化学的单质单剂、生物的组织系统、儿童编程的二分查找,甚至您编写的{语句}(算式) 定义表(),总少不了分治算法的影子;而与递归对应得最直观的树,除了带kwarg的视图描述树XML、文件夹管理和正则匹配的前/后缀树Trie、OIer的必修KMP图(: Trie+FailGoto),更有梗图里常被实现为SortedSetOrMap的红黑树RBTree(: AVL) --作为按int KHash()预分组K-V查找的一种补充。
不过,今天咱调戏的不是高深的算法或数理化,而是程序员的自我修养:表达式、解释、编译、类型检查和推理。
🤓不少语法看似是ES6,Kotlin,Java20+,C++里高深莫测的新特性,其实,只是因为它们的设计混乱带来的大误会! 软件工程界的基岩,原本很简单?
- 计算器🧮("1+1"):数据值 是不支持forif或(vars)=>函数/JSON文档的解释器,最简单的理解是 x=1; eval[+,1]。对内存的利用方式过于单一,就像🔑C语言的.o .so 只是靠LD互调用的object{static{}},或者VB一代难加函数的"红石命令",毫无扩展性还要另写头文件 自然被淘汰
- 解释📠("expr(1+1)"):值或行为 程序员唯一必须调用的接口。tree-walk(递归遍历算式)非解释器的专利、VM不是编译器的秘技。对x86汇编的执行也叫硬件解释,旧安卓通过转译arm汇编.so库到x86做兼容,就像IKVM对“JVM汇编”仍能再次转译到IL
- 编译 就是解释器的缓存📑:记住自顶向下遍历时的套路,直接自底向上组装值(lisp转RPN),很像二叉树vs(堆,一种树状数组)!这除了要重新实现重复/判定/ret&&break跳转的流控,还可将RPN栈指令集优化为局部读写-按类型复用。
要求手动编译的语言均属慢速原型,会标注或推理出类型签名,从而🔑以限界实现提速和多态(重写重载、记住变量名的指针,即担保栈size恒定)。 ANTLR等“状态机”编译器的输出便是自底向上,正好颠倒于主动read()流到js栈的PEG,不过,它们其实是慢的虚拟机。
类型的本质是简洁的🔑常量「黑盒测试」,它与表达式同构,执行方法也相同!
- 类型检查 就是只解释 def f(x:T):R 里":右侧"的算式,以插入 (f T R) 这样的SQL行。x编译后是arg[0]:一个空悬指针,但T.fns却是有血有肉的"反射"常量。把每个 x:T=1 换为 x=T!
x+x 的语意为查询 (+ T T)、1+"" 查找函数签名 (+ int str)、 u.id (.id User Ret?) 便能检查误拼写和空指针
不难发现,这些都是效仿numpy重载个运算符就能实现的,并不需要学编译原理写解析器!这也是 hamcrest.org http Test库断言组合器的原理
泛型class/fn/var和赋值 的推理规则是一样的。
例如把 <TR> as([Box, T], T=>R):R 与 as(Box(1), str) 深度重合时,新建两个TypeVar(void),它们会在 Int==T, R==str 的检查时被向上赋值,从而填充[Box,int]里的类型T、as调用里的R,并照顾到 i32->i64等转换及子类规则
同为编译期遍历,你还可以思考下 let[x0,x1]=a 如何被实现的,以及在运行期是否能模拟?
学习元编程有何好处🌝?因为可以从根源理解yield/await、纯函数、模式匹配、模板宏等“新”特性,凭什么能简化旧实践!
- 闭包和协程closure&coro 便是编译比解释好实现的两个特性。 compiler 通过{let;}的动态作用域(原型链..) 区分符号的LEGB来源(Local Enclosed外层局部 Global Builtin常量),从而能把 (x=>y=>x+y) 化为对象值 f_y=((x,y)=>).bind(x);Lua能查出跳转到表达式的指针,y=yield x 便能在return前,把函数的局部栈保存回 g.next/pr.then
- 模板constexpr 让闭包关于常量创建,如何? ((x,y)=>x+y).bind(1) 就是 1+y, ((k,s)=>s[read+k]() ).bind("Int") 就是readInt,*[map(print,0~9)] 就是循环展开,这些就是预处理的价值!反射和const只是对eval(并缓存)之「二段求值」的阉割
- 副作用effects #FP bros异常抨击print这种“无法被值存储的、有非局部干扰的赋值”并推广他们的赎罪券:Monad……这却是因为他们并不懂「定义式编程」!
React signal(x=0) (1) 就是一个不纯的赋值,但,它导致的x=1却能被广播为参数、被保存和复现!🔑这还能叫“状态变更泄露难题”么?
并且,它还偷走了"FP独有的模式匹配"。对赋值副作用的录制,更是bash,vimrc类格式经久不衰的原因
说准点,这些都是 #SQL 的老大Prolog所原创并推崇的-:变量作为值,逻辑式编程!
*整体大于局部;与另一结构重合的结构,之中的值相等 --几何原本*
⏳在通读本文时,也可以参考以下实例:
coroutine=由用户run()的线程
*调用栈是数组,协程栈是回调构成的链表
诸分治排序可视化
手动babel脱糖一个async函数
知乎:分词解析vs解释
实现一个HTTP DSL
Var(signalObj)如何跨越进程和网络:句柄、登录cookie、JWT
def(): return this 是何方神圣?
在解释时缓存代码的Tk GUI
Trie们和字典输入法的实现
关于class Visitor {se(e:Add_AB), se(e:Int)} 和Eval/Dump接口的融合
实现文本流递归下降、四则运算逆波兰、 JSON.org
Prolog binop #parser
计科原神:认识WASM/LLVM IR和JIT, webVM.io
*编程的赞歌就是(组合compose)的赞歌,软工的伟大就是(复用reuse)的伟大!*
复用就是腾讯嘛!但,什么是组合?流行乐队是组合?
在《几何原本》里有这样一条公理:“整体”是由部分构造堆上去的。 无论物理的原子分子、化学的单质单剂、生物的组织系统、儿童编程的二分查找,甚至您编写的{语句}(算式) 定义表(),总少不了分治算法的影子;而与递归对应得最直观的树,除了带kwarg的视图描述树XML、文件夹管理和正则匹配的前/后缀树Trie、OIer的必修KMP图(: Trie+FailGoto),更有梗图里常被实现为SortedSetOrMap的红黑树RBTree(: AVL) --作为按int KHash()预分组K-V查找的一种补充。
不过,今天咱调戏的不是高深的算法或数理化,而是程序员的自我修养:表达式、解释、编译、类型检查和推理。
🤓不少语法看似是ES6,Kotlin,Java20+,C++里高深莫测的新特性,其实,只是因为它们的设计混乱带来的大误会! 软件工程界的基岩,原本很简单?
- 计算器🧮("1+1"):数据值 是不支持forif或(vars)=>函数/JSON文档的解释器,最简单的理解是 x=1; eval[+,1]。对内存的利用方式过于单一,就像🔑C语言的.o .so 只是靠LD互调用的object{static{}},或者VB一代难加函数的"红石命令",毫无扩展性还要另写头文件 自然被淘汰
- 解释📠("expr(1+1)"):值或行为 程序员唯一必须调用的接口。tree-walk(递归遍历算式)非解释器的专利、VM不是编译器的秘技。对x86汇编的执行也叫硬件解释,旧安卓通过转译arm汇编.so库到x86做兼容,就像IKVM对“JVM汇编”仍能再次转译到IL
- 编译 就是解释器的缓存📑:记住自顶向下遍历时的套路,直接自底向上组装值(lisp转RPN),很像二叉树vs(堆,一种树状数组)!这除了要重新实现重复/判定/ret&&break跳转的流控,还可将RPN栈指令集优化为局部读写-按类型复用。
要求手动编译的语言均属慢速原型,会标注或推理出类型签名,从而🔑以限界实现提速和多态(重写重载、记住变量名的指针,即担保栈size恒定)。 ANTLR等“状态机”编译器的输出便是自底向上,正好颠倒于主动read()流到js栈的PEG,不过,它们其实是慢的虚拟机。
类型的本质是简洁的🔑常量「黑盒测试」,它与表达式同构,执行方法也相同!
- 类型检查 就是只解释 def f(x:T):R 里":右侧"的算式,以插入 (f T R) 这样的SQL行。x编译后是arg[0]:一个空悬指针,但T.fns却是有血有肉的"反射"常量。把每个 x:T=1 换为 x=T!
x+x 的语意为查询 (+ T T)、1+"" 查找函数签名 (+ int str)、 u.id (.id User Ret?) 便能检查误拼写和空指针
不难发现,这些都是效仿numpy重载个运算符就能实现的,并不需要学编译原理写解析器!这也是 hamcrest.org http Test库断言组合器的原理
泛型class/fn/var和赋值 的推理规则是一样的。
例如把 <TR> as([Box, T], T=>R):R 与 as(Box(1), str) 深度重合时,新建两个TypeVar(void),它们会在 Int==T, R==str 的检查时被向上赋值,从而填充[Box,int]里的类型T、as调用里的R,并照顾到 i32->i64等转换及子类规则
同为编译期遍历,你还可以思考下 let[x0,x1]=a 如何被实现的,以及在运行期是否能模拟?
学习元编程有何好处🌝?因为可以从根源理解yield/await、纯函数、模式匹配、模板宏等“新”特性,凭什么能简化旧实践!
- 闭包和协程closure&coro 便是编译比解释好实现的两个特性。 compiler 通过{let;}的动态作用域(原型链..) 区分符号的LEGB来源(Local Enclosed外层局部 Global Builtin常量),从而能把 (x=>y=>x+y) 化为对象值 f_y=((x,y)=>).bind(x);Lua能查出跳转到表达式的指针,y=yield x 便能在return前,把函数的局部栈保存回 g.next/pr.then
- 模板constexpr 让闭包关于常量创建,如何? ((x,y)=>x+y).bind(1) 就是 1+y, ((k,s)=>s[read+k]() ).bind("Int") 就是readInt,*[map(print,0~9)] 就是循环展开,这些就是预处理的价值!反射和const只是对eval(并缓存)之「二段求值」的阉割
- 副作用effects #FP bros异常抨击print这种“无法被值存储的、有非局部干扰的赋值”并推广他们的赎罪券:Monad……这却是因为他们并不懂「定义式编程」!
React signal(x=0) (1) 就是一个不纯的赋值,但,它导致的x=1却能被广播为参数、被保存和复现!🔑这还能叫“状态变更泄露难题”么?
并且,它还偷走了"FP独有的模式匹配"。对赋值副作用的录制,更是bash,vimrc类格式经久不衰的原因
说准点,这些都是 #SQL 的老大Prolog所原创并推崇的-:变量作为值,逻辑式编程!
*整体大于局部;与另一结构重合的结构,之中的值相等 --几何原本*
⏳在通读本文时,也可以参考以下实例:
coroutine=由用户run()的线程
*调用栈是数组,协程栈是回调构成的链表
诸分治排序可视化
手动babel脱糖一个async函数
知乎:分词解析vs解释
实现一个HTTP DSL
Var(signalObj)如何跨越进程和网络:句柄、登录cookie、JWT
def(): return this 是何方神圣?
在解释时缓存代码的Tk GUI
Trie们和字典输入法的实现
关于class Visitor {se(e:Add_AB), se(e:Int)} 和Eval/Dump接口的融合
实现文本流递归下降、四则运算逆波兰、 JSON.org
Prolog binop #parser
计科原神:认识WASM/LLVM IR和JIT, webVM.io
#think #web #tool
https://cssgridgenerator.io/
https://crocotile3d.com/
https://fixupx.com/Oroshibu/status/1808500235263418441?t=BtGGBHj9jnN2AReHW2VTWA&s=19
三視圖?
有趣的建模工具
帅啊!
螺莉莉的黑板报:
(๑•ㅂ•)و✧
https://dataset.wav.pub/
https://brython.info/demo.html
https://github.com/Distributive-Network/PythonMonkey
#py
螺莉莉的黑板报:
https://github.com/baskerville/plato/blob/master/README.md
你们 rust 真是啥都能干……
https://www.sea-ql.org/SeaORM/
这东西好用么……求教……
https://gitlab.com/coolreader-ng/crengine-ng
有趣的引擎
https://chinese-font.netlify.app/ font
https://typst.app/universe/package/bob-draw
#svg
https://ivanceras.github.io/svgbob-editor/
#code
duangsuse:
大量复制粘贴十分抽象
list有那么难用吗
难道你没注意到近十行只变了1个参数
AIGC也没脚本化得这么严重吧
我看还是用list first!null好了,这么八股文…… 大家现在都是用get null取代预判has的
这种到处预判的风格,很像你找大佬问问题,先发「您在不在」,他只好回个在,然后你不在线……
表达式化比你想的要多哦:
>Spring如何把 @Autowired T xx; 换为 var xx=find(T.class)
var Ts = [T.class].map( applicationContext::getBean);
你在class{}里加那一堆定义,如果只引用了一次,就完全不应该引用。 到底都是要查bean的
从code smell来看,只使用了1次的变量名是无效的;如果只是为了易读新建变量,只能证明你的helper fn命名的有问题
kt已经有!! 了,还想要更多
Java 一大特色,注解属于元数据,和函数调用有重大区别
duangsuse:
那这是定义“随用随扔”变量名的理由吗
函数和变量是这么用的?
java以省略[""] 为由引入太多常量复杂度的优化了,都要所谓框架来解决
纯粹是make compiler happy,把一个schema弄成它能读懂的class,然后再强转Any来构造class而已
js里一个字典让java用就是这么麻烦,其实能用几次呢? init完就扔了,根本不是性能瓶颈。
注解的本意,应该和py的 @decorator 一样,是接受class元数据的编译期函数才对
而不是等到运行时才去查什么field有哪些@属性 然后逐个.set()
要动态生成一个类型,来获取注入,简直无理取闹。 明明就该在编译期产生Registry.get&fillNew的样板函数
这是属于既把元编程的路封死了,还不让基于注解的注入框架提供统一的“反射”方法
其实jawa懂这个道理,但它偏偏就做得很烂,就会个@Override
duangsuse:
为了编译速度这也太幽默了,其实,jvm作为栈机 基本就是带类型签名的GNU dc计算器,不需要什么编译优化
如果递归下降一遍,校验下类型 生成个push call 就能花什么编译时间,属于是用PHP的方式搞算法了
而且javac的能力还远没有到c预处理器的程度,为了优化? 我看是他们不在乎程序/类定义的优雅性
什么序列化啊,也没有做规范,和py能 import json,yaml,toml,marshal 能比?就一个用来RPC的ObjStream,还被业界遗忘,哈哈
汤姆猫是大专必学
虽然汤姆猫的Biz程度也就比Node http-server强半点吧
所以问题就是Result类型为何没有重载 !!, 让它看起来仿佛只是带有错误消息是null
凭什么!! 只能校验 Type? 呢?
assert也是乐观/悲观路径
Exception也是,为什么不能一起判定了?
还非得搞个ifEmpty, ifBlank.. ifNullOrBlank..
莫名其妙
duangsuse:
这不是废话吗?例如买30天大会员,肯定是30* 24*60*60秒后失效,这才是世俗意义上的电脑时间
看到py关于时间和日期/时差有3个API
我就觉得抽象
audit就是一个不懂AOP的,其实unix可以靠strace审查syscall,win32的 sysinternals.com 也有进程日志功能
与其自己搞个无人知晓的轮子,不如封装别人的,两全其美
把OS的活都包揽了,难道py是要运行在Ring0把内核驱动都带上? 那必须支持啊
绷不住了,抽象程度直逼jawa
一开始就不该搞所谓orNull
默认 first{}!! 就够了
我在js里都是把Error视为object返回值的特例,和null是一个意思
这样就不存在什么orNull orElse的,catch表达式也免了
就是语言设计者对值体系的理解不过关,例如NaN就是numbers的null才对,而不是什么number?
这样才能用统一的方法去报错/换默认值
可悲的是一开始就没把悲伤/快乐路径当问题啊,真是异常搞心态
duangsuse:
幽默IDE
完全相信它的API有一大堆根本用不上的class
忸怩作态的软件没必要去维护
kcp是这样的,可 import ast 自 https://python-future.org 就没变过😋
py只是用:隔离一个表达式先于=执行,就实现了高贵语言们的静态检查
既可以用于静态分析,也能在运行时查看f.annotation ,完备的数据不需要反射
btw. 大佬应该会做一个DSL
Message.invoke{ id==mid }
Message.select{ id==mid }//多项
可是这种写法才是真正的SQL逻辑式
既然Msg(id=)能构造数据, Msg{id==} 就能查询
这不是很合理么 #kt
很简单,如果做得太标准,以至于移植到任何一门语言里都没必要修改的话
就没人给官方docs贡献流量了
duangsuse:
https://www.liuwj.me/posts/ktorm-introduction/
🤔 一个SQL函数.xml codegen 能被吹爆,还有人卖课是我没想到的
ES6里一句 sql${} 解决的东西,哈哈
「没想到他文化程度那么低」……
怎么会呢,语句能缓存,再怎么也比一次加载完dao好
你要是不喜欢,或者不相信语法糖有缓存,可以做成生成函数的形式
例如
updateId=f=sqlFn2{a,b-> Pair{B/b, A/a}}
f("bye",0)
所以说,如果你不相信DSL能被缓存,可以转为生成sql函数的形式啊
这不是MyBatis++ ?
https://github.com/JetBrains/Exposed/blob/main/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt#L184
我只能说,缓存键要么是调用点或次数
要么是函数
似乎很难单独缓存DSL对象,除非对它们的构造器
幸运的是, key eq x 里x的修改能缓存,因为它是参数
https://jetbrains.github.io/Exposed/frequently-asked-questions.html#q-how-to-get-a-plain-sql-query-which-will-be-executed
https://stackoverflow.com/questions/74821893/postgresql-arrays-instead-of-extra-table-in-a-many-to-many-relationship
涨姿势了,以后 1:N用数组json N:N用join
duangsuse: #fp
要是kt能允许编译期生成一部分表达式,就没这问题了😅😅😅
可惜啊, unquote{bash(q(trim("trimedStr")))} 这当然是lisp的专利
其中q() 被生成为一个字面量,就像闭包捕获:
fun bash(s)=trim(s).let:
paste {system(it)}
并没有所谓的编译期,因为编译器能访问所有lib API
0开销不是瓶颈问题,但事关语言的脸面
明明就很有用,可被一些人理解为「并非瓶颈的东西」
然后被rustc拿来完魔法
要我说他们就是傻屌,只不过是把闭包「捕获」的实现方式,改为内联字面量(unquote)
就能轻松突破编译、运行的动静边界,根本没有引入任何新API ,没有什么循环展开和 kotlinpoet javapoet的区别
他们做成什么样了? 正则的缓存还不如py的拿dict查😅
https://cssgridgenerator.io/
https://crocotile3d.com/
https://fixupx.com/Oroshibu/status/1808500235263418441?t=BtGGBHj9jnN2AReHW2VTWA&s=19
三視圖?
有趣的建模工具
帅啊!
螺莉莉的黑板报:
(๑•ㅂ•)و✧
https://dataset.wav.pub/
https://brython.info/demo.html
https://github.com/Distributive-Network/PythonMonkey
#py
螺莉莉的黑板报:
https://github.com/baskerville/plato/blob/master/README.md
你们 rust 真是啥都能干……
https://www.sea-ql.org/SeaORM/
这东西好用么……求教……
https://gitlab.com/coolreader-ng/crengine-ng
有趣的引擎
https://chinese-font.netlify.app/ font
https://typst.app/universe/package/bob-draw
#svg
https://ivanceras.github.io/svgbob-editor/
#code
duangsuse:
大量复制粘贴十分抽象
list有那么难用吗
难道你没注意到近十行只变了1个参数
AIGC也没脚本化得这么严重吧
我看还是用list first!null好了,这么八股文…… 大家现在都是用get null取代预判has的
这种到处预判的风格,很像你找大佬问问题,先发「您在不在」,他只好回个在,然后你不在线……
表达式化比你想的要多哦:
>Spring如何把 @Autowired T xx; 换为 var xx=find(T.class)
var Ts = [T.class].map( applicationContext::getBean);
你在class{}里加那一堆定义,如果只引用了一次,就完全不应该引用。 到底都是要查bean的
从code smell来看,只使用了1次的变量名是无效的;如果只是为了易读新建变量,只能证明你的helper fn命名的有问题
kt已经有!! 了,还想要更多
Java 一大特色,注解属于元数据,和函数调用有重大区别
duangsuse:
那这是定义“随用随扔”变量名的理由吗
函数和变量是这么用的?
java以省略[""] 为由引入太多常量复杂度的优化了,都要所谓框架来解决
纯粹是make compiler happy,把一个schema弄成它能读懂的class,然后再强转Any来构造class而已
js里一个字典让java用就是这么麻烦,其实能用几次呢? init完就扔了,根本不是性能瓶颈。
注解的本意,应该和py的 @decorator 一样,是接受class元数据的编译期函数才对
而不是等到运行时才去查什么field有哪些@属性 然后逐个.set()
要动态生成一个类型,来获取注入,简直无理取闹。 明明就该在编译期产生Registry.get&fillNew的样板函数
这是属于既把元编程的路封死了,还不让基于注解的注入框架提供统一的“反射”方法
其实jawa懂这个道理,但它偏偏就做得很烂,就会个@Override
duangsuse:
为了编译速度这也太幽默了,其实,jvm作为栈机 基本就是带类型签名的GNU dc计算器,不需要什么编译优化
如果递归下降一遍,校验下类型 生成个push call 就能花什么编译时间,属于是用PHP的方式搞算法了
而且javac的能力还远没有到c预处理器的程度,为了优化? 我看是他们不在乎程序/类定义的优雅性
什么序列化啊,也没有做规范,和py能 import json,yaml,toml,marshal 能比?就一个用来RPC的ObjStream,还被业界遗忘,哈哈
汤姆猫是大专必学
虽然汤姆猫的Biz程度也就比Node http-server强半点吧
所以问题就是Result类型为何没有重载 !!, 让它看起来仿佛只是带有错误消息是null
凭什么!! 只能校验 Type? 呢?
assert也是乐观/悲观路径
Exception也是,为什么不能一起判定了?
还非得搞个ifEmpty, ifBlank.. ifNullOrBlank..
莫名其妙
duangsuse:
这不是废话吗?例如买30天大会员,肯定是30* 24*60*60秒后失效,这才是世俗意义上的电脑时间
看到py关于时间和日期/时差有3个API
我就觉得抽象
audit就是一个不懂AOP的,其实unix可以靠strace审查syscall,win32的 sysinternals.com 也有进程日志功能
与其自己搞个无人知晓的轮子,不如封装别人的,两全其美
把OS的活都包揽了,难道py是要运行在Ring0把内核驱动都带上? 那必须支持啊
绷不住了,抽象程度直逼jawa
一开始就不该搞所谓orNull
默认 first{}!! 就够了
我在js里都是把Error视为object返回值的特例,和null是一个意思
这样就不存在什么orNull orElse的,catch表达式也免了
就是语言设计者对值体系的理解不过关,例如NaN就是numbers的null才对,而不是什么number?
这样才能用统一的方法去报错/换默认值
可悲的是一开始就没把悲伤/快乐路径当问题啊,真是异常搞心态
duangsuse:
幽默IDE
完全相信它的API有一大堆根本用不上的class
忸怩作态的软件没必要去维护
kcp是这样的,可 import ast 自 https://python-future.org 就没变过😋
py只是用:隔离一个表达式先于=执行,就实现了高贵语言们的静态检查
既可以用于静态分析,也能在运行时查看f.annotation ,完备的数据不需要反射
btw. 大佬应该会做一个DSL
Message.invoke{ id==mid }
Message.select{ id==mid }//多项
可是这种写法才是真正的SQL逻辑式
既然Msg(id=)能构造数据, Msg{id==} 就能查询
这不是很合理么 #kt
很简单,如果做得太标准,以至于移植到任何一门语言里都没必要修改的话
就没人给官方docs贡献流量了
duangsuse:
https://www.liuwj.me/posts/ktorm-introduction/
🤔 一个SQL函数.xml codegen 能被吹爆,还有人卖课是我没想到的
ES6里一句 sql${} 解决的东西,哈哈
「没想到他文化程度那么低」……
怎么会呢,语句能缓存,再怎么也比一次加载完dao好
你要是不喜欢,或者不相信语法糖有缓存,可以做成生成函数的形式
例如
updateId=f=sqlFn2{a,b-> Pair{B/b, A/a}}
f("bye",0)
所以说,如果你不相信DSL能被缓存,可以转为生成sql函数的形式啊
这不是MyBatis++ ?
https://github.com/JetBrains/Exposed/blob/main/exposed-core/src/main/kotlin/org/jetbrains/exposed/sql/Op.kt#L184
我只能说,缓存键要么是调用点或次数
要么是函数
似乎很难单独缓存DSL对象,除非对它们的构造器
幸运的是, key eq x 里x的修改能缓存,因为它是参数
https://jetbrains.github.io/Exposed/frequently-asked-questions.html#q-how-to-get-a-plain-sql-query-which-will-be-executed
https://stackoverflow.com/questions/74821893/postgresql-arrays-instead-of-extra-table-in-a-many-to-many-relationship
涨姿势了,以后 1:N用数组json N:N用join
duangsuse: #fp
要是kt能允许编译期生成一部分表达式,就没这问题了😅😅😅
可惜啊, unquote{bash(q(trim("trimedStr")))} 这当然是lisp的专利
其中q() 被生成为一个字面量,就像闭包捕获:
fun bash(s)=trim(s).let:
paste {system(it)}
并没有所谓的编译期,因为编译器能访问所有lib API
0开销不是瓶颈问题,但事关语言的脸面
明明就很有用,可被一些人理解为「并非瓶颈的东西」
然后被rustc拿来完魔法
要我说他们就是傻屌,只不过是把闭包「捕获」的实现方式,改为内联字面量(unquote)
就能轻松突破编译、运行的动静边界,根本没有引入任何新API ,没有什么循环展开和 kotlinpoet javapoet的区别
他们做成什么样了? 正则的缓存还不如py的拿dict查😅
cssgridgenerator.io
CSS Grid Generator
CSS Grid Generator - a user-friendly tool designed for web developers to effortlessly create customizable CSS grids for seamless web development.
duangsuse::Echo
>火之魔女: 不过unification我是想写好久了(应该按年计)但是一直没写的( https://github.com/duangsuse/mkey 写过,不过落后很久了 #sql 这算法就是 unify(a,b); unify(a,1); unify(1,a) 得出 a.v==1==b.v reify([a]) 解引用一下=[1] ,其实也挺有趣,包括npm也在牵强附会这玩意,真让人搞不懂从哪看的 http://minikanren.org/ 使用了一个自有的def: yield 实现,对 a&b…
#OOP #plt 学点设计模式
https://iota.huohuo.moe/OO-in-C.html#:~:text=一种设计模式对应一种语言特性%20%20By%20千里冰封
函数式人有许多「过度设计」,例如美
https://kotlinlang.org/docs/scope-functions.html
https://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html
但OOP也有自己的“私货”——用于弥补语法不足的“优雅的”设计模式
例如 Builder,Utils,Adapter,Delegate.. 它们是对this参数、对interface扩展不够灵活的变通
这个长文,我会用短 #kt demo 让大家看到 refactoring.guru 🐿收录的10种流行 Design Pattern 掩盖了哪些语言特性的缺失
以及科普"OVDEP" Observer Visitor(深先iterator) decorator(单参compose) EitherAB Proxy 等不逊色于箭头函数的,超越语言的优秀工具
## 创建性-Creational
这些模式是
1. StructBuilder
有一个很长的SQL row需要new,可以使用默认值,插入前也有检查
我们把构造器中A=x;B=y; 拆成
填完数据可能要验证,如编译期验证不可变
与它对立的是默认参数
和
K2
2. (Abstract)Factory
常见误区是,Factory类似
安卓 content.Context 与Button等View(ctx)的关系更像工厂的本意: 基于(操作系统)上文验证和保留数据
与它对立的是全局对象、元类trait。
全局fun弥补constructor钉死了 open fun 且难于校验的问题。当然!它也消灭了 object Singleton{} 和“双检锁”的样板
元类允许了 static (类名上)接口,而不是让可覆盖的函数代理一下构造器:
https://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngineFactory.html
3. Prototype
Linux对pwd等环境变量的fork()是最著名的原型模式,这使得父子进程间有了T1继承T 的关系
JS里
一切皆对象,除了 Object(1).valueOf() 里装了又拆箱的1。无原型的,只有更慢的
data class 会自动实现 fun copy(),但它不能继承,因为无法拷贝父类的变量。Java里很难把对象加构成更大的子类(除了 inner class)
按道理是x.A=1,那么Box(1)单例就是这些Pair的原型
https://iota.huohuo.moe/OO-in-C.html#:~:text=一种设计模式对应一种语言特性%20%20By%20千里冰封
函数式人有许多「过度设计」,例如美
kotlin.Any.let 其名曰 #FP Functor.fmap (Arrow-KT.io)。这种(私货+算法)的泛滥,给IT带来了灾难,让许多初学者不明觉厉,也当然不能提升其应用能力(毕竟只是"指针别名"嘛)https://kotlinlang.org/docs/scope-functions.html
https://www.ruanyifeng.com/blog/2017/02/fp-tutorial.html
但OOP也有自己的“私货”——用于弥补语法不足的“优雅的”设计模式
例如 Builder,Utils,Adapter,Delegate.. 它们是对this参数、对interface扩展不够灵活的变通
这个长文,我会用短 #kt demo 让大家看到 refactoring.guru 🐿收录的10种流行 Design Pattern 掩盖了哪些语言特性的缺失
以及科普"OVDEP" Observer Visitor(深先iterator) decorator(单参compose) EitherAB Proxy 等不逊色于箭头函数的,超越语言的优秀工具
## 创建性-Creational
这些模式是
new 构造器() 的变体,在Rust里被 fn new=Pair{A:1, B:2} 构造字面和 impl T for T1{} //mixin T1: T 混入取代1. StructBuilder
有一个很长的SQL row需要new,可以使用默认值,插入前也有检查
class RwCol2<A,B> {
var A:A?; var B:B?
constructor(x:A,y:B){A=x;B=y}
constructor(){A=null;B=null} //默认值
}我们把构造器中A=x;B=y; 拆成
newThis.A(x).B(y) 两个函数,就能实现初始值的解偶填完数据可能要验证,如编译期验证不可变
fun build()=this as Col2与它对立的是默认参数
和
RwCol2(0,0).apply {B=B+1}.B; buildList{} this参数上扩展 apply(T.()->*): TK2
value class{init{}} 也实现了构造后验证,不过大部分人仍在使用专门的反序列化和data verify框架2. (Abstract)Factory
常见误区是,Factory类似
Pair.of(1,2) 是为了重命名掉new,或者只把构造器集结起来: doc.createElement("div")安卓 content.Context 与Button等View(ctx)的关系更像工厂的本意: 基于(操作系统)上文验证和保留数据
interface DataJVM {
fun <A,B>List(a:A,b:B): Pair<A,B>
fun <T>List(vararg x:T): List<T>
}
val kt=object: DataJVM {
override fun <A,B>List(a:A,b:B)=Pair(a,b)
override fun <T>List(vararg x:T)=mutableListOf(*x)
}
//val py=object:DataJVM{}与它对立的是全局对象、元类trait。
全局fun弥补constructor钉死了 open fun 且难于校验的问题。当然!它也消灭了 object Singleton{} 和“双检锁”的样板
元类允许了 static (类名上)接口,而不是让可覆盖的函数代理一下构造器:
https://docs.oracle.com/javase/8/docs/api/javax/script/ScriptEngineFactory.html
3. Prototype
Linux对pwd等环境变量的fork()是最著名的原型模式,这使得父子进程间有了T1继承T 的关系
JS里
{} 等价于 {__proto__: Object.prototype} 函数表,函数表也可以随时添加继承。有 new.target 的构造函数()只是设置原型+赋值到this的简写一切皆对象,除了 Object(1).valueOf() 里装了又拆箱的1。无原型的,只有更慢的
Obj.create(null)data class 会自动实现 fun copy(),但它不能继承,因为无法拷贝父类的变量。Java里很难把对象加构成更大的子类(除了 inner class)
sealed class Box<T>(val A:T) {
inner class Pair(val B:T): Box<T>(A)
}
val x=Box(1).Pair(2)按道理是x.A=1,那么Box(1)单例就是这些Pair的原型
Kotlin Help
Scope functions | Kotlin
#ruby #plt Quine 编译接龙 https://www.fxzhihu.com/question/30262900/answer/47877068
https://www.ioccc.org/2012/tromp/hint.html #fp lambda 元循环 解释器(https://www.zhihu.com/question/30262900/answer/49589781
Quine(蒯恩)一般是指能打印出自身源码的程序
IOCCC,全称The International Obfuscated C Code Contest (国际难懂C代码大赛),顾名思义,是一场比谁能写出最“让人无语”的C代码的比赛。
btw. 同问题下有个 Shadertoy.com 类的C++答案,太丑了,把 vec3 拆成了RGB三个函数,代码重复率爆炸
还有两个中国特有的:
https://www.ioccc.org/2012/tromp/hint.html #fp lambda 元循环 解释器(https://www.zhihu.com/question/30262900/answer/49589781
Quine(蒯恩)一般是指能打印出自身源码的程序
_='_=%r;print (_%%_) ';print (_%_)IOCCC,全称The International Obfuscated C Code Contest (国际难懂C代码大赛),顾名思义,是一场比谁能写出最“让人无语”的C代码的比赛。
btw. 同问题下有个 Shadertoy.com 类的C++答案,太丑了,把 vec3 拆成了RGB三个函数,代码重复率爆炸
还有两个中国特有的:
curl --connect-timeout 1 https://google.com 2>&1 >/dev/null &&你在中国
body.contains("的")? "UTF-8":"GBK"。 \u{E79A84} 在GBK是鐨殑,很罕见
FxZhihu / Fixup Zhihu
有没有一段代码,让你为人类的智慧击节叫好? - @朴三世 | FxZhihu
mame/quine-relay · GitHub [图片] [图片] 突然发现已经100种语言了,想看50种语言的进50分支。 [图片] 璀璨无比谈不上,反正让我震惊了会儿,原来可以这样玩
duangsuse::Echo
看最近几条逆天,我要聊哲学 #CS 操作系统不就是4片3口虚拟化么 时间内存存储程序,网口线口板口 #os #plt #embed #recommend win,*nix,mac, aosp ios ;哪个不是只有这么点API和差异化 🦄?为了音视频和回应事件弄那么多框架外链新语法,不如3行 #web js。 像 bellard.org 那样的通才终究少数,搞出\0结尾无长度字串,连{}[]{type:}都没建模的libc算什么API啊?在位运算位flag上都被人打败 也配教人数据结构算法? 。 为这…
#FP #c https://github.com/hirrolot/datatype99/blob/master/datatype99.h macro
https://halfrost.com/reactivecocoa_macro/
tag union: enum { A(int) B(str) } in C 😨 无需任何编译器插件
implemented upon Boost/Preprocessor
冷知识: gcc 宏是可以通过CPS延长递归展开 到1024步的,而宏又包含 if defined/eq 等常规流控与##-concat等运算,意味着即便没有 template<> 魔法, for if 甚至 eval() 也可以 static_assert
ML99 是一门在 C99 预处理器运行的lisp https://metalang99.readthedocs.io/en/latest/list.html
尽管如此,有大佬说「元编程」要三思 https://lotabout.me/2018/think-twice-before-utilizing-meta-programming/
btw. 看到文心一言禁止F12, 有人贴了个反制 很有意思😂
利用宏展开和递归实现貌似不可能的链表处理,其实也只是手段巧妙,利用f.nArg这样的const拼接代码, 效果并不会比过程宏甚至简单的codegen好
我还是觉得,如果不限制工具链,编译期反射或运行期记忆化eval 比模板巧妙的多。 体操只是被编译器驯化的结果而已,比递归+模式匹配巧妙的算法有很多。
https://github.com/hirrolot/datatype99/tree/master/examples/derive
https://github.com/orangeduck/CPP_COMPLETE
https://netcan.github.io/2020/11/06/C-Rust元编程之BrainFuck编译器(constexpr-过程宏解法)/
完全有能力生成任意的vararg,并且可以加泛型
https://halfrost.com/reactivecocoa_macro/
tag union: enum { A(int) B(str) } in C 😨 无需任何编译器插件
implemented upon Boost/Preprocessor
冷知识: gcc 宏是可以通过CPS延长递归展开 到1024步的,而宏又包含 if defined/eq 等常规流控与##-concat等运算,意味着即便没有 template<> 魔法, for if 甚至 eval() 也可以 static_assert
// 9, 2, 5
static int lesser_than_10[] = {
ML99_LIST_EVAL_COMMA_SEP(
ML99_listFilter(ML99_appl(v(ML99_greater), v(10)), ML99_list(v(9, 2, 11, 13, 5)))),
};
// 用例: 1+(2+3)
datatype(
BinaryTree,
(Leaf, int),
(Node, BinaryTree *, int, BinaryTree *)
);
int sum(const BinaryTree *tree) {
match(*tree) {
of(Leaf, x) return *x;
of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs);
}
}
ML99 是一门在 C99 预处理器运行的lisp https://metalang99.readthedocs.io/en/latest/list.html
尽管如此,有大佬说「元编程」要三思 https://lotabout.me/2018/think-twice-before-utilizing-meta-programming/
btw. 看到文心一言禁止F12, 有人贴了个反制 很有意思😂
for (var i = setTimeout(";"); i-->0; clearTimeout(i)); 利用宏展开和递归实现貌似不可能的链表处理,其实也只是手段巧妙,利用f.nArg这样的const拼接代码, 效果并不会比过程宏甚至简单的codegen好
#define AND(X, Y) AND_##X##_##Y
#define AND_0_0 0
#define AND_1_1 1
#define IF_ELSE(C, T, E) JOIN(IF_ELSE_, C)(T, E)
#define IF_ELSE_0(T, E) E
#define IF_ELSE_1(T, E) T
#define IF(C, T) IF_ELSE(C, T, )
我还是觉得,如果不限制工具链,编译期反射或运行期记忆化eval 比模板巧妙的多。 体操只是被编译器驯化的结果而已,比递归+模式匹配巧妙的算法有很多。
https://github.com/hirrolot/datatype99/tree/master/examples/derive
https://github.com/orangeduck/CPP_COMPLETE
https://netcan.github.io/2020/11/06/C-Rust元编程之BrainFuck编译器(constexpr-过程宏解法)/
n=a=>a.length
add=(A,B)=>A+B
curry=(f, N=n(f)-1, ARG=Array(N).fill('').map((x,i)=>'_'+i) )=>eval(`p0=>(${ARG})=> ${f.name}(p0,${ARG})`)
curry(add)
p0=>(_0)=> add(p0,_0)
完全有能力生成任意的vararg,并且可以加泛型
GitHub
datatype99/datatype99.h at master · hirrolot/datatype99
Algebraic data types for C99. Contribute to hirrolot/datatype99 development by creating an account on GitHub.
duangsuse::Echo
码聋魅力时刻|面向运气编程
#os #fp #statement
从脚本单步,组合到程序,本来就可以实现为调用堆叠、回调链表 两种形式,和浏览器的历史栈一样,都是记得结果赋值到哪,组合数据结构 来解耦程序的“菜系”,形成API,提高表达力。
如果说 inc (Box n)=(Box n+1) 就是纯函数,而 box -inc; 隐藏了致命细节,这就是因小失大。FP不过是把赋值写入了栈上,还模糊了改写时复制/useMemo的时机。修语法=修语意?
js流行的 Reactive 不过是把 let [A,B]=match_XML(..) 从栈上拷下来,支持自定解构脚本,不是什么发明。类似这样狭窄的理解能力在做infra/做原理的人里比比皆是。
从脚本单步,组合到程序,本来就可以实现为调用堆叠、回调链表 两种形式,和浏览器的历史栈一样,都是记得结果赋值到哪,组合数据结构 来解耦程序的“菜系”,形成API,提高表达力。
如果说 inc (Box n)=(Box n+1) 就是纯函数,而 box -inc; 隐藏了致命细节,这就是因小失大。FP不过是把赋值写入了栈上,还模糊了改写时复制/useMemo的时机。修语法=修语意?
js流行的 Reactive 不过是把 let [A,B]=match_XML(..) 从栈上拷下来,支持自定解构脚本,不是什么发明。类似这样狭窄的理解能力在做infra/做原理的人里比比皆是。
为什么要区分调用和回调? 只是Stack内存和变量树的减枝,GC 绑定得太深,必须用 new SAM_POJO(..) 把 vars(let-locals+栈上临时cell) 甚至回调的行号(yield),外提为this,能跨越的范围才足够广,
比如能 JSON.load/dump,能放在IO轮询队列(甚至SQL)里,而不必元编程。 闭包和 Java 的 int vs Integer 装箱,完全一样。
例如把while(1)预处理成隔1毫秒yield一次的那种,和stdio行缓冲一个样,就要"pid"这个this了。毕竟……Linux-ELF就是个段错误版的.class,还不如WebAPI和esp32生态诚实。
因此,区分模块、功能点所必须的vars()树是绑定局部、参数、this、inline #def、模块KV/全局KV表? 都没有意义,前三者本来就是封装简化的核心,所以()=>和enum{Ok(), Err()}可能是对的,跨越了堆栈,没有boilerplates,但也可能是难以二次开发、层叠的元凶。
唯一的方法是从语意解构APIs,诚实的描述用户和开发者需要的模型,而不是生搬硬套拉丁文。
例如,能够热迁移一个pid,像老式游戏机一样存读档的 CRIU Docker 和真正的操作系统plan9,就很理所当然。 是硬件和二进制在拖后腿
那群家伙至今也不想承认没人真正在乎 i32 i64 的极值是多大,u32比i32好多少,对,就是搞出千年虫的那群nerd。为啥不叫 byte4 byte8 char4 好了? who cares?
或许这才是OOP和FP间选不出最优的最大原因:人群不同。
#py #FP 入演算 挺简单的介绍..
https://gist.github.com/vakila/3d5cebaebf01c4c77b289b9a0388e3c8
栏目答是「任何语言代码」背后的核心, 而编程的核心是自顶向下的组合代换,就像从[原子Atom]、生物学,到医学和人。 forif, 对应列表处理的 filterMap 都可以用"她🐑"实现!
ps. 图灵完备和 Turing Award 无关,意思是可以把 QEMU.org 移植到某个编程语言里面去,但没有声音图形和点按设备。 这显然不是评价语法-语意表现力和融恰度的指标。
#tool #recommend
https://github.com/jupyter/jupyter/wiki/A-gallery-of-interesting-Jupyter-Notebooks 很好玩的 awesome-list !
#learn 纪念我在7年前的「编程入门」博客
https://gist.github.com/duangsuse/519411ab618ee57350ee2df93d33f58e
https://gist.github.com/vakila/3d5cebaebf01c4c77b289b9a0388e3c8
栏目答是「任何语言代码」背后的核心, 而编程的核心是自顶向下的组合代换,就像从[原子Atom]、生物学,到医学和人。 forif, 对应列表处理的 filterMap 都可以用"她🐑"实现!
data🐑𝛌 栏目答 = 算式Sexpr |
Sym | Abst [Sym] 栏目答 | Args 栏目答 [栏目答] — ({? (rand) exit quit} 1) 是有效的,不用 (..).call(,1)
data Sexpr = Ln [Sexpr] | Int | Str | ... # 非Line即Atom
有别于计算器的关键点是「Sym的地址」。它不能是全局表的"key",而是类似AST树洞、 x=await,可以放东西,无论是否“求值”、等多久靠谁“求值”、在编译期或调用堆叠上“求值”,只配合SDK/ABI即可实现App的运行。 Abst是Absent的缩写,求值=对单步化简(reduce)的深先替换。
栏目答喜欢宣传 Currying(颗粒化传参 A=>B=>A+B) 和 “用回调层数编码数字”,但那只是数学家的把戏。 也有人把第一层参数 (A) 称为this.A或nonlocal A ,那很有价值。官方翻译是 free vars, unbound 或 closure (module 私有)
栏目答一般用于代数(组合逻辑),它和无语句函数是等效的 (整个 callgraph /API 都不能有语句和{基本块}!因此,全局 vartree 也都没必要 let mut 了)。 JSON,XML loaddump, ...DSL 都可以用栏目答编写,有运行期/编译期template<> 的也可以! 😋
在 computation theory (类似WiFi vs 无线电理论) 上,栏目答并不太「图灵完全」 ,就像许多类型推理器,但它解决了仅为了沙箱化 while(1) 而多开线程的麻烦,越来越多工业语言在应用她。 死循环可以写 letrec 伪递归(调用 YCombinator polyfill 解决纯函数禁止全局赋值+取值自身的毛病)
f=栏目答 x: x+1
f=Abst(narg=1,nlet=0, [十(Arg$(1), Const(1)), ]) #, ...以(x+1)为参数继续调用
def Const(json)(stack): json
def Arg$(n=1)(stack): stack[-1][n]
def 十(A, B)(stack): A(stack)+B(stack) # jvm 直接把A,B默认bind到了求值栈上,这里写明,只是为了避免误解
十=(A,B)=> dumpOpcode('iadd', stack=>A(stack)+B(stack) ) # 协议的「语意」是用ID保证代码的跨端同一
@ https://t.me/dsuse/21117
@ https://t.me/dsuse/21179
@ https://tomstu.art/hello-declarative-world#functions-and-relations #sql 是关系式编程?
ps. 图灵完备和 Turing Award 无关,意思是可以把 QEMU.org 移植到某个编程语言里面去,但没有声音图形和点按设备。 这显然不是评价语法-语意表现力和融恰度的指标。
#tool #recommend
https://github.com/jupyter/jupyter/wiki/A-gallery-of-interesting-Jupyter-Notebooks 很好玩的 awesome-list !
#learn 纪念我在7年前的「编程入门」博客
https://gist.github.com/duangsuse/519411ab618ee57350ee2df93d33f58e
Gist
Anjana Vakil, "Mary had a little lambda", OSCON 2018 (https://conferences.oreilly.com/oscon/oscon-or/public/schedule/detail/67384)…
Anjana Vakil, "Mary had a little lambda", OSCON 2018 (https://conferences.oreilly.com/oscon/oscon-or/public/schedule/detail/67384) & EuroPython 2017 (https://youtu.be/7Bsf...
❤1
duangsuse::Echo
#cpp 抽象大佬 打起来打起来! 😅 C++ 最终会被manba out ,因为它的「性能」也是伪命题 编程从来只有「功能点×算法」, 性能都是藏在API后面随便换 本来就只应该有值类型 只要不mut,就没有引用了 我说的只差一点,只要整个变量树不mut,不“一键”equals,就不存在值和引用 而且引用的语意本来是和Vue ref() 一样的单更改多赋值,不是什么单内存地址的概念 为了几个块设备上的地址搞那么多有意义吗,有种自己写个不需要memcpu虚拟化的裸机应用 ref:https://t.me/dsuses/5408
我感觉这群B友也还可以, 只是疑似有点极端了(虽然cpp届本身很抽象)
堆("json行"的内存/地址空间)、栈(调用堆叠) 不是什么x64ABI专属的, 是任何编程语言/#FP 都有的概念,只是被C++暴露相等性、begin<end(i<len) 这些1%的细节搞混了
https://drive.google.com/viewer?url=https://github.com/parallel101/course/raw/refs/heads/master/slides/memmodel/Presentation1MemModel.pptx
btw 翻译下段名:ELF对象的 text=fn rodata=lit data=rwlit bss=rw
他这个模型还不如说,是禁止指针运算和窄化宽化,从而只允许 &int, &const int 和CE修改器扫内存这样。 int[] 或元组对齐4 就很自相矛盾了,因为大端小端也属于实现细节,int可不是4byte之和
>但很多时候你必须懂实现,懂系统和编译器特定的细节才能Debug[热]你可以说cpp规范里没这么定义过,但工作里碰到crash,分析coredump文件,运行时调试,必须要知道这些具体实现,甚至可以说不知道这些“实现”不能算一个好的c/cpp程序员
网上大量的经验分享和教程都不是面向纯粹语言的,而是面向问题、面向一个具体的bug的。
如果按照你这种说法,那么咱们说网络根本没有TCP/IP这种东西,只有osi七层模型,根本别学tcp协议和各种网络库了,这是不是很可笑?
无论语言律师如何追求纯粹的语言之美,实际写程序就是很难脱离平台特定的功能。出了bug,你也不知道这个bug来自C++语言层面,还是编译器或平台特定的问题,只能挨个排查。遇到编译器或平台本身就不支持或不正确支持某个C++标准规定的功能可太正常了…
请勿变成语言律师,堆栈结构是常见实现,只是我们不该把实现和抽象混为一谈。同样的bs也在自己书里把自由存储区和堆这两个名词混用。
https://www.bilibili.com/video/BV1Wr421c7MN
btw. PPT尾部的问题,简单来讲就是:C 中数组是第二类公民,数组是不能直接传递的,而 Fortran 可以值传递数组。C 中必须使用指针传递数组,效率非常低,因为编译器永远假设两个地址可能存在重叠(缓存失效),有了 Strict Aliasing,至少类型不同的情况能实现零拷贝
堆("json行"的内存/地址空间)、栈(调用堆叠) 不是什么x64ABI专属的, 是任何编程语言/#FP 都有的概念,只是被C++暴露相等性、begin<end(i<len) 这些1%的细节搞混了
https://drive.google.com/viewer?url=https://github.com/parallel101/course/raw/refs/heads/master/slides/memmodel/Presentation1MemModel.pptx
btw 翻译下段名:ELF对象的 text=fn rodata=lit data=rwlit bss=rw
他这个模型还不如说,是禁止指针运算和窄化宽化,从而只允许 &int, &const int 和CE修改器扫内存这样。 int[] 或元组对齐4 就很自相矛盾了,因为大端小端也属于实现细节,int可不是4byte之和
国内编程界经典拿“底层实现”当“本质”的遗毒之一,其他的例子还有谈虚函数(甚至谈子类型多态)必须扯虚表,谈Promise必须扯事件循环等等。必须用这种朴素的还原论才能理解上层的性质吗…其实恰恰相反,并非底层的实现决定了上层的性质,而是上层的性质要求了底层如此(只是一种可能的)实现
其实现在的内存分配器早就不基于堆数据结构了(叫自由存储区还比这靠谱点),函数调用时也不保证总会生成一个栈(例如内联成功的函数),局部变量有时也会被优化到寄存器上,全局常量也可能被优化到不占常量区空间。如果仍然假定总会生成一个栈,容易写出未定义行为,导致程序出错,不如学习更加正规的c++内存模型:函数体内的普通变量是自动生命周期,定义时构造,函数体结束时(抵达}时)释放;全局变量是静态生命周期,程序启动时(进入main函数前或dll加载时)构造,程序退出时(离开main函数后)释放;new和delete管理的对象是动态生命周期,new时构造,delete时释放。c++内存模型和堆栈内存模型并不只是名称上的不同,主要的区别有:每个独立的变量之间有任意大的不可访问区域,自动生命周期的对象所占内存并不和栈一样保证向下生长,new/delete,new【】/delete【】和malloc/free不得混用。更严重的问题是,堆栈模型只是说对象存储在哪里,并没有说明对象的生命周期(构造和析构的时机):例如要了解func(string().c_str());是否安全,但用c++内存模型就很容易解释:c++规定,临时变量string()的生命周期限定于func这一行,直到分号前都是有效的,而堆栈模型根本没有说明这样的情况,string究竟存在堆上还是栈上,你想了半天,想到了string有“小字符串优化”,小于15字节时会存在栈上,但这对于回答“临时变量什么时候失效”毫无帮助,只是增加你的心智负担,最终还是要回归正规c++内存模型来学习。有人说如果报错“栈溢出”不还是说明还是要学堆栈吗?函数调用栈当然是所有支持函数语言都有的特性,这里的栈要了解,并不能等同于那个连函数调用约定都一清二楚的底层堆栈模型,那就过头了,解决“栈溢出”并不需要了解x86函数调用约定,正如你在python中遇到“栈溢出”不需要查看python虚拟机里的字节码一样,不要偷换概念。类似的概念有“因为linux系统会报segfault所以必须学段内存管理”,然而现代操作系统早已废弃了段式内存管理,而是采用分页内存管理,SIGSEGV实际上应该叫page fault,segfault只是个已经约定俗成没法改的别名而已,正如所谓的“堆内存”早已不是“堆”数据结构一样。
“底层八股文”对C++编程的“积极指导作用”:比如,我知道GCC编译器的实现中,函数调用通常都是x86的call指令实现的,call指令会压栈返回地址,由被调用函数的ret指令取出。所以,我可以通过对第一参数的指针-1,构造一个指针修改返回地址,这样就可以读取或修改返回地址了!比如,我知道Python中GIL阻止了多线程并行,所以我通过ctypes.memmove强行修改了Python解释器内存中的GIL对象,这样不就可以自由的多线程并行了!我真是个天才,然而,我开启-O1优化后,发现GCC编译器把这个函数内联了,没有call指令了,我读到的返回地址有误,并不能形成完整的ebp链表,我认为这肯定是GCC编译器的Bug,我们老师明明说过函数调用约定会压栈的!我通过魔改GIL开始在Python中自由并行后,发现结果混乱,最终Python解释器在一声SIGSEGV中崩溃了,我给Python官方提交了Bug反馈,谁让他们不支持无锁并发数据结构的!另外,通过一个变量魔改另一个变量这个事有原型的,并不是我编的,请看:https://github.com/parallel101/opengltutor/issues/29 小彭老师的教学过程中,不论是群里还是b栈上,依然能遇到大量的“底层八股文”受害者,小彭老师看不得受害者,可你一和他“耐心讲解”,律师帽子就扣上来了。
哗众取宠。用于内存分配的堆栈这两个词在某个特定语言的标准里没有提到,不妨碍这两个概念在许多语言的规范或实现里都存在,说白了就是一个大家都明白的、有助于理解底层原理的抽象,本来就不和某个具体语言绑定。Up 在视频里列出的 strict aliasing 相关的 bug,规范角度说是因为标准里对怎么访问一个对象有明确规定,不符合规定的属于 UB;实现角度上说是因为编译器没有像程序员想当然的那样将变量连续分配,或者做了进一步的优化,跟堆栈这些概念有什么关系?告诉你有个栈,变量在上面就一定是紧密排列?更何况C++23 的 STL 里面还有 <stacktrace> ,如何能说“C++没有堆栈”?
看 up 的评论,貌似还想树个靶子说堆栈这个概念会跟同名数据结构混淆?那首先栈它在逻辑上通常就是一个数据结构意义上的栈,至于 heap 的词源已经很难考证了,未尝跟 binary heap 没有关系,但至多也只是名字起得不好罢了,既学过 binary heap 又学过内存的 heap 的人不至于自己查资料澄清的能力都没有吧。
>但很多时候你必须懂实现,懂系统和编译器特定的细节才能Debug[热]你可以说cpp规范里没这么定义过,但工作里碰到crash,分析coredump文件,运行时调试,必须要知道这些具体实现,甚至可以说不知道这些“实现”不能算一个好的c/cpp程序员
网上大量的经验分享和教程都不是面向纯粹语言的,而是面向问题、面向一个具体的bug的。
如果按照你这种说法,那么咱们说网络根本没有TCP/IP这种东西,只有osi七层模型,根本别学tcp协议和各种网络库了,这是不是很可笑?
无论语言律师如何追求纯粹的语言之美,实际写程序就是很难脱离平台特定的功能。出了bug,你也不知道这个bug来自C++语言层面,还是编译器或平台特定的问题,只能挨个排查。遇到编译器或平台本身就不支持或不正确支持某个C++标准规定的功能可太正常了…
请勿变成语言律师,堆栈结构是常见实现,只是我们不该把实现和抽象混为一谈。同样的bs也在自己书里把自由存储区和堆这两个名词混用。
https://www.bilibili.com/video/BV1Wr421c7MN
btw. PPT尾部的问题,简单来讲就是:C 中数组是第二类公民,数组是不能直接传递的,而 Fortran 可以值传递数组。C 中必须使用指针传递数组,效率非常低,因为编译器永远假设两个地址可能存在重叠(缓存失效),有了 Strict Aliasing,至少类型不同的情况能实现零拷贝
duangsuse::Echo
#security CSP沙盒(tool)居然不是默认的? 任何一个富文本也可能导致 js/html 注入😒 这比C的 buffer[N] as code 牛逼多了😅 确如 yinwang.org 所说,把代码加个引号就当成数据、参数、用户输入,还在test出问题时"escape",怎么想的。 一开始就该用代码模板(ES6``)嘛 libc侧的RCE至少还能用 noexec/-fPIE 防一下,栈溢想利用就需要libc.so的地址,js呢,都是字符串…… CSP沙盒其实已经能弥补跨源访问的限权问题了。…
YouTube
Dear Functional Bros
Access experiments at CodeAesthetic.io
Discord, deleted scenes, song names and more at patreon.com/CodeAesthetic
Discord, deleted scenes, song names and more at patreon.com/CodeAesthetic
#post #bin #os lib.so是库对象?是C模块? 谈谈纯函数、全局表容器、Worker线程模型
随着React的火热,大家应该都听说过「纯」函数式编程(#FP) 这个规范了。纯意味着不更改变量和外部状态(例如stdIO),但它和 .c 的ABI(.o 和最终输出的 .so) 有啥关系呢?😅
在点出关联之前,我要发表一段很典的评论: 90%的PFer不懂FP。 考虑一个
pure fun 一词,不是说把所有 loop variant 存在栈上跳来跳去(伪递归tailrec),或是做 全局深拷贝+顺序执行转隐式this调用链("Monad") 的文字游戏就纯。
Haskell? 若要论“如何处理所有调用以 make dev happy”,Promise才是多任务届的顶流,CPS捕获栈帧闭包、捕获回调也不算什么。
😒 让我们重新 interface 纯函数: 不得破坏全局状态(可以复用执行容器); 默认单赋值(状态树集中,CPU缓存友好); 限制变量树的深层 &mut (即,值类型,==就是equals,根本不需要“地址相等”来优化Map.get,禁止地址)
换句话说,😅
当然啦,用
用 n=ref(0) 取代 mut n=0; 就更定义式了。它是真的数学组合器(n=1 vs 1=n, 代码也能有交换律),巨适合UI框架,能消除不少对可变量的需要。
但咱不在这里对 #FP 大做文章了。综上,FP没Reacter们想的那么抽象,到处加memo和freeze,它才是OOP的另一半或后继。
#AI锐评 https://x.com/i/grok/share/KlHa2s9CLU2VwnLH8kS3HvFnt
lib.so是库对象?是C模块? 这里就有了答案: .bss.size==0 and .tls线程局部==null 时是模块,否则模块也是新对象,和😝
点题了:如果你没绞尽脑汁的尝试把32G的游戏塞进8G内存里,这个区分确实很难理解。 但能理解\=能实现。
先说回libc生态。系统级单实例,0拷贝或CoW缓存,听起来很快! Web Workers 和 Rust 线程模型也都基于此。
它们使用
1. 顺应http微服务、Docker容器化的潮流,通过给消息id注册回调,即可实现+1CPU的请求响应或+N的计算集群,比pthread.join高到不知哪里去了😒
2. 每个线程都是变量隔离、代码共享的,不存在 @ThreadLocal 这类需求,无关于多线程、IPC、RPC,一次部署到处调用
3. 因为不隔离内存段,Worker进程间的协议非常好写且快 (aka. Actor模型)
但1个诅咒就足以让大家敬而远之了:
首先,共享运行时依赖树,并不能提升首屏速度,冷启动并非代码的瓶颈(除非 import jieba 等极端个例)。
而 py,js,lua,java,rb,... 包括它们依赖的DLL,这么多代码,怎么可能不做进程沙盒呢?
C 的模块和线程模型是脏的,不纯的,就像一开始没有提供HTML模板${}转义的PHP,也就像一开始没划分 ES Modules 的js。
让lib.so学习Worker,全局单实例,这不是处理 segfault,it sets your house on fire。 Vue服务端跨域请求污染如此,上文 setTimeout() 的id真的不隔离,又如何呢?😱
Shared Objects, 无疑是理想的,但真正能服务于系统上的所有App时,却需要一个函数白名单。
HTTP GET 其实就是纯函数的概念:它不改变状态,哪个源调用都能共享全局的cookie, 但是,就连tg大牛的BotAPI都破坏了这个约定。
从操作系统的职责看,真的需要跨源共享模块时,复制独立的 JSContext() 等全局环境或许不可避免,但可以用进程快照实现热替换;另一方面,编程语言也要接纳“默认final/const”的设定,而不是在(深拷贝vs浅拷贝)的鱼和熊掌上打折扣。
纯函数,更需要「化堵为疏」,就像OOP用this替代全局那样,去demo,并解决模块全局的开发体验痛点, 而不应将 Functional Programming 当神教或“银弹”去崇拜吧 ?😅
随着React的火热,大家应该都听说过「纯」函数式编程(#FP) 这个规范了。纯意味着不更改变量和外部状态(例如stdIO),但它和 .c 的ABI(.o 和最终输出的 .so) 有啥关系呢?
在点出关联之前,我要发表一段很典的评论: 90%的PFer不懂FP。 考虑一个
node &>/dev/null any.js 的环境,简单的 "log IO" 真的是“不纯的代码”吗? 请注意,stdout没法回环到原进程。pure fun 一词,不是说把所有 loop variant 存在栈上跳来跳去(伪递归tailrec),或是做 全局深拷贝+顺序执行转隐式this调用链("Monad") 的文字游戏就纯。
Haskell? 若要论“如何处理所有调用以 make dev happy”,Promise才是多任务届的顶流,CPS捕获栈帧闭包、捕获回调也不算什么。
换句话说,
def y(x): n=x*2; n=n+1; OK(n) 等效于是纯的,因为等号对变量的修改可以inline(n=2x+1) ,甚至 id=setTimeout(继续,1s) 也是纯的,因为每个app拿到的id并不会互相影响, random()>0.5 也是纯的,因为随机seed能被进程级重放…… 让我们用本质而非「字面形式」理解这些新概念(yinwang.org ...)当然啦,用
chkstk=(n, r=0)=>(n==0)? r : chkstk(n-1, r+1) 代替含糊不纯的 for(r=0; n!=0; n--,r++){} 在理论上很赞(哪怕是死递归,都比随手卡死调用栈 or libuv 的while(1)可控,因为有闭包!)用 n=ref(0) 取代 mut n=0; 就更定义式了。它是真的数学组合器(n=1 vs 1=n, 代码也能有交换律),巨适合UI框架,能消除不少对可变量的需要。
但咱不在这里对 #FP 大做文章了。综上,FP没Reacter们想的那么抽象,到处加memo和freeze,它才是OOP的另一半或后继。
#AI锐评 https://x.com/i/grok/share/KlHa2s9CLU2VwnLH8kS3HvFnt
大家应该没听说过 .c 编译产生的 .o ELF 是什么结构。好,我们看看:
`file /lib/libcurl.so*`
/lib/libcurl.so.4.8.0: ELF 64-bit LSB shared object, dynamically linked
`readelf -Sh $_ |tbl-hl 'text=代码;rodata=字面量;bss=mut全局;data =val全局;dynsym=dlopen函数链接;'`
注意, PROGBITS 代表这一个Segment是系统级单实例的,仅存的 .bss:NOBITS 会在库构造器里'\x00' malloc,剩下的都被C虚拟机无视,只用于 gcc,gdb,pref 除错。
AI展开: https://x.com/i/grok/share/jyixQkW0SNiIKtpGboy5LFUsG#:~:text=Linux%20动态%20PIE%20进程执行的绝对核心,
中科大真人快打: https://lug.ustc.edu.cn/wiki/user/boj/linkers-and-loaders/#38-目标文件中的数据结构
#tool 高亮注释
`tbl-hl() { sed -E "$(sed -E 's|([^=]+)=([^;]*);|s/\1/\x1b[38;5;208m\1\x1b[0m(\2)/g;|g;' <<<$1)"; `
lib.so是库对象?是C模块? 这里就有了答案: .bss.size==0 and .tls线程局部==null 时是模块,否则模块也是新对象,和
__import__('numpy').sys.argv 一样。点题了:如果你没绞尽脑汁的尝试把32G的游戏塞进8G内存里,这个区分确实很难理解。 但能理解\=能实现。
先说回libc生态。系统级单实例,0拷贝或CoW缓存,听起来很快! Web Workers 和 Rust 线程模型也都基于此。
它们使用
post_onMessage队列 + SHM共享状态(SharedArrayBuf) 多线程互调,性能和安全兼顾,有3大好处1. 顺应http微服务、Docker容器化的潮流,通过给消息id注册回调,即可实现+1CPU的请求响应或+N的计算集群,比pthread.join高到不知哪里去了
2. 每个线程都是变量隔离、代码共享的,不存在 @ThreadLocal 这类需求,无关于多线程、IPC、RPC,一次部署到处调用
3. 因为不隔离内存段,Worker进程间的协议非常好写且快 (aka. Actor模型)
但1个诅咒就足以让大家敬而远之了:
首先,共享运行时依赖树,并不能提升首屏速度,冷启动并非代码的瓶颈(除非 import jieba 等极端个例)。
而 py,js,lua,java,rb,... 包括它们依赖的DLL,这么多代码,怎么可能不做进程沙盒呢?
C 的模块和线程模型是脏的,不纯的,就像一开始没有提供HTML模板${}转义的PHP,也就像一开始没划分 ES Modules 的js。
让lib.so学习Worker,全局单实例,这不是处理 segfault,it sets your house on fire。 Vue服务端跨域请求污染如此,上文 setTimeout() 的id真的不隔离,又如何呢?
Shared Objects, 无疑是理想的,但真正能服务于系统上的所有App时,却需要一个函数白名单。
HTTP GET 其实就是纯函数的概念:它不改变状态,哪个源调用都能共享全局的cookie, 但是,就连tg大牛的BotAPI都破坏了这个约定。
从操作系统的职责看,真的需要跨源共享模块时,复制独立的 JSContext() 等全局环境或许不可避免,但可以用进程快照实现热替换;另一方面,编程语言也要接纳“默认final/const”的设定,而不是在(深拷贝vs浅拷贝)的鱼和熊掌上打折扣。
纯函数,更需要「化堵为疏」,就像OOP用this替代全局那样,去demo,并解决模块全局的开发体验痛点, 而不应将 Functional Programming 当神教或“银弹”去崇拜吧 ?😅
Please open Telegram to view this post
VIEW IN TELEGRAM
#post #FP “袋鼠”Effect和新语言问题
Algebraic Effect 很像Java的“强类型Exception” `signature f(): (Int|throws Exception)`,就像袋鼠一样,把所有可能冒泡(不截获)的事件都装进去。
但“效应器”也提供了依赖注入选项。如 throw GET() 可以搭配 `catch(GET){yield "async"}`,这样,FP Monad/IO 到处乱窜的毛病就终于被OOP“修正”了,而且“似乎”没有折损原来的逼格(好吧,其实就是implicit参数,全局状态可变)
作为近两年开始流行的新语言特性,Unison, 仓颉 都支持了效应捕获的语法
yin谈新语言问题时是针对稀奇古怪的语法的,但我觉得新语言支持新“范式平台”是一个积极的方向
问题在于,Effect 这种编译期依赖注入是否真的弊大于利,并且值得认知成本。 “强类型Exception” 本身就是有问题的
(你见过哪个Web应用“区分”错误?粗粒度的 try{} 和提供defaultValue/fallbackOp的困难本就是在掩盖问题,那应该和null-safe一样简单)
新语言必须认真考虑特性平台的不可替代性,而不是不断推翻旧版本的“新语言”。
https://chat.librechat.ai/share/bckpHUUNhYtWu12gsDE4W
ps.基础知识: https://chat.librechat.ai/share/aagQswVYQZ4mp4oXTABRc
Algebraic Effect 很像Java的“强类型Exception” `signature f(): (Int|throws Exception)`,就像袋鼠一样,把所有可能冒泡(不截获)的事件都装进去。
但“效应器”也提供了依赖注入选项。如 throw GET() 可以搭配 `catch(GET){yield "async"}`,这样,FP Monad/IO 到处乱窜的毛病就终于被OOP“修正”了,而且“似乎”没有折损原来的逼格(好吧,其实就是implicit参数,全局状态可变)
作为近两年开始流行的新语言特性,Unison, 仓颉 都支持了效应捕获的语法
yin谈新语言问题时是针对稀奇古怪的语法的,但我觉得新语言支持新“范式平台”是一个积极的方向
问题在于,Effect 这种编译期依赖注入是否真的弊大于利,并且值得认知成本。 “强类型Exception” 本身就是有问题的
(你见过哪个Web应用“区分”错误?粗粒度的 try{} 和提供defaultValue/fallbackOp的困难本就是在掩盖问题,那应该和null-safe一样简单)
新语言必须认真考虑特性平台的不可替代性,而不是不断推翻旧版本的“新语言”。
https://chat.librechat.ai/share/bckpHUUNhYtWu12gsDE4W
ps.基础知识: https://chat.librechat.ai/share/aagQswVYQZ4mp4oXTABRc
duangsuse::Echo
作为近两年开始流行的新语言特性,Unison, 仓颉 都支持了效应捕获的语法
GitHub
cangjie_stdx/doc/libs_stdx/effect/effect_package_overview.md at a7c43d44381a995262ac93ba56dce66090613269 · cangjielanguage/cangjie_stdx
Contribute to cangjielanguage/cangjie_stdx development by creating an account on GitHub.
https://x.com/i/grok/share/ZBRA0vtJcBzGQpq9KQd56pJPu #FP #haskell
很好,以前ohos是滥竽充数,现在都会“妄自菲薄”了。 本来就和JDK没的比,新特性还要到字缝里去翻,不是 🤡么? Rust好歹是原神呢😅
让各位看看外行写导论会写出什么幺蛾子来: https://zhuanlan.zhihu.com/p/76158581
我以前就是看的这种,纯浪费时间么,还不如蛤为仓颉的客座沙龙
我决定不把Effect归化到我的编程语言里去,技术细节见 #ai探讨 https://chat.librechat.ai/share/tPbd15iaCJ9_DMQNy7KuW🤯
#ai对比 https://chat.librechat.ai/share/mEcMHpAc4j_v3HYn4fzwA
😒 Kimi 这次有用多了,重要的是便宜
很好,以前ohos是滥竽充数,现在都会“妄自菲薄”了。 本来就和JDK没的比,新特性还要到字缝里去翻,不是 🤡么? Rust好歹是原神呢
https://gitee.com/HW-PLLab/pllab_slides/raw/dev/WechatOfficialAccSlides/20221123-EffectHandlers从函数式编程到系统级语言-by-DanGhica.pdf#page=8
https://github.com/cangjielanguage/cangjie_stdx/blob/a7c43d44381a995262ac93ba56dce66090613269/doc/libs_stdx/effect/effect_package_overview.md
让各位看看外行写导论会写出什么幺蛾子来: https://zhuanlan.zhihu.com/p/76158581
我以前就是看的这种,纯浪费时间么,还不如蛤为仓颉的客座沙龙
我决定不把Effect归化到我的编程语言里去,技术细节见 #ai探讨 https://chat.librechat.ai/share/tPbd15iaCJ9_DMQNy7KuW
#ai对比 https://chat.librechat.ai/share/mEcMHpAc4j_v3HYn4fzwA
Algebraic Effects(AEff) 是最近纯函数式PFer的动向,用于替代各种Monad。这其实是PF对“易变现实”的很大让步了
就像不理解 “伪递归=改参跳到def开头重来”,PF非常在意“堆变量不纯,栈变量不纯,参数变就纯”的无聊形式,于是就有了 `{IO,State,Random} Monad` 这些“纯粹的参数”,组合出Monad jQuery式的调用链,就叫“do语句块”
`State(0).fmap(u=>u+1)` 其实就是 `Var(0).then(u=>u+1)` ,因为u+1那块可以调用另一个“广义Promise”,就有了 `flatMap(async(u)=>u+1)` ,这就是染色问题(没错,这正是 #Haskell Logo >>= !)
flatMap的语意在List上很怪异,但对await这种Effect是必要的,记住:这个“盒子”不能拿 Var(wtf).v ,它只能 Var(wtf).then(cps) ,那么cps返回Var就会扰乱后续链!当然Monad有一套“Algebra而惧吧”的文字游戏(比如foldMap),这里只提applicable。
与强行拿call回调串联顺序,在语意层去手写interpreter里“求值序语法”的单子相比,AEff 更是典中典。 不过我在这里,却是要欲抑先扬的赞同AEff的4个爽点。
我喜欢把 Algebraic Effects(AEff) 函数叫做“袋鼠效应器”。错误、系统调用、localStorage等“感受器”被她放在育儿袋外,代数跳出袋子,感受器就【择机】把它放回去:
- 异常的冒泡、重抛或替换,类似Rust受检的Result<T,Err>
- “请求局部”的可变量容器,就像隔离的 Arena,localStorage,Worker全局 ,这样PFer就不会受“参数变才纯”的限制
- 单例工具的参数注入,比如“进程”的pwd,fetch的登录头
- 异步(syscall)!求值栈转回调链表,才能够做 sleep() 和 evpoll/queue 等“内核态操作”
异常异步相耦合,“IO结果注入”和可变容器相耦合,可以说很优雅的确定了报错与IO请求的“范畴”。
袋鼠妈妈,就是evloop,那感受器自然是线程了!catch时她停止resume,并且waitUntil池空的话,进程自然退出。
虽然用 auto await + implicit_arg(getters) 很容易breakdown AEff的概念,但它的本质是在于【可观测性】:在于静态确定“卡线程的调用”卡多久,依赖fs还是db,而非模拟(Promise.catch)。
AEff实现“参数变才纯”时,就比Monad轻量了许多: 别忘了var.flatMap(Var内)可以有then以外的键。 不过这种文字游戏对practical是白费脑力。
上面说欲抑先扬,那表扬完该批评了:AEff 中看不中用!
相对于DOM/Java“漏洞百出”的IO限界和样式值注入,Monad还不严谨吗? 尽信书不如无书,尽受检不如不检。一个白屏是100%不会抛错的,这就是“干净”的价格。
我自己用我自己的异常和异步范式,实现那“4个爽点”
Result有另一种实现:所有值,包括0都是truthy。null,Error和NaN是falsey。只允许object键的值是null,而访问Error的任何键都会throw。
在这种模式下,为Result提供冒泡、捕获替换的最好方法,不是AEff的“自动await”,而是nulley链(?. 和 ??),比如 txt=readSync('_404')? ,再加上“异步函数名”的约定,比如 read?('_404')? ,这些可以预处理实现,缺点是没有AE的默认值注入那么“自由”
至于可变状态,我使用类似Hooks的 n=inHole(0); n1=n.As(x=>x+1); n.As(233); assertEq(n1.v, 234) ,这个模式显然兼容Promise,As就等效Thenable。
---
有人告诉我可以直接在AEff语言上实现 read()?错处和“函数名?异步”,从而在架构上利用AEff,业务上却使用nulley链。这忽视了“async是否天然就该标明”的争议点。
AEff,或许是对系统调用的极佳抽象,也可以“插入”传统的OOP异常里。这就像closure变量不等于this变量,函数值与dict原型链,【正交】构成了对所有数据和操作的“Composer”。
但我认为,closure和SAM对象的协调性是特例,AEff和nulley链只能择一而从:AEff说到底还是 auto await + implicit_arg(getters) 的赠品,错处的一致性,不可能超过由链提供的默认值或rethrow操作!
AEff的赢面,是用函数签名【静态】确定线程的await,甚至能区分noreturn抛出vs捕获回调链表的优化,就像closure能unbox掉不泄露的SAM对象或纯const的cellvar。
但隐晦和省事,在工程上未必是好事,尤其是定义与使用处都不一致的AEff。
在应用编程时,几乎没人会根据Error子类去注入default,因为那天然是caller的职责,并且,其实 IO 是非常有限的!fetch() 或FileReader的caller“应该”有几层?
async到处乱窜,是因为UIUX没有切换到基于信号变量的 compose API ,和React恼人的useMemo一个道理。 本来是“setter续延”的粒度不够细导致的,AEff再去模糊界限,是对timing语意的忽视。
另一方面,AEff的函数签名过于复杂。异常和“系统调用”应该静态检查,但分的太细就是“屎上雕花”。我从没见过隔着两层caller还能针对性的fallback,而95%的App都以C的那种tag+msg处理异常。
仅仅是为了“async到处乱窜”和“参数变才纯”扩充结构化异常,看上去很值,其实并没有认识到“异步操作”的局限,也掩盖了catch{}本身的糅杂性;这就像Monad这个丑陋的“栈上Heap” hack,是在将错就错。Monad也是一个到处乱窜的“动态域”,do语句块可把它驯服了?
AEff 可以轻松实现“结构化并发”(协程的批量等待与撤回/close),看上去也很牛,但“异步的祖师”,DOM fetch() 用的却是信号变量,这不足以指出班门弄斧的“袋鼠笑话”吗?
ES6花了10年把你从for(x)带到forEach(x=>),“结构化”的学霸又把你带回去了,那你打算怎么用“结构化并发”写一个IDM的暂停重下呢?
DOM或许像没有兼容问题的一体机,但它的思想是纯粹的。我们需要的是 Worker<->Promise&Signal、普通计算<->异步IO管线 这样清晰的解耦,而不是半吊子的“大同”!
Please open Telegram to view this post
VIEW IN TELEGRAM
duangsuse::Echo
我决定不把Effect归化到我的编程语言里去,技术细节见
#PLT #learn HOAS/de Bruijn index 两种变量(和“栏目答”)实现方法 😅
#statement 知道我为啥圈选回复这条吗?
Algebraic Effects 也是一个PFP的“新秀”,但我考察后觉得没有吸纳的必要,那么不是新秀的deBruj啥,就更没有必要了。
我一直觉得提出它的领域(“定理证明器”)是多此一举的: 自己test都不明白,又何谈证明呢? 若非如此,何需证明呢?
不懂的证明没用,能懂的证明干嘛! 所以,我不会和AEff一样(因为像 #Haskell 还有些可取之处),就额外偏心一些
但是,这俩理论启发了我(作为负面教材),也算不虚此行,没有在弯来绕去的无聊符号上,浪费智商。
回头我会讲讲Prolog的“1=x式变量”与它所不能做的「形式化证明」有何联系。
https://t.me/dsuse/11841
#ai探讨 https://chat.librechat.ai/share/9iz2YegEZl9kEdiacDNmF
#statement 知道我为啥圈选回复这条吗?
Algebraic Effects 也是一个PFP的“新秀”,但我考察后觉得没有吸纳的必要,那么不是新秀的deBruj啥,就更没有必要了。
我一直觉得提出它的领域(“定理证明器”)是多此一举的: 自己test都不明白,又何谈证明呢? 若非如此,何需证明呢?
不懂的证明没用,能懂的证明干嘛! 所以,我不会和AEff一样(因为像 #Haskell 还有些可取之处),就额外偏心一些
但是,这俩理论启发了我(作为负面教材),也算不虚此行,没有在弯来绕去的无聊符号上,浪费智商。
回头我会讲讲Prolog的“1=x式变量”与它所不能做的「形式化证明」有何联系。
https://t.me/dsuse/11841
#ai探讨 https://chat.librechat.ai/share/9iz2YegEZl9kEdiacDNmF
Please open Telegram to view this post
VIEW IN TELEGRAM
Telegram
duangsuse::Echo
前置知识:De Bruijn Index - Trebor的文章 - 知乎
https://zhuanlan.zhihu.com/p/94601499 #PLT #FP
https://zhuanlan.zhihu.com/p/94601499 #PLT #FP
dnaugsuz
https://github.com/MoonshotAI/kimi-cli/issues/405#:~:text=「提示字编程语言 这哥们是结构化编程和“typehint”写魔怔了,没有认识到LLM是在「语意」层面写代码呢,还和某些人那样觉得写个PEG+语法高亮就叫元编程呢。🤯 我上次用Gemini聊“符号执行、抽象解释”,怎么都没有想到这些有的没的、形式主义…… REPL的状态? AIGC+code interpreter+MCP 才是真正的REPL workflow 他的大意是,觉得prompt时…
#fp #sb https://github.com/MoonshotAI/kimi-cli/issues/405#issuecomment-3615015273
信达雅究竟是什么? 信是目标语言的原生感,达是源语言的语义保留
《中文编程》圈有时挺魔怔的,yin 说他不开发ONE语言是因为懒,而yin(.java)没有做的下去有一部分是被各种人指点江山的原因失去了兴趣,我算是明白是哪种人了(帝球 也指点过呢)🤯
同样是FP和PLT,为啥我的翻译就是「lambda栏目答」「recursion睿括式」「interpreter硬特匹蕊特」,这人就是莫名其妙的「兰姆达」「演算」,难道我们小学学的不是一门国语?😅
最头疼的是他根本不知道怎么用AI,output出这么多玩意也不知道删减,我滚动都浪费我的时间。
#ai探讨 https://chat.librechat.ai/share/iC-S-ZmLqNwIyzlYiOlrh
#pingbk https://codemanship.wordpress.com/2025/11/25/the-future-of-software-development-is-software-developers/
信达雅究竟是什么? 信是目标语言的原生感,达是源语言的语义保留
《中文编程》圈有时挺魔怔的,yin 说他不开发ONE语言是因为懒,而yin(.java)没有做的下去有一部分是被各种人指点江山的原因失去了兴趣,我算是明白是哪种人了(帝球 也指点过呢)
同样是FP和PLT,为啥我的翻译就是「lambda栏目答」「recursion睿括式」「interpreter硬特匹蕊特」,这人就是莫名其妙的「兰姆达」「演算」,难道我们小学学的不是一门国语?
最头疼的是他根本不知道怎么用AI,output出这么多玩意也不知道删减,我滚动都浪费我的时间。
#ai探讨 https://chat.librechat.ai/share/iC-S-ZmLqNwIyzlYiOlrh
#pingbk https://codemanship.wordpress.com/2025/11/25/the-future-of-software-development-is-software-developers/
Please open Telegram to view this post
VIEW IN TELEGRAM
《DSL, esolang 的本质?》
#ai对比
https://chat.librechat.ai/share/Y5K-iX1AnM3p-yO6lnJ0J 概括
https://x.com/i/grok/share/ny0di6aIaf5iRnGzPAt5Kpjha #FP Brainfuck 阅读起点:50%
https://chat.librechat.ai/share/c2LT4sxCdp6CneM3EDU3j 和Kimi直接怼我不同,我突然发现Gemini3的吹捧有时反而是好的,因为它能批判性吹捧……
还能从侧面验证真正的要点
😅 忍不住多问了几句
😅 这些探讨其实非常抽象,就像从红黑树vs HashMap谈到了信息熵,不过我觉得,计算理论 还是有些前景的,比如 Nim UFCS(obj.func(arg) 等价于 func(obj, arg)) 不就很好么
https://x.com/i/grok/share/5kdLGiROON2UcvO3r4nng2wq9 结尾…… 感觉对我的设计还是有帮助的,但瓶颈感非常大。
或许让AI决定方向是错误的,因为瓶颈感非常大。
json本身是一个非常简单的文档树编程语言,但它成了事实上的标准。
Lisp可以称为语言里的语言,因为它只有变量查找和函数查找不可重定义(虽然很多Lisp不支持调用链)(这里的method lookup是指闭包和同构于闭包的宏)
理念意义上,《黑客与画家》的作者PG的“百年语言”是对的,因为它既不是SKI这种对bf和dup/swap的模拟,也不是Scala这种类似于C++的美与丑大杂烩,也不是晦涩的PFP语言,而是复用和状态转移的箭头本身。
PG加上了Lisp匮乏的非链表式集合与位置语法,简化了let-in等纯函数傲慢,所以虽然Arc被yin评价为“退步都算不上”,还是能从反面启发我们: Worse is Better, just like Markdowns.
#ai对比
https://chat.librechat.ai/share/Y5K-iX1AnM3p-yO6lnJ0J 概括
https://x.com/i/grok/share/ny0di6aIaf5iRnGzPAt5Kpjha #FP Brainfuck 阅读起点:50%
https://chat.librechat.ai/share/c2LT4sxCdp6CneM3EDU3j 和Kimi直接怼我不同,我突然发现Gemini3的吹捧有时反而是好的,因为它能批判性吹捧……
还能从侧面验证真正的要点
G3: Java 引入 for-each,它是把“迭代器模式”固化成了语法;当 Python 引入 decorator,它是把“修饰器模式”固化成了语法。
这对初学者是好事(Worse is Better),但对追求终极“理”的人来说,这是语言设计者把太多的石膏涂在了核心逻辑上,导致我们看不见下面的“肌肉线条”。
Lisp(特别是 Scheme)之所以被称为“百年语言” “语言中的语言”,是因为它拒绝固化。它只给你 lambda 和 macro,剩下的你自己造。
而你心中理想的“百年语言”,其实是在寻求一种黄金平衡:
它不完全像 Lisp 那样拒绝一切固化(太累),也不像 Java 那样固化一切(太僵)。
它固化那些最符合人类直觉的模式(如 Markdown 的排版,JSON 的层级,Kotlin 的简写),而保留核心的流动性。
所谓的《屠龙术》,最终不过是:看山是山,看数据是数据。不再有“纯”和组合子,别无他物。
...你觉得,调用链、惰性求值(autoclosure)、cond 不是核心语法吗
这里的method lookup是指闭包和同构于闭包的宏,函数作为值是核心,所以减不掉
if剪枝和call的栈或回调链表语义还是要保留的,确实存在递归的需求,代码是要运行的
OO模块化的调用链,nullsafe 需要打开函数查找模式来添加。
cond,惰性求值,pmatch 这些确实可以用宏
这里存在有争议的两项:过度工程的 effect, 基线和状态转移不明确的 loop
IO effects 本质上是一种高效的 yield tag+tuple (await的实现证明了这点),因为它能在return前让结果可见。 如果把OS的syscall也视为yield,这个定义就是一致的。也就是说IO并没有那么“不纯”
loop 的卡死(阻塞时的死锁)是需要effects的一个理由,tailrec 是对基线+转移模型的严肃化,但我觉得明确的 time slice 和event signals(取代 poll) 更完备。
其实你知道我说的 递归固定点(运行时支持) 是对调用层叠的实现,那么对堆也应该定义下,不过Lisp没有区分值vs地址引用
但是可变性又成了新的“引用”。虽然类型化区分二者的收益不大(不同的app可能完全偏向值/容器引用之一,Int本身也不一定是“autoboxing primitive”),struct inter (类似于 str intern) 又是负收益(不是万物皆有 Eq trait-比如闭包),但一个正确的语言还是要区分值类型,哪怕是为了写独占(unique_ptr)
结构性共享?
哦,我设想的一种共享不是直接的内存池,而是模拟def(mutArg) -> oldTree
这样虽然每次使用都要先把mutArg应用为保存好的tuple,但是非常明确的,就像ThreadLocal
这个方案特别优雅,学习负担低,但是也不适合“1次调用”以外的情况——Clojure 持久化结构 是真的创建了共享,而我是依赖于调用栈,显式重放
其实…… 变量树的问题是被高估的,因为一个优秀的程序员不会被GC/malloc的性能卡住,问题在于语言能否信任他们的学习能力。
手动重放变量树里的hole,其他项尽量深不可变(phased lifecycle)
这种模式很好。它和Java的“元组泛型<A,B,C..>” 数据很像,推导后的元组泛型就是不可变的
我在考虑更好的模式
区分“僵化语言”和“活体语言”的关键点——**“点号(.)”的解释权归谁?**
* **在 Java/C++ 里**:`a.b()` 的含义通过编译器写死。如果 `a` 是 null,JVM 抛出 NPE,你无法干预。
* **在理想语言里**:`a.b()` 仅仅是一个语法糖,它在底层被翻译成 `send(a, :b)` 或者 `lookup(a, :b).call()`。
如果我们**固化**了“发送消息”这个动作,但**开放**了“如何响应消息”的逻辑(Method Lookup),奇迹就发生了:
1. **NullSafe**:你可以定义一个规则:如果 `a` 是 Null,`lookup(a, :b)` 就返回一个“什么也不做的替身(NilObject)”,而不是报错。NullSafe 变成了库的行为,而不是编译器的特权。
2. **Proxy/AOP**:你可以轻易拦截调用链,做权限检查或日志。
3. **动态转发**:类似 Ruby 的 `method_missing` 或 Lua 的 `__index`。
https://chat.librechat.ai/share/Lh_1H_JhfmTxW2juTln2f
https://x.com/i/grok/share/0w2xy2ztSjghopoD9KRjA7rOp 这俩都很优秀啊……
https://x.com/i/grok/share/5kdLGiROON2UcvO3r4nng2wq9 结尾…… 感觉对我的设计还是有帮助的,但瓶颈感非常大。
或许让AI决定方向是错误的,因为瓶颈感非常大。
Please open Telegram to view this post
VIEW IN TELEGRAM
duangsuse::Echo
#post 《元编程的未来是被“AI高人” “vibe code流水线”替代吗?驳「猴群里的拿来主义」》 上面的 #ai探讨 也谈到数学和物理的交界点。之前有对 Taichi-lang.org 有啥优化探讨过一些: https://chat.librechat.ai/share/3VSVoX4nhRH2mC-Y4833L 高级特性/SoA https://chat.librechat.ai/share/XBPzBihUUsmIs4L3R1Mg7 JIT 还是THU姚班好人多啊。😅 先说结论: >AI 对…
#ce #post 《从129个JS引擎和1个元循环实现里,PLT人能看出什么》
JS引擎游乐园!😒
https://zoo.js.org/?arch=amd64&sort=loc
最短的是0.6k行的,国人看编译原理书写的TS tree walker(他还有个vm版)
https://github.com/bramblex/jsjs/blob/master/src/eval.ts#L116
native最短是 cesanta/elk:单个 .c 文件,编译后 ~20kB flash 堪比 c4
不容易被看到的一点是,这个 ECMAScript 实现列表有129项,扣掉6大厂商和 QJS,muJS,Duktape 有120人,
所以能实现某流行PL解释器并不是什么高端技能,我见过几个设计游戏或框架的被动写出来过。
#ai探讨 https://chat.librechat.ai/share/bvGuBeVwZkLVGkgiR0lQH GraalVM 究竟比JVM好在哪
https://x.com/i/grok/share/bXeWFhrIZiXgok1hQKiogctAx killer 语言特性
JS引擎游乐园!
https://zoo.js.org/?arch=amd64&sort=loc
v8在光追上比JSC坏点,代码也多不少(但可能是没有模板单态化 所以bin反小10M)。PrimJS是字节的QuickJS,MuJS是0.4M bin
JVM自带的Nashron和Mz的Rhino(用AutoJS的应该不陌生),Graal惜败V8
并不是 Googlers 不如水果,raytrace 是“重计算、轻对象变异”的场景,可能适合WebGPU的实现。V8 自带了巨大的 init Heap Snapshot 还是比JSC小啊
最短的是0.6k行的,国人看编译原理书写的TS tree walker(他还有个vm版)
https://github.com/bramblex/jsjs/blob/master/src/eval.ts#L116
很容易看见,pypy,jsjs 元循环“硬特匹蕊特”本质上就是把 try{}catch{}finally{} 等等硬流控逻辑外提为对VarTree的深先重写,
从而将 {..} 转写为 (e.try).evalIn((env)),其中.try和 runtime env 可以组合与替换。 如果把局部分配编号化,把跳转固定化为goto,你就可以得到JVM的汇编模板解释器
元循环本质是在做 round-tripping,才很容易找到这个「编号元组化 vs Str和层叠查找」的符号表差异,以及基于offset而非调用栈的流控,这就是唯一两个语义差别了——它是可组合性的骨架
思考:为什么不是所有bytecode解释器都能“免费获得”汇编模板解释器? 因为jmp的语义没有固定到已生成(或backpatch)的opcode
而 tree walker 和 tailcall interpreter 间的性能差异如出一辙。从广义看,eval(if(q)A:B) 和 computed goto vm_iseq[q?A:B]; continue.. 都只是一种跳转,后者少了stack开销(因为更紧凑),这也是tailcall字节码解释器的缓存友好
#FP 对尾递归的追求并非自讨没趣,如果宿主语言支持完美的 TCO,理论上“函数调用的解释器”和“Goto 的解释器”在机器码层面是可以等价的(Scheme 解释器常利用这一点)
btw. 另外,这里有两个全靠 InvokeDynamic, Partial Eval的免费编译器? 它们的查找和跳转是怎么实现的呢?
native最短是 cesanta/elk:单个 .c 文件,编译后 ~20kB flash 堪比 c4
不容易被看到的一点是,这个 ECMAScript 实现列表有129项,扣掉6大厂商和 QJS,muJS,Duktape 有120人,
所以能实现某流行PL解释器并不是什么高端技能,我见过几个设计游戏或框架的被动写出来过。
#ai探讨 https://chat.librechat.ai/share/bvGuBeVwZkLVGkgiR0lQH GraalVM 究竟比JVM好在哪
https://x.com/i/grok/share/bXeWFhrIZiXgok1hQKiogctAx killer 语言特性
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
jsjs/src/eval.ts at master · bramblex/jsjs
简易的 JavaScript 元循环解释器. Contribute to bramblex/jsjs development by creating an account on GitHub.
duangsuse::Echo
#math 如何用一个【没有发生】的东西,证明一个发生了的镜子存在且以read开头?🤓✅ 反正 while "I AM": print(read()) 它可以从print开头,也可以从 not("I AM") 或者说 break; 开头,另一条世界线的宇宙“从一开始就是无,而不是有。” 因为苏格拉底选择用read(从笑和幸福)开头,我所理解的《数学》也要这么开头。广义相对论选择用print开头,是因为有人不明白 alias print=echo…… 可是人工智能实验室的Lisper知道的,哪怕祂“没写过”。🌚👌…
#FP 纯函数其实就一句话:“编程的人不调用「结果不一样的函数」”。
input(">>>") 和 random.pick(*"AB") 结果只在测试环境下一样,print() 在caller不能读取它(stdout流)时结果不一样,yield在耗时上结果不一样。
那么他们是怎么把代数搬到电脑里的呢?不是写vec2场函数,也不是挑战Rust宏或平民版comptime func,是把JS里的.then(f)做成“编译期查表出f”。
没错,去掉副作用只靠「不调用0参函数」(拒绝全局this和“立即树相等”),所以他们把任何函数都塞给了一个argLast:我们一般叫“调用栈”、“单步调试或执行”的那参数,还美其名曰高质量工程。数学和计算机就是扯淡,真数学的门(Torch/Taichi)FPer摸不到
用范畴论术语装点门面。范畴的集合可是有N:1箭头函数的,就连物理模拟也有2:1的sqrt(x)计算,哥德尔不喜欢听废话,什么时间和折叠(eval order)没有发生因为“代数生效了”。
Monad和 #Haskell 的Logo(>>=) 又是什么呢?结合律。
(read | greet) | echo 和 read | (greet | echo) 是等同的
(a;b);c == a;(b;c)
窝槽,这不是废话吗?不对。因为 greet(x) 有1个点位,所以FPer就造了整个“链式调用栈”,来发扬Curry和模式匹配GADT&class延迟绑定的精神,
其实 a;(b;c) 根本就是鬼扯,任何一个正常人都看得出Lambda不是这么用的
套那么多层无非是为了实现 if(Q,print,print) 和 if(Q,return,''), print 的“调用侧决定”,引用一大堆有的没的paper,
最后还不如 yield eventTuple 或纯粹的 DSL=(...lit)=>(env)=>{return value}
写操作系统和编译期函数的人早就知道了,DB/DS/CG 领域的人知道的更「纯函数」。
有这点能力不去写些有意义的DSL和“可以不乱的混乱语法”,去屠C++ template<>的龙,却凑一个死寂了70年的数学界的热闹。现在还想证明Dijkstra的软件测试知识是错的。
CS+Math,学术cosplay。 🎓 👎
我不两次踏入同一条河流,任何一个用户都是如此。 πάντα ῥεῖ
1958: Lisp → 解决实际问题(AI, symbolic)
1972: C → 解决实际问题(Unix, 系统)
1974: SQL → 解决实际问题(数据管理)
1983: C++ → 解决实际问题(性能+抽象)
1991: Python→ 解决实际问题(快速开发)
1995: Java → 解决实际问题(企业应用)
2009: Go → 解决实际问题(并发服务)
2015: Rust → 解决实际问题(安全+性能)
世界在变,数学没有意义,或者说数学的语言没有用。数学依靠语言,不是语言依靠数学。
如果代数逻辑都不够母语,还有什么是“整个宇宙的方言”?所以,没有一种有价值的领域,在担保上败给数学。
脱离涌现的几何知识是死的,死枝「挂名不上」活果实,就像量子物理承认了芝诺、费马、贝克莱大主教(牛顿的“好同事”)、高斯曲率定理。断言什么死的正确,真知识就复活来否定它。
就连算力的语言,也很可能是安排不够好而卡慢的。或许走一遍必然是 O(N),数学无穷里一定有一堆Node可以跑通 A->B,但谁告诉你N一定要有“那么多”?
"If 🍎 + 3 = 5, what is 🍎?" 🍎 = 1.
Accepted.
https://github.com/Kuri-su/yinwang.bak/blob/master/articles/函数式语言的宗教.md#:~:text=这个世界里的所有东西都是“有线”的。你需要绞尽脑汁
幸好我不需要线。没有吃掉苹果的人,才害怕那道线不对。 😊
GitHub
yinwang.bak/articles/函数式语言的宗教.md at master · Kuri-su/yinwang.bak
yinwang.org's auto backup. Contribute to Kuri-su/yinwang.bak development by creating an account on GitHub.
duangsuse::Echo
UNIXer觉得不支持()=>{}的C就是唯一的编程语言,而且libc的fork()隔离成本“极低”。
sched.c与vm.c,很大程度上是在【用最愚蠢的方法】实现fnarg2obj(闭包)和GC
sched.c与vm.c,很大程度上是在【用最愚蠢的方法】实现fnarg2obj(闭包)和GC
当然了,我简化了 accept() vs accept(then) 的问题,前者传入了自身pid(或者说整个ret2stack),后者另外传入了一个“代码和数据”双指针。 内核权限对后者是无能为力的,因为一个进程不能长两个头。
这个问题,真正是我说的“用非常愚蠢的方法实现闭包”:把 一个纯粹的token鉴权,和栈(pid)绑死在一起,所以有了各种语言的await。 这是养鸡场只有一个谷堆,一群鸡随机插着队来消化,但谷堆(网卡)本身是事件性的!😂
鸡确实没有两个头,但把进程视为单线的、有栈顶的,这种说法本身是错误的。并没有确定的执行顶部,只是一堆信号变量间的因果链!
😅因为OOP封装和“阅后即焚”式计算太流行了,好像必须要有个栈vs堆一样。其实栈分配只是个内联优化,泄露进了认知里,还成教科书了。 不会真以为栈变量就能阅后即焚吧?
这就好像某人发现了【文件名不占空间,可以拿来做压缩】,或觉得伪递归(continue fn(x-1)) 比for更占内存的“真理”一样让人哭笑不得。for还会死机,递归却允许爆栈时优雅容错怎么不说?
OS就是大一点的JVM,甚至代码解释器而已。 🐧因为sched/vm的内核功能把 “回调链表” 给藏在混乱的procfs统计里,就认为不存在持续态栈消耗这回事?
一个进程不能长两个头。 更深层次的问题是,pthread无法区分出这双指针里谁是“安全”的数据(需要喂给用户态全局sighandler)
😇我就摊开了讲:两个版本accept的本质区别是栈易失vs堆拷贝,是从
为了这个内核不能“跨域执行”的手短问题,你们发明了Kay的OOP里没有的毛病,这个模型并没有比“单线程”那个好看,因为仅仅是内核不能去直接eval那个回调而已。它必须区分arg和fun。
这件事的结果是,因为4K页和抢占式调度器太贵物的弊病,libuv 这些东西动态创建线程只为了在accept/read之类的固定行号卡死,然后push给master,后来又有了epoll/uring逐步的“跳步”支持。
本来的模型错了,但它的 dirty hack 碰巧掩盖了这部分。好像线程这东西真是存在的一样,好像“服务”真的都不是单线程的。
他们还经常说什么高并发L3缓存友好,其实就是一个不存在的问题,就像React的vdom vs Svelte的点对点绑定一样,错误的把“回调链表”用timer + while(1) if(ret!=null) 这样的若智逻辑表达,改回来,还长脸了? 你tm一开始就在无脑GOTO和鬼扯。
还有人又学到了 #FP Continuation,就是【回调链表】asks(A=>B=>C=>...) , #haskell IO Monad 给整的亲妈都不认识
让一切“返回”某种json再去diff减枝真是我听过最搞笑的优化了,JS觉得自己比C++快,C++认为x86中断不懂事件和因果链,编译器觉得机器和指针比人聪明。 根本没有“返回”,编程是点对点的。 🙄
这个问题,真正是我说的“用非常愚蠢的方法实现闭包”:把 一个纯粹的token鉴权,和栈(pid)绑死在一起,所以有了各种语言的await。 这是养鸡场只有一个谷堆,一群鸡随机插着队来消化,但谷堆(网卡)本身是事件性的!😂
鸡确实没有两个头,但把进程视为单线的、有栈顶的,这种说法本身是错误的。并没有确定的执行顶部,只是一堆信号变量间的因果链!
😅因为OOP封装和“阅后即焚”式计算太流行了,好像必须要有个栈vs堆一样。其实栈分配只是个内联优化,泄露进了认知里,还成教科书了。 不会真以为栈变量就能阅后即焚吧?
这就好像某人发现了【文件名不占空间,可以拿来做压缩】,或觉得伪递归(continue fn(x-1)) 比for更占内存的“真理”一样让人哭笑不得。for还会死机,递归却允许爆栈时优雅容错怎么不说?
OS就是大一点的JVM,甚至代码解释器而已。 🐧因为sched/vm的内核功能把 “回调链表” 给藏在混乱的procfs统计里,就认为不存在持续态栈消耗这回事?
一个进程不能长两个头。 更深层次的问题是,pthread无法区分出这双指针里谁是“安全”的数据(需要喂给用户态全局sighandler)
uring后来解决了。IOCP可能还简洁点,但如养鸡场一例所说,这是手写闭包和大switch的智障级设计。 为了一个“不能跨域请求污染”的事兴冲冲的把垃圾当成高性能做
😇我就摊开了讲:两个版本accept的本质区别是栈易失vs堆拷贝,是从
pix(x,y, implicit pid) 装箱转换为 enum Stack{Pix(x,y)} and pid {case Pix: .. } 的双指针的组合方法之别,大小写问题。为了这个内核不能“跨域执行”的手短问题,你们发明了Kay的OOP里没有的毛病,这个模型并没有比“单线程”那个好看,因为仅仅是内核不能去直接eval那个回调而已。它必须区分arg和fun。
这是模块化时的权限问题,其次是ld-linux的ABI问题。让accept自带fork的语意并不会让nice沙盒+mmap的开销更低,何况养鸡场并不适合为了while(1)设计的抢占式调度器。 把pid这个隐藏状态诚实的写成一个参数,怎么就这么难呢?
有多少人知道strace和stap可以像F12网络文件覆盖那样,模拟chroot? 好像pid和gui本身是不可再编程的最终产物。
这件事的结果是,因为4K页和抢占式调度器太贵物的弊病,libuv 这些东西动态创建线程只为了在accept/read之类的固定行号卡死,然后push给master,后来又有了epoll/uring逐步的“跳步”支持。
本来的模型错了,但它的 dirty hack 碰巧掩盖了这部分。好像线程这东西真是存在的一样,好像“服务”真的都不是单线程的。
他们还经常说什么高并发L3缓存友好,其实就是一个不存在的问题,就像React的vdom vs Svelte的点对点绑定一样,错误的把“回调链表”用timer + while(1) if(ret!=null) 这样的若智逻辑表达,改回来,还长脸了? 你tm一开始就在无脑GOTO和鬼扯。
还有人又学到了 #FP Continuation,就是【回调链表】asks(A=>B=>C=>...) , #haskell IO Monad 给整的亲妈都不认识
归根结底,异步编程就是个骗局。是事件的就归事件,不要把谷子堆起来,再责怪鸡怎么挤来挤去数据都乱了
让一切“返回”某种json再去diff减枝真是我听过最搞笑的优化了,JS觉得自己比C++快,C++认为x86中断不懂事件和因果链,编译器觉得机器和指针比人聪明。 根本没有“返回”,编程是点对点的。 🙄
duangsuse::Echo
我很好奇Scala现在的普及程度。它并没有像Clojure那样消亡
#Haskell 们长期连fmap就是现代H5里的derive()变量这点都没还原好。
直接把Promise弄成不人不鬼的 IO Monad,然后集合类不可变到处Lens(如同Rust的Rc RefCell套壳),结果还不如Svelte。都是回调链表,函数式的功能性和性能就拉胯一节, 不活该被淘汰么
安全${内插}和 o?.nulToNul 这些都属于是极其容易但价值高到夸张的, 所谓的 #> #| bash语法(自定义DSL)与之相比算不了什么。
究竟是天真到什么地步,会觉得mixfix生态位不尴尬? 可以bash或shadertoy里测试,为什么要用Scala写bash?能自动补齐? 需要检查pipe的类型吗?
Li Haoyi 的成功,和他所有库(os-lib, requests-scala 等)的流行,恰恰是因为他回归了Pythonic,利用了JVM上的生态位(kt太卡 Groovy太拉),但是native/js的scala支持咋样我就不说了。 我只能说, tstl (js2lua) 比较成功,这取决于SDK的阻力和output是否够原生。交叉到wasm上都不一定能有好果子吃
🤔 #Lua 其实是个非常奇怪的语言,它的迭代类似于range和JS整数键名的杂种,从1开始数,len和not运算也长的诡异,但只凭效仿SQLite就搞得许多lib(尤其是NVim/Wayland世界)不得不兼容它,虽然效果像H5兼容WASM那样是良善的
#js #FP #ai探讨
“这玩意儿就像 Excel 里的公式往下拉”
直接把Promise弄成不人不鬼的 IO Monad,然后集合类不可变到处Lens(如同Rust的Rc RefCell套壳),结果还不如Svelte。都是回调链表,函数式的功能性和性能就拉胯一节, 不活该被淘汰么
安全${内插}和 o?.nulToNul 这些都属于是极其容易但价值高到夸张的, 所谓的 #> #| bash语法(自定义DSL)与之相比算不了什么。
它很酷,能在特定场景下让代码看起来更“漂亮”或更“贴近领域语言”。 但是让我来选,我会毫不犹豫把${}和parserc作为一等公民,而operator重载和infix作为次要的。
究竟是天真到什么地步,会觉得mixfix生态位不尴尬? 可以bash或shadertoy里测试,为什么要用Scala写bash?能自动补齐? 需要检查pipe的类型吗?
Li Haoyi 的成功,和他所有库(os-lib, requests-scala 等)的流行,恰恰是因为他回归了Pythonic,利用了JVM上的生态位(kt太卡 Groovy太拉),但是native/js的scala支持咋样我就不说了。 我只能说, tstl (js2lua) 比较成功,这取决于SDK的阻力和output是否够原生。交叉到wasm上都不一定能有好果子吃
🤔 #Lua 其实是个非常奇怪的语言,它的迭代类似于range和JS整数键名的杂种,从1开始数,len和not运算也长的诡异,但只凭效仿SQLite就搞得许多lib(尤其是NVim/Wayland世界)不得不兼容它,虽然效果像H5兼容WASM那样是良善的
#js #FP #ai探讨
duangsuse::Echo
#selected #tool 弄了个精简版妙妙词典,可以快速帮你了解现代全栈 + 编程语言特性 用Gemini2.5展开了一下主流解释 函数式:栏目答 蕊括深 控伴同 它剖_馈睿 择深_徘深 仿行_候数(Signal Holes) 面向事件:一问特_括需饵 喊得了饵 爬撕饵-串读串写 授齐易-管道配对 IO密集型:待客 偶醒刻 叩融听-回调链表 窟启 海稀_通证 通用执行层:正择_挨口 硬特匹蕊特 勘木排而-微迈细硬 码可揉 有联_应塞类型 多页面Web:落靠-locale 画架嵌入-iframe…
Telegram
duangsuse::Echo
#fp #sb https://github.com/MoonshotAI/kimi-cli/issues/405#issuecomment-3615015273
信达雅究竟是什么? 信是目标语言的原生感,达是源语言的语义保留
《中文编程》圈有时挺魔怔的,yin 说他不开发ONE语言是因为懒,而yin(.java)没有做的下去有一部分是被各种人指点江山的原因失去了兴趣,我算是明白是哪种人了(帝球 也指点过呢)🤯
同样是FP和PLT,为啥我的翻译就是「lambda栏目答」「recursion睿括式」…
信达雅究竟是什么? 信是目标语言的原生感,达是源语言的语义保留
《中文编程》圈有时挺魔怔的,yin 说他不开发ONE语言是因为懒,而yin(.java)没有做的下去有一部分是被各种人指点江山的原因失去了兴趣,我算是明白是哪种人了(帝球 也指点过呢)🤯
同样是FP和PLT,为啥我的翻译就是「lambda栏目答」「recursion睿括式」…
#life 《中文编程》一词长期以来被民科霸占了
而实践上,拼音输入和英汉混杂的问题又让使用母语不切实际。
可是 母语=汉语 时,如果用AI编程(只定大框架),在输入上真有好处,那么,在源码阅读上,应该是同理(只是较难设计)
所谓的中文XXX,鼓吹这种东西,其实不如早年的金山输入法、汉化DOS,今天的人人字幕组好用。 就像把游戏科学政治化一样
反正他们又不听劝 ,就和那个在电线杆下观测出 🌎 🌞 用 💠轨道转圈的老人一样 《鬼畜区 李文亚:地的运动》
在2026年还能有【朝闻道】的那种感觉,李某亚也是够幸运的。 在他眼里所有官方机构都被西方思想荼毒了吧, 对于我来说,哪怕「预期」达到了,最后无人问津,自己维护到弃坑,也是可能的结局呢。 🥱
但又如何呢? 没人是天才,iq和Bellard那样的【神】也有尚未触及的领域,比如SQLite就不是他写的。而且SQLite最近还被tailscale试出个WAL并发数据破坏,更不用说Linux主线了
Bret曾说,【软件有两部分,一段安在硬盘上,一段安在头脑里】。 或许,对开发者也一样。
我收获了头脑里与心里的那部分软件,这就足够了。
而实践上,拼音输入和英汉混杂的问题又让使用母语不切实际。
可是 母语=汉语 时,如果用AI编程(只定大框架),在输入上真有好处,那么,在源码阅读上,应该是同理(只是较难设计)
所谓的中文XXX,鼓吹这种东西,其实不如早年的金山输入法、汉化DOS,今天的人人字幕组好用。 就像把游戏科学政治化一样
我感觉许多做toolchain/小玩具的,就是奔着《中文编程》《真·纯函数》这四个字,好像达成了就万事大吉一样。 根本没有认真试过【之后呢】
对我来说,就是一种人嘛。 所谓 “做到了就怎么样怎么样的”,Rust原神,Agile疯,认为TeX/Vim “原生” 就比 Docx/VSC 好的用户
就连小众赛道,都这样的浮躁。如果国人做IDE,是否会往 build/out 里注入广告呢?(Xcode Ghost 的恶劣性质,但传成 pdd root 事件那样的 “不小心翻车了”)
反正他们又不听劝 ,就和那个在电线杆下观测出 🌎 🌞 用 💠轨道转圈的老人一样 《鬼畜区 李文亚:地的运动》
在2026年还能有【朝闻道】的那种感觉,李某亚也是够幸运的。 在他眼里所有官方机构都被西方思想荼毒了吧, 对于我来说,哪怕「预期」达到了,最后无人问津,自己维护到弃坑,也是可能的结局呢。 🥱
但又如何呢? 没人是天才,iq和Bellard那样的【神】也有尚未触及的领域,比如SQLite就不是他写的。而且SQLite最近还被tailscale试出个WAL并发数据破坏,更不用说Linux主线了
Bret曾说,【软件有两部分,一段安在硬盘上,一段安在头脑里】。 或许,对开发者也一样。
我收获了头脑里与心里的那部分软件,这就足够了。