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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
duangsuse 重构小讲堂(迫真)
duangsuse::Echo
首先我们来学习第一个模式,拼接 Uint8Array fun concat(buf0, buf1) { let buf01 = new Uint8Array(buf0.byteLength+buf1.byteLength); buf01.set(buf0, 0); buf01.set(buf1, buf0.byteLength); return buf01; } 注意 buffers = buffer; 那一段的类型正确性: buffer 没有 it.buffer.byteLength? 其实用…
better flat than deep 之所以是一个原则,是因为若不作为原则,它也不是不可替代的选择,例如
if (p) {
f();
}
cont();
当然也可以写成
if (!p) return; // 或者 break 之类能够跳过下面的 else branch 的东西
f();
cont();

但是,语义上条件执行并不能证明 if (p) f(); 或者 if (!p) { return; } f(); 是唯一的正确选项。
较浅的块嵌套层次对好的代码很重要,比如 Promise——把 callback 和 error handling 结合在一起,如果我们用 onOver/onDoneif (res.error) else …… 那代码还能看么?

对于代码来说,一致性也是相当重要的——所以当你开始降低嵌套层次,就会更容易和其它浅嵌套的部分契合一些,也更容易发现可以重构的一些细节。

我们来看看一个更广义的 if:(下文 f() f1() 是对立的两条分支, cont() 是 continued block 的意思)

if (p) {
f();
} else {
f1();
}
cont();


如果我们用线性指令流来表达:

(br.not b) a (jmp c) b c
或者
(br.if a) b (jmp c) a c

其实控制流图上,c 一般被称为 merge block…… 这里就用 cont() 代表了:P

这种 if/else 的结构没法用 early-return 改写,举个例子:
if (!p) return; f(); cont();
(test p) (br.not return) (call f) (call cont) return

if (p) f(); else f1();
(test p) (br.not f1) (call f) (jmp cont) f1 (call f1) cont

但是 if (!p) return 的 false branch 不包括 cont 就是了,如果 dirty 一点可以随意 jump (goto),但不建议。

不过,如果有可能还是得做进一步封装,比如 C++ 里如果 cont() 仅包含对资源的 close(),你就可以用 RAII(resource acquire is actual initialization) 技术,它能够在离开局部作用域 (return, ...) 之前自动回收资源。
This media is not supported in your browser
VIEW IN TELEGRAM
原来现在技术已经这么成熟了,好羡慕 SP/ML/CG 的dalao们啊
https://github.com/dhakehurst/net.akehurst.language/blob/efafa3e57f89ddea2f81ca3080121f2e70cce9e0/net.akehurst.language/agl-processor/src/commonMain/kotlin/processor/LanguageProcessorDefault.kt#L94
草,觉得可以学习一下,自带补齐方法
override fun expectedAt(goalRuleName: String, inputText: CharSequence, position: Int, desiredDepth: Int): List<CompletionItem>
override fun expectedAt(inputText: CharSequence, position: Int, desiredDepth: Int): List<CompletionItem>
https://github.com/dhakehurst/net.akehurst.language/blob/efafa3e57f89ddea2f81ca3080121f2e70cce9e0/net.akehurst.language/agl-processor/src/commonMain/kotlin/parser/scannerless/InputFromCharSequence.kt
看到这个“新”Parser lib 我就知道 ParserKt 的设计是有多不容易了……
遇到 parser 既没有 lexer/parser 又没有 TERMINAL/NON-TERMINAL 还不强调scannerless因为它本身概念上就不存在scanner这…… 虽然和 Haskell 系的 Parserc 差不多,但更 Kotlin 一些
如今又得重构了……
https://github.com/dhakehurst/net.akehurst.language/blob/efafa3e57f89ddea2f81ca3080121f2e70cce9e0/net.akehurst.language/agl-processor/src/commonMain/kotlin/parser/sppt/SharedPackedParseTreeDefault.kt

这一系列操作…… 很算法啊
一般类似 ANTLR 一样的工具也会有 rewrite/action 的选择吧,可这个几乎只有 SPPT(shared packed parse tree) 一样……
ParserKt 是纯递归下降解析组合子,所以没有 YaCC 系的 Parser-Tree 说法,只有内部递归的调用树和临时的 Fold 对象,没有这种……
#Telegram #sysadmin 🤔好方便啊,自动更新
Forwarded from 〄FW
Forwarded from dnaugsuz
This media is not supported in your browser
VIEW IN TELEGRAM