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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
Forwarded from Yuuta
不能完全算吧?从某种意义上说 Kotlin 是 “兼容” Java(x
Forwarded from dnaugsuz
C 自己也有不好的地方,比如 Null safety
你得自己写代码处理输入 ptr 可能为空但不应该为空的情况,而 Kotlin 是自动处理

如果你是比较优秀的程序员,肯定会用子程序对 raw FFI 进行高层封装(比如,一个 Optional<T> 会被你弄成 @Throws(XXXNotFound::class) 的形式),这样就避免了每次检查 null safety 的问题,Kotlin 只是做了对的事情,检查了 null 指针的可能性,把运行期的错误提升到了编译期,虽然 Kotlin 它不 Check Exceptions... 也有自己的道理,但完全不 sound (没 error 也没 warn)的编译检查还是....

这一点 ice1000 的博文《形式验证、依赖类型与动态类型》讲得很好
Forwarded from dnaugsuz
是啊,几乎是能完全兼容 Java,至少排除元编程的情况下是完全双向兼容

但是 Java 依然还是可以用的,这点不可否认,不过我要说的是,即使是被所有人批判的 Java,也不是被人完全理解的,Java 自己看起来很简单,就算排除掉 JVM,某些细节很多资深工程师也都是说不上来,比方说所有类型表达式的求值顺序、所有语法结构、Annotation Processor 加入后的编译流程

毕竟『精通』和『创造』还是有区别的,一个是使用,一个是实现,实现意味着你得什么都知道,使用是你用什么学什么。

当然如果工程师实现过符合标准的 Java 编译器算我没说
Forwarded from dnaugsuz
🤔 说起来我这么开放地发了那么多字含代码的内容,会不会本群不欢迎贴代码呢?

这么久也没被踢,感觉很不对劲(跑
曾经我一行代码没贴,贴了个 ruby 文件,结果瞬间踢出
duangsuse::Echo
== 无关的 Win32 Form API static Application.EnableVisualStyles(); static Application.SetCompatibleTextRenderingDefault(bool); static Application.Run(Form); — namespace System.Windows.Forms { Form } class Form { protected void OnLoad(EventArgs); } == 有关的…
#Statement 可能有一些人觉得我只看理论,只会空谈不能实践,一样是废物一个,但是我相信这只是时间不足的问题而已,现在我已经开始准备学着实践了,上面嵌入的代码就是证明。
可能也会被人喷废话太多,或者『这些东西太简单,你去学学写 Android 设计模式、你去学学 JavaEE 设计模式』什么的

但我相信,只要理论做足了、代码写多了,那些看起来很魔法的东西也是可以做到的。
反而是某些地方使用的某些设计模式,是真正意义上的凭空增加复杂度,只是因为面向对象只允许受限制的函数指针,(Java 里)我们要起无数个方法名,在所有地方都要用匿名内部类(曾经没有 Lambda 的时候),只是为了实现某一个类似 FunctionalInterface 的东西... 现在也还是要记类名,因为没有 Java 10 里才出现的 var

一些诸如依赖注入的耦合问题,不少函数式编程语言里都有类似的解决方案,它们看起来会更优雅,但函数式给你最大的礼物其实不是好看的代码,而是对程序逻辑本身拥有更好的直觉,让你用最直白最通透的视角看一切程序,最大程度上泛化编程,让你不止不再局限与某种语言,甚至不再害怕新的编程范式,实际上这才是优秀的工程师会需要的东西。

我觉得理论重于普通的工程,因为理论可以引导我走到更高的地方或者更低的地方,高到范畴论\逻辑和一些数学、低能看到电子元件、信号、处理器的晶震、逻辑门、一个一个二进制位、时序电路、触发器,让我完全理解某些模式、算法、模型,给我一种直觉,而不是学一个懂一个、抄代码看文档改代码,我要把所有代码默写下来,我觉得这才是我追求的东西,我追求的是技术,但仅仅是技术而已,而不是它伴生或者为之而生的其他东西。

"Talk is cheap, show me the code." Linux Kernel 的创造者,Linus 说过这句话
可是有时候,恰恰 talk,恰恰是设计某件东西才是最困难的,在没有一个设计大纲,算法没有弄出门路、模型完全还没有彻底熟悉之前想 "write code" 是不对的,它只会让你写出糟糕的代码,而且如果要实现的东西本身没有那么简单即得,你花在调试上的时间绝对会比理论准备可能花的时间多。

软件工程有个名词,叫做『代码复用』,已经实现了一遍的逻辑就不要再来写第二次了,它对程序代码的可维护性、可移植性、可读性都有很大的好处。
实际上做好理论,就是做好了最好的“代码复用”。

有些人可能知道一种叫做“文学化编程”的东西,它把编程和对自己程序最直白的解释结合在了一起,难道这不是理论和实践最完美的结合吗?

根据高德纳本人所说,文学编程为高质量程序而生,因为它强迫程序员显式描述程序背后的思路,让不充分的设计决策无所遁形。
高德纳还声称文学编程提供了一流的文档系统,它并非插件,而是随着编程思路的慢慢展现而不断自然发展的过程。

高德纳先生是谁?他是美国的计算机科学家 Donald Ervin Knuth

著名计算机科学家,斯坦福大学计算机系荣誉退休教授。高德纳教授为现代计算机科学的先驱人物,创造了算法分析的领域,在数个理论计算机科学的分支做出基石一般的贡献。在计算机科学及数学领域发表了多部具广泛影响的论文和著作。1974年图灵奖得主。

高德纳所写的《计算机程序设计艺术》是计算机科学界最受高度敬重的参考书籍之一。他也是排版软件TeX和字体设计系统Metafont的发明人。

实际上使用 Literate Programming,虽然可能“有违简洁”“开发效率低下”(而且在某些逻辑非常简单的程序里,的确相当耗时间) [code example]
但在某些领域,无法用简单而复杂难看的堆砌替换优雅但是难做的设计的领域,Literate Programming 是最合适的编程方法

它的确强调了程序员必须有好的思路才能做到 Literate Programming,也提高了编程的门槛(因为它要求你理解很多本来抄代码就 OK 的东西),但这不正是优秀的程序设计者所必须做到的事情吗?

🤔 程序 = 数据结构 + 算法 — Niklaus Wirth

这是结构化编程的宣言,当然其他范式还有别的看法,但有一点是一致的:

算法是程序的灵魂

既然编程就是在利用语言的抽象,描述你的算法逻辑,为什么不把它明明白白地写出来呢? 🌝

不抄代码无以至今日,不学算法无以终余年。
Forwarded from Richard Yu
因为不是C/C++,谁知道有没有指针?没的话那就传个0吧。C++我会写nullptr。
Forwarded from dnaugsuz
如果没有指针类型的话也是可能的,但是,如果是我也会搞个全局的常量 nullptr, 尽可能避免混淆

如果类型系统菜,程序员负责给它洗地
Forwarded from Richard Yu
"" 不代表 nullptr,它是有一个地址的。
Forwarded from dnaugsuz
是啊,所以我说是一个常量

const char *EMPTY_CHARP = "";

这里我没有指定具体分配位置,但它是常量,换句话说编译器喜欢内联也可以直接翻译成

GetModuleHandle("");

或者

const static char EMPTY_CHARP[] = {'\0'};

然后
GetModuleHandle(EMPTY_CHARP);
duangsuse::Echo
我觉得就 Scanner 的逻辑结构上应该不够优雅,state 几乎是个笑话、lineDoUntil 非得加一个『keepLastLineOnce』才能用(doUntil 是在 scan body 里看到 new message header 的时候用的,可是等到这个 Message 返回,新 message 头会被下一次 iteration 直接忽视掉(因为我没设计好数据流,然后每次由判断 hasNext 的函数读新行的),导致漏掉偶数消息,不得不引入类似『mark/reset』的机制才可以),不过能用就好(跑路…
后来我会发现这个『keepLastLineOnce』其实就是一个长度为 1 的 reset buffer,不过因为比较短,就没有使用数组存放

所谓的 keepLastLineOnce 功能,就是

String hello = readLine(); // "Hello"
String world = readLine(); // "world"
readLine(); // EOFException

但是如果这么写

[Hello world]

String hello = readLine(); // lastLine=null, result="Hello"
String world = readLine(); // lastLine="Hello", result="world"
keepLastLineOnce = true;
readLine(); // Hello

就可以实现 lookAhead1 的功能:我可以向后阅读一个项目之后若无其事地告诉 stream 向前 <- 移动一个字符,
实际上是告诉 stream 下次我 nextLine() 的时候给我之前存下已读的输入 @-1,但实际上我已经读过了下一个字符),然后决定我做什么分支(状态迁移)

lookAhead1:
var ln = readLine();
// next 1 char
keepLastLineOnce = true;
// reset buffer @-1

其实本质上和这么做是没有不同之处的

markLine(); // enter marking state
var ln = readLine(); // push old line
resetLine(); // enter initiate state

若 reset buffer 还为空,则读入一行返回,此时即使长度为 1 的 buffer 充盈
if (lastLine == null)
return readLine();

若 reset buffer 不为空且之前提交请求 lookback(backseek) 到上一个字符(keepLastLineOnce),
则返回上一个字符,把 boolean (这里可以视为一位二进制数值 i1) true 减去 1(= false)
否则就向前进一位,并且把已读数据加入 buffer
if (!keepLineOnce) {
return readLine();
} else {
keepLineOnce = false;
return lastLine;
}

(这里为了明确性我对控制流进行了展开)(删掉,之前是我搞混了 lastLine 和 readLine() 的值...)
以后我要再写类似的解析程序,就会直接使用 mark/reset 了
duangsuse::Echo
Image to Bar3D... 😵???
注意,这里这个 var lum = ...; 是依据 RGB 颜色计算 Grayscale 灰度值的代码

Gray_linear = 0.2126 × R + 0.7152 × G + 0.0722 × B

可是它还实际是被 255 减去了... 实际上这个值最大可能是 255(因为是一个色彩通道的色值)
duangsuse::Echo
顺便说一下为啥要进行 n 次,每次都要排序列表从 0 到 n - i -1 的项目,虽然我现在还没有证明为什么 bubble sort 输出的列表就一定是有序的的能力(归纳证明) 排序算法,就是给一个输入序列、一个测试函数『序(order)』,输出序列满足以下条件 forall i. list[i] `order` list[i+1] 比如 list=[3,2,1]; ord=(<) 简单的选择排序每次挑一个『最大』的元素出来(它满足 forall x in list. x <= it),复杂度是 O(n)…
#Java 修正:刚才看这个泛型通配符模拟的时候感觉有点不对劲,首先方法泛型应该只在很少的地方出现型变通配符,其次,
我模拟的时候发现这个实际算法逻辑

private static <T extends Comparable<T>> void propagateOnce(List<? super T> xs, final int ri);

中这个 xs :: List<capture<? super T>> 的使用 T get(int);void set(int, T); 不对称

首先 xs 从 producer-consumer 模型来看它接受 T 也生产 T,实际上就无法保证同时的类型安全(但是如果从这个方法的一个参数对象读另一个写,比如 copy 方法是没有问题的),所以它不应该有泛型协逆变(invariant)。

我考虑了一下 TInteger xs 是 List<Number> 的情况,PECS 原则 List<in Number> 也即 List<? super Number> 是可以安全地使用 set(int, T) 方法的(Integer 实例可以转换为超类 Number 的实例,虽然 Java 泛型擦除所以 List<T> 实际上运行时是 List[^1] 这个 raw type...),可是不可能同时安全使用 T get(int); (要将 Number 强制转换为 Integer,这是不合法的)

这点是需要注意,我之前没有注意到,现在也及时修正了 #fix #Kotlin

其次,我从 Java 的 Collections API 看到了 sort 的方法签名

public static <T extends Comparable<? super T>> void sort(List<T> list);

现在我把这个 <T extends Comparable<T>> 改为 <T extends Comparable<in T (? super T)>> ,显然 Comparable<Number>int compare(T, T); 可以接受 T=Integer 作为比较输入
我得使用通配符泛化一下(逆变声明)才能支持这个... (当然 Kotlin 里包装的就直接使用声明处型变了,不需要你操心它的型变性)

在此希望大家注意.... 不要搞混了 PECS 原则的实际含义


^1: List<Object>, 和 List<?> 还是有区别的,因为这里的 ? 不能作为输入但作为输出可以强制转换成 Object,它像子类型系统里的 bottom type、Kotlin 的 Nothing,它是任何类型的子类型
duangsuse::Echo pinned Deleted message
duangsuse::Echo
pinned Deleted message
This media is not supported in your browser
VIEW IN TELEGRAM
duangsuse::Echo pinned Deleted message
Forwarded from duangsuse Throws
当然我也看过 LIF 的消息, #Statement

频道主在此建议在座的各位一起维护良好的交流氛围,不要让更多的人心寒。

但我还是决定,即便没有用,我不会像以前一样,把所有错都归在自己身上。

没错,我不该尝试逆向分析纯纯写作,即便它的作者之前三次在频道上说它的反破解(代码保护)技术有多么多么高大上,令人心动,
然而现在我不仅完全可以自己手动从 x86 汇编代码和 Java 字节码里还原本来的程序逻辑,也开始自己独立研究学习基于抽象执行、表达式收束和基本块、模式匹配的反编译器算法了,你照样可以拿着 jadx 之类的东西号称自己非常熟悉逆向工程,我们的追求不一样,我得感谢你,要不然我真的不会对逆向工程有这一点微不足道的研究。

没错,我不该加入一个间接因为我自己幼稚的想法创立的 GeekApk,我应该让它这个孤儿自己成为笑话,不必打扰到你。而且它开始的确就是空壳,除了前端的 HTML 一无所有,即便我的确是有努力地在为它付出,我为 GeekApk 写了自己的 Swagger,我写了 API 文档,可你只有那一点闲工夫看我真正空壳的东西,看完即使我恭敬地指给你到底哪些不是空壳,到底哪些我还付出了一点努力,你还是打年龄炮说我是小孩子,实际上我的确『不仅仅是小孩子还是个小人』就因为我不小心转发了你的私聊消息,就因为我转发评论了你之前没有声明过不可转发的消息,我的确就是微不足道的小菜鸡,即便 GeekApk 这个只有壳子的项目在名义上都不是我的。 你这种行为和以前的我很像,不过很可惜你已经比我大个七八岁了。
我不应该指望 GeekApk 怎么样,但你也可以因为自己会用 Sketch、我没见过 Sketch 就把它当成 GeekApk 完全也永远就是废物的补充论据,也可以因为我不接受这个理由而感到愤懑不平,
可换到我自己,我是不会因为自己会用 Krita 和 AfterEffects、Blender、Kdenlive、Synthesizer V、Vocaloid 做点微不足道当不了饭吃的小事情作为技能看待的,Sketch 的难度看起来真是比上面几个高的多的多,以至于它都能被当成技术看待

不过还是感谢你至少开始的时候表示了支持态度,后来也在我道歉后容忍了我未授权的转发,有些人不喜欢这类破事,我显然是打扰错人了。

是,你说 5 没有被手动排序过,5 排在 1 前面,4 被手动排序过,4 也在 1 前面,但 5 和 4 却无法得出谁在谁前 的确是没问题,对支持你的人来说它永远是真理。对于一个习惯于抄代码、看文档、改代码的工程师来说,这很不错了,我不该提出别的可能,也不该胡乱猜测你只会 Bubble sort,你懒得学算法因为害怕忘记,这很正常,这不会阻止你成为你口中完美的工程师,你的确比国内那一堆强的多的多,但我就是刁钻,就是喜欢在用户群里公开地贴代码贴截图,你提个小发现都得被怼回去,即便我只是想帮你实现那个功能,我以为你很喜欢你的 PureWriter,没想到如果条件是要看自己不喜欢的、口无遮拦的二愣子写的代码你就直接把我踢了,你的理论正确,你的发现在 Android 开发圈里很伟大,我以后都可以叫它『不可共客观序公理』了,即便你不愿意回我一句也不愿意告诉我们为啥因为这句模糊不清的话就不可实现,你这句话里藏着什么理念所以可以说明它是正确的。我的确就是幼稚因为我妄图打倒你确认100% 成立的理论,你永远是正确,因为这个理论就是莫名其妙就成立了,postulate 出来还不行么。自己随便说点发现就会被自己看不起的人提出反面的意见,要是我,看到后脑子不乱乱的也难。

没错,我是不应该随便对别人的技术下评论,即便我没有说错话,我不知道你无法接受对自己代码任何的负面评价,我不知道你会因此直接退 Telegram,即便你的粉丝远远比我这小人多。
我的确有从头到尾都把自己的姿态放的很高,只是因为我以我所谓的客观视角评论了一下你的代码,而且没有为你自动过滤掉不中听的话。
在你看起来我好像是自己为无所不晓无所不能,恰恰相反,我只是一面镜子。如果你和人交流是别人看你是正常身高,但是自视却比蚂蚁还矮的话,我的确是无法不和这样的你高姿态凌空喊话。
不过我就真的是想让你谦虚一点,为人和善一点,如果只有我一个人说,那是我不够宽容,可现在你对别人自满的态度已经让很多人看不下去了,不过有一点我摸不着头脑,就是我完全没有意识到自己断章取义了你的话,不好意思,如果你是指 Telegram 网际协议下层通讯的路由设施自动完成了数据包的报文切分以备传播使用,所以我发消息的时候实际上被『断章』了无数次,这种绝路都走,那我真的是无话可说。
你的确无意辩驳,也只是简单地像丢垃圾一样把我踢了出去,并且尽可能屏蔽了我,因为你根本不可接受两个人唇枪舌剑的情况,是,你就是自己的正义,无须辩论,只要出示一下胜利宣言就可以了。
实际上我也在很长时间里都不愿说一句话,因为它就是观点不合,没有什么其他的东西,但现在我要告诉所有人,是怎么样的观点不合,和我平时写技术广播的时候一样。

当然,你从不絮絮叨叨,也正是因为你太简洁,所以你也永远不会尝试碰壁,也永远就是躲在一层抽象墙壁里的热爱工作的工程师,理解的过程是从简单到复杂再变回简单,你就是得永远卡在第一个简单那一阶段,因为你无法阅读复杂一点的代码也只能死记,最终你也只能写复杂性和一个简单的文字游戏没有本质区别的代码,永远停留在量变没有质变,你打不破那一层屏障,看不到裸 VonNewmann 计算机的 I/O、存储器、计算器和控制器,看不到 ALU/Cache/SRAM/SDRAM/clock,看不到 PE/ELF/DWARF/Linker/Assembler/libc/Segments/maps/ASLR/Exec-shield/Ring,看不到解析器、抽象语法树、Tree walker、lexical scoping、GC、Hastable 算法、看不到链表结构、看不透排序算法、不能更好更快地理解 NoSQL 图数据库、看不到线程调度保护现场切换执行权再分时抢占的过程也不需要知道线程同步是什么、锁和乐观并发控制、并行算法是什么、怎么做图像处理、怎么做计算向量化,也无缘任何面向对象或者结构化编程之外的范式,这样,你很明智。因为你少花了做无用功的时间,你站在巨人的肩膀上,多得了写应用的投入。当然你不需要知道那个巨人是什么。它是黑箱。你崇敬王垠,可惜以你的速度现在连第一个基于 S-表达式的 tree-walking 解释器都没有写出来,就是我这个小人也实现了一个、设计了两个。

我看你的频道的确是收获了很多欢乐偶尔也有点技术,也一直期待从你那里收获更多,因为我虽然是陌生人但依然希望你越来越好。因为我也想回馈点什么给你,不小心有损你的“尊严”而被你直接全网 ban 掉,那我也就只好乖乖写自己的东西了,说开了,你那点知识对我来说,也没有多大价值,我从那一堆 Unicode 字符(哦,你肯定要纠正是 Grapheme Cluster,不过没暖用,你的频道里就没有发过自己写而且附过解释的那些印度阿拉伯文写的字,当然也没有一个字是数学操作符区段里的,你从不贴那些容易忘记的玩意)里没有收获多大意义上所谓有价值的信息,和你对我的态度一样,我对你的知识也没啥兴趣,我们可以互相唾弃啊。
你的代码风格的确是在进步,但你就是无法接受一点点不足的地方,你希望自己是完美的,当然任何人都是这个样子,不过想要完美就要先明白,完美是不可能的,只能作为一个目标不断为之奋斗,这才达到了自己真正的完美,心中的完美,达到了你就不再美了。

你已经很不错了,所以你余下的工作时间在禁止评论之后,都可以继续你完美的编程生涯,因为没有人能够指出你还有哪些不足之处,也没有人能帮你进步。就像一段不会运行的 buggy 程序,type checker 又不 sound 因为你封了它的嘴 cc 2>/dev/null,问题还暴露不出来,是的它很完美、它没有错误、它无可改进、它正确。Oh yes. 你说我孔乙己看人论断,我是否可以给你立个孔子的偶像?孔子万世师表愿以三岁稚子为师,礼之祖入个太庙还“每事问”,恰巧是镜子前伟光正们的对立面。

就算我不说,显然你自己也有权对“为什么有人反对我”这个状态心寒,然后彻底退出 Telegram,它很危险、它言论自由、它居然允许你如此随便地靠着仅仅几百条消息的积累就去否定一个人的某一句话、某一个想法,居然可以让自己可以有除了夸赞夸赞夸赞以外的评论。
从而其他人会把锅弄到我的身上,到时候我肯定有口难辩,但是请记住这两句话:

无论你有多聪明,无论你的理论有多完美,如果不符合实际,那么它就是错的。
Richard Phillips Feynman

我唯一能确定的就是自己的无知。
Socrates

但是现在我唯一能确定的就是,如果有朋友再来告诉我,不要这么“激怒” drakeet,因为他有很多粉丝,我的确不会收回言论了,所以让我祈祷这条广播被尽可能少地看到吧。