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
duangsuse::Echo
https://tttttt.me/kn007_channel/7253 (这个) #Android #dev 完全没改 🌝.. 好吧,我承认对于一个优秀的设计者而言,视付费(或共享)软件为自己的私有之物并没有问题,但是我也觉得 Xposed 或 Lucky Unlocker (1)是搞机圈广泛使用的 (2)是用户的自由 ,开发者无权干涉或者做进一步限制,没有必要对破解太敏感。 dreamtonics.com 和它的 SynthesizerV 也遭到过声库授权验证的破解,作者对这个软件花了很大心思,但是他也没有…
#cplusplus 嘛,为了避免有人说我指点江山 🐸我就写几行证明下 fcntl() dnotify 是超级简单地。
Android 除了 RootFS 和 libc 结构外本质就是为嵌入式优化的 Linux ,而 DNotify 是 Linux 2.4 引入的目录变更监听机制(为兼容性, in_ 是 2.6 feature),所以我用 C++11 lambda 不需要几行代码就能实现「文件变更的监听和删除文件的保存」

众所周知写程序先写测试:
touch a b; echo 1>b
rm a b
cat saved/b

预期 ./fsw_amd . 输出 Aa Ab Mb Da Db 行。
#cplusplus #code ,居然不支持文件名…… 真的只能看目录么 那样只能 fstat() readdir() 扫 dirent 了,而且也没法知道具体什么文件有变更,非常草。 之前还以为是不能递归监听
#include <fcntl.h>
#include <csignal>
#include <unistd.h>
#include <cstdio>
const int sigPrior = SIGRTMIN+1;
#define notNeg(v) v; if (v<0) return -1
void printFPath(int signo, siginfo_t* si, void*) {
auto o = *si;
getFPath(o.si_fd); printf(" %s\n", fpDesc);
}
int main(int argc, char** argv) {
auto fp = (argc>1)? argv[1] : ".";
int fd = notNeg(open(fp, O_RDONLY));
fcntl(fd, F_SETSIG, sigPrior);
fcntl(fd, F_NOTIFY, DN_MULTISHOT|DN_CREATE|DN_MODIFY|DN_DELETE);
struct sigaction dnAct = { .sa_sigaction=printFPath, .sa_flags=SA_SIGINFO };
sigemptyset(&dnAct.sa_mask);
sigaction(sigPrior, &dnAct, NULL);
while(true) pause();
return 0;
}

fs watch 是 Ruby/Node 系 CLI 应用重要的特性,包括 jekyll, inotifywatch 在内支持者不在少数,封装好的东西例子就不举了 睡大觉😴
https://www.linuxjournal.com/article/8478 #linux #dev
https://github.com/NexusBots/Umbreon-Rootkit/blob/master/readlink.c
关于 dnotify 如何取得 path 的问题可以 readlink /proc/self/fd/0 ,看这个

#DontKnow MAX_CANON PATH_MAX 第一次知道 canon 是指 termios 意义的…… 难怪 termcontrol 会有相关常量名 😳

https://gist.github.com/duangsuse/a8984950c563894eea54fc2f537b5003#file-inotify-cpp
唉现在想着初学时不知道 stdio, fcntl, unistd, stdlib 这些 header 都是干什么的呢…… 不知道怎么选。不过,或许新手会觉得 C 的 std in/out/err; fprintf,fscanf; fread,fwrite 比 Java 的 I/O Stream 要方便些,其实 libc 的确更不方便呢
啊哈,直接完整封装 inotify 的所有功能了,不过 70 行代码 😋
下载代码clang fsw.cpp -O3 &&install -Dm755 a.out /usr/bin/infsw 就可以收获简单易用的 fs watcher 了 😊
$ infsw #sysadmin #cplusplus #tools
R M attrib close close.rd open move.from move.to A D self.D self.move self.unmount in.queovf in.ignore
evNames=above evFlags=dFu1 hasPrefix=1 bufSize=1360
#日常精神分裂 #旧事重提 #Java #JS #PLT #cplusplus #project
A: 啊真的很头疼呢, JPlayer 的 fix 和 depth.html 附赠的 Myson 数据描述语言……
B: 像往常一样,我们一起想想吧。
A: 首先说 JPlayer ,这个原先是作为重写 Yuuta 大佬项目的东西,变的蛮多的,后来也有完全的 C++ 重写。
这个东西最后也是长期熬夜 timedout ,失败点是为优化性能加的 Ringbuffer 队列缓冲区利用有瑕疵,导致最后一次缓冲的内容没放完退出
B: 你还记得它的大体数据流程吗。
A: 当时怀疑 Java 计算速度慢所以用的缓冲器预计算一定内容,整体是 while(frame=next()) 呃不,是 while (escape=que[incPtr()]) if(samePtr()) genChunk() 。
B: 对了,你缓冲的帧是什么数据类型啊,二维数组吗?
A: 基于 frame pix diff 的 ANSI escape string ,这个当然是在 chunk 计算的
B: 生成新缓冲帧的程序你大概是没隔离吧,按当时的设计,应该是 genChunk 收到 VideoIO throw NPE 就跳出绘制loop 了,即便最后一块刚刚准备好。我建议 catch 住NPE ,如果 !samePtr(p,p1) 即还有余帧就继续播放,否则才真的退出。
(接下来一段被证明是误会)
A: 这大概是不利于性能的吧,最后一块的每帧都要 catch ,而且还要局部 landingpad ,函数级有一个了。
B: 你也说了是 jacoco 解码器 API 的问题? throw 是不可避免的,只能说或许可以把输出帧的做成子程序,最后一块的 catch 里直接消耗完队列,或者加个 bool ,未结末时先 if 一下避免重复。

A: 我总结一下流结末的情况: genChunk() 生成某帧时 catch 到一次,但是缓冲区没放完,继续放完这一块,再 catch (输入终末)了发现缓冲区没了,就停止播放。
A: 挺简单啊。那么 Myson 该怎么办,这个语言挺不常规的,既有缩进语义又只支持对象?
B: 首先我们先明确下,既有 heading tree 是怎么解析出的。
显然是每个DOM元素都有「深度」,然后非 h1~h6 的元素默认上一次深度或0 的 +1,所以说是「以能解析 Python 的算法解析标题嵌套深」对吧。
A: 可 Myson 就不是直接分开的,觉得要写 RegExp Lexer ,不敢写,挺麻烦的。
B: 看了语法设计,是不支持 array 什么的,只能 key-JSONValue 吗?
A: 是的,只支持一种嵌套,就是更深=子对象
B: 这么说没有行尾冒号也没问题喽?
A: 按理说是这样的……没问题吧?
B: 我能理解,反正你打算完全用缩进深度吧。你又没有支持 optional 多行的语法,唯一的不优雅在于有冒号没用,没冒号的话已有 value 的行后尾随缩进增,就不易看出冲突了。
A: 那具体如何实现呢。
B: 只需要 split lines+trim count 就可以了,之后 line 实际上就是 k-v ,遇到更深的就视为上一行的 v ,递归展开成 JSON.parse object 的形式,检查下不冲突就行了。当然,缩进莫名上升这种就检查不出来。
比如:
小明
名字 "明天白"
年龄 14
朋友 ["小张", "小红"]
小张
名字 "张大奇"
年龄 15
最爱
世界 "你好世界"
伍六七 "excited"
突然想到可以这样.. Object.assign
某人 {"id": 1}
姓名 "小白"
朋友 "小黑"


A: 听你这么一说我都有把这个 publish 到 npm 骗 star 的欲望了(
B: 我觉得这个挺浪费的,当然 JSON 也一样,key 重复了那么多次,不方便写也不方便传输
A: 有什么办法呢,下一层是 csv 基于 row 存储,那个是 efficient 但是只能存 object array ,而且也不能有嵌套对象
B: 我觉得你加上内联 CSV 的特性,就真的可以骗 star 了。 噢对你还应该把 JSON2Myson 写出来,就是带 indent: string 字段的 TreeWalker 是吧。相信你会写,这对工具化很有用,毕竟 JSON 不好看
A: (若有所思)
B: 你还可以把这个做一个 DOM Tree 的后端,甚至直接变成一个模板语言
html
head
meta {charset: "UTF-8"}
body
a {onclick: "alert()"}
_text "你好。世界"


B: 对了, JSON2Myson 用于带缩进输出的递归子程序还可以对 k-v 里的 v 立即处理而不必再下层递归,反正顶层又不支持单个值,就当是优化了。
A: 打住打住…… 这当然可以,其实就是翻译 {} 吧。区分 Attr 和 childs 对复用性有些挑战,但我相信能行。

A: 对了,我还有两个小点子:
(1)infsw 可以增加 timedline MM:ss ; 此外还有 exec 与 statics 子命令,以及 event name 的自定义和自动修正 failed watch 的 argv filter ,因为 watchdog py 的 watch medo/exec 和 inotify-tools 的 cli 都太麻烦,就自己写。
(2)之前的 OGL 频谱透明动画可以加一个纵反向的功能,利用 xdo 跟踪到窗口顶端什么的,像 supertuxkart 这样的游戏就可以当音游玩了(迫真)
A: 说起来卓依婷是谁啊,写的歌好熟悉呢
羽毛的小白板
https://www.zhihu.com/question/20210025/answer/1744173869
#zhihu #net #cplusplus #Haha 什么? send/recv 次数对应?那返回 size_t 是给你检查错误的?!🌚
TCP 不是基于 packet 的,基于数据包的是 IP 网络层, TCP 是 SocketStream ,字节流,它是传输控制层,哪有「包(packet)」这个概念?

“手动 static size 拼包?你在教我 TCP 做事,还是说你用我 TCP 干嘛?”
🤔 #school #cplusplus 妈耶,可以考虑下兼容抽象层 getNewChar() 和 fpsLoop(fps,op) ,支持 std::queue 和 ringbuf , termios 和 wincon 。
想了半天,学习了下条件断点如何使用( i%100==0 ...) 最后还是不知道为什么 getchar_nonblock() 是 linebuffered ,以及为什么会 segfault...

毕竟 fps 限制是没有 dt 计算的程序必须的,本来是 while((ch=getchar()) 的,看来 sleep 再试 get 也有必要变成在 mainloop 里测试了
duangsuse::Echo
接续上次贪吃蛇,但也最终没弄出多玩家和朋友玩,而且连 dt 时差都没算,额(当然弄出来了也很不满意,因为高二的大佬都会给五子棋加 AI 了 贪吃蛇难度巨--) 下课后几个同学开起这段小程序的玩笑,「怎么没豆呢」「吃了都蛇咋不长呢」,还问我能不能搞出植物大战僵尸来(当然不行啦,除非只有字符画 但也要300行最少) 我熟悉了下 C++ ,用的 new struct * 和 std::queue ,中间出了三次非常有意思的问题。 1. 动画不动但帧明明在刷新(当时快崩溃了 根本不知道为什么 还以为渲染有问题),地图蛇头…
#school #life #cplusplus #web #algorithm #statement snake&dom 🤔
感觉这个实在是太幼齿了,下次一定要加速啊(关于游戏 只会一两个模板就太可惜了)

对了,没有网的话怎么消磨时间呢? #Google #DontKnow Dragon Trex 小恐龙!
这个东西的源码不在页面上,查 event 注册什么的应该也看不到,但通过 Performance 快照,或者 Network 查 canvas 更新的 initiator 能找到 VMno 脚本号,可以看见它把 Runner 类暴露了。

作弊小技巧: r=new Runner(); r.gameOver=console.log; r.restart();
这样 Trex 就不会 GG 了,而是永无止境地跑下去 -_-|| 仔细看还能发现月亮 spirit 是有圆缺更替的,非常细心。
整个脚本是没带框架的,还包括碰撞检测程序,啊真是非常完整呢。
#CG #cplusplus 草,直接把渲染层 pipeline 整体给参数化了…… 还是 yaml 支持
#cplusplus #sql join 是按AB共同键的相等性过滤。中间三角是交、并、并-交
总之 join B on A.k=B.k 左交就是A+B查询,加 where B.key=NULL(仅选B没有的部分) 就是 A-B
所以L/R/inner/fullouter join 的复杂度是 O(nn)这种 for(a)for(b)

此外SQL 还有GROUP BY HAVING(=where)
#dev 现在的许多傲慢消失了,感觉好像啥也没专门去学一样😌

以前觉得组合器是特殊的,现在只是利用设计DSL
以前想长就是好、快,现在长就是烂、空洞
以前想多就是系统性,现在多就是冗余、套版

以前觉得CSS盒模型是坏的,现在发现它比其它平台更适合而贴切,言词不多,贵在扩展
以前想代码生成是大的,现在FileTree+列表处理 随手就能做
以前想反射是难的,现在发现只是名词太长,class{val/*field*/;@WTF fun} 没啥不好区别,换框架看文档对个名词就成
以前解析器是不会的,现在提取前缀,组装返回值,预过滤行号流、记录span词区间 ,根本不需要分词器或任何工具和严谨

以前不知道UI框架里线程做什么,被 web 的 timers,worker post/onMessage 等 0阻塞API 矫正了,原来Thread级阻塞去 event loop 就是检测手势,查找调度Task 的,而并发异常只会随机出现; 队列是数据,随便在哪 add pop 阻塞poll;懂了为啥想放几音乐不能用for、想 fetch() 要暂断执行此函数 await 或.then(op)

以前没看到nav浏览栈是什么,被 web 的 PJAX 矫正了,原来可把生成View的数据保存pushState起来,也因此理解内存对象不都可序列化
以前不会HTTP和Cookie(服务端KV之K),现在只想大的API绑定,忽略无关数据交换的细节 httpd((req,res)=>res.write
以前不懂 SQL 和ORM,现在我只当它是严谨化加速列表处理过滤,以及事务和JOIN
以前连分页都觉得好神奇,现在 a.chunk(2)=[a.slice(0,0+2), a.slice(2,2+.. 和类似的列表处理写过无数;各种控件 tab,slideshow,fab,drawer,drop-upload 也早不稀奇,反而觉得还不够可配置

#PLT ”动态语言“ ”脚本“确实不严谨,但class{}大定义也是从小程序组合起来的,只在框架内思考会失去对框架本身的认知、放弃优化框架的可能。 例如反射只是元编程的运行时形式,«Ruby元编程»是本好书;编译期和运行期差别只在有无变量、编译解释只在有无缓存,代码生成是编译期计算。 强弱类型在于兼容和转换的显式隐式,类型推导可以让用户少手写编译期信息,类型检查能让人和机器少犯傻。 语法和语言工具用于表达,写法只有缘由,没有条条框框。
JS和CSS,JSON,YAML,HTML ,都是嵌套结构构成,只是人赋予了JS执行序、计算变量,而只让JSON解释为构造1数据--prettify又怎不是1数据 ;结构相同语法不同、数据相同命名不同,等于完全相同
效果相同类型不同 —泛型和 map,filter 函数正是如此
好的优化能让人知道。而不 prof, %timeit 怎么知道性能快慢

多观察或许就可预测,可预测或许就可控制。 被带偏或试着控制,各有好处,但没有理解缘故就只能被动模仿,束手束脚害怕出错。
就好像一个未良好复用的动作,能少一行代码,却会造就整个软件、更多软件里无数多余代码、不完善功能、高学习难度

以前不知模板和 animation/queue 是什么、粒子是为什么,现在我自己做过
以前不会二进制,现在 Read/Writer 流都被我抛了,我想0copy直接mmap()绑定,不停留在”Int=4x Byte“
以前不会画画,现在 arc rect fill stroke % alpha hsv(hsl) 一把梭,视频和参动之画也绘,了解向量计算=角度无关位置=(A-B)0点角,也认识到”非主流“ GLSL 打散绘制的方便
以前不知道值类型(全复制)、位置引用和惰性计算/编译期宏,和许多函数式Type术语,现在大致分清了
以前不懂编译原理,现在从 ASM chunkspy r2 libdl.so链接器 objdump shellcode 看到了更多、从 kamet 了解了 AST->LLVM::Value 树转化、地址和类型处理

从逆波兰了解了优先序重排和栈,从S-expr嵌套列懂了局部变量=栈位置 及()=>{} 闭包是程序+变量数据的实质;从无数次重写中明白了编程的实质是表达思维,多余代码只是环境限制
从函参返memo 了解了递归缓存与伪递归(递推) ;从深先树遍历了解了 DFS/BFS 途径/可达搜索,以及有更实际的 Dijstra/A*/JPS
从前缀树Trie+failPath=AC的关系了解了状态(自动)机、KMP的Map状数组了解了OI的一些惯用法,试出了1行的JS后缀合并树,从B站的一些视频明白了算法有许多讲法,之间差异也很大
从自顶向下,伪(左)递归转循环、去除流回退(peek/backtrack)到 LL(预判=k) 机; 到自底向上yacc/Simp?LR/LALR ,我不做无意义的打断优化;不把大状态机+报错,嵌套表等小儿科当编译原理。 别只用切碎的程序状态解释实现目的,复辟冯诺时代编译-汇编序列模板


以前很讨厌设计模式,现在会区分 Visitor,Delegate(T-by-obj,"proxy"),Observer 等真正的设计模式和

Chain(责任链),Adapter,Singleton(lazy),Builder(return-this链),Factory(选择子类new),抽象Factory(选中子类构造器), 等假装的设计模式和
Iterator,Context,Prototype(链上级虚表),Filter, SvcLocer(Lazy ctx+调用cache),

State(废话,啥函数不看this val),模板(废话,OOP封装继承是为啥的),策略(废话,OOP接口多态是吃白饭的),Command(函数闭包) 等非设计模式
明白 FP与OOP 间的异同,闭包即SAM对象,对象即 send(fname,*arg) 闭包

以前只会Java 甚至AWT/swing/net 都记不住,现在 JS/TS,Python,Kt 都是常用语言,也会 Ruby,C#/Powersh, C,C++,Scala/Hs ,我会在JS和Python 间按API和UI选择写脚本处理工具
以前害怕项目build定义,现在讨厌
以前觉得真理是系统性的,现在觉得真理也可以有开头和前言

以前相信教条规范,现在明白教条和权威也有局限性(比如不会自动化重构),需要择优
以前相信web是菜鸡聚集地,现在明白有人在写的 和你不是一个JavaScript
以前相信原理是极少数人在学的,现在明白任何人做同样的事情,也有选择与目标

以前觉得C难,现在知道C难点,以及导致难点的历史目标与时代局限性
以前只能看到app"前后端/桌面" ”小工具“的一亩三分地,现在明白嵌入式、各框架游戏、专业软件 比它们更有趣
以前尽量严谨,现在废话要简写,突出顺序和重点

我学到的最终不是知识,而是简化知识的方法
我编写的最后不剩代码,只是代码后的目的
duangsuse::Echo
#recommend #ce 不可能单单靠 #bing 的建议实现解释器,甚至(逆波兰)计算器。 它的回答太零散,而且分不清AST解释(对象的重写) 和代码字面,更难以解释语法为何设计如此;但可询问语言的构成 #plt
唉, 自己作为程序员也应该重新考虑编程的方向了

以前完全搜不到的技术,依赖少数人语文素质的技术,真的变得人尽可用、只剩重点,那些七零八碎的乱代码真的消失了,一时间还有点接受不了
但这又是我强烈要求的代码优雅性.. 人真是矛盾的动物🤔
一边说简单,一边心里有优越感。

#bing 又真的能懂巧妙的算法,如果只想运行,编程只剩下最后一公里能写了..

难道这几年的努力,真的只是为成为「创作者」铺垫功底吗
这些功底AI能不能搜好给我呢
https://tttttt.me/dsuse/15666 的字符画动画,AI生成的也完全能接受,但我就花了一晚上调试
以后只能做
https://tttttt.me/swiminthedream/1292 这种创意性吗

我以前的代码在我眼中确实不够看,但如果AI的思考不再受现有code的限制, 我现在的设计想必也是能被生成的