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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
%timeit codeSer.loads(codeSer.dumps(c))
34.6 µs ± 103 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
from pickle import dumps, loads
%timeit codeSer.loadItems(loads(dumps(codeSer.dumpItems(c))))
25.8 µs ± 405 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

还好我写的抽象层有支持…… 就知道跑不过 pickle ... 这个变态腌黄瓜。 ☹️
This media is not supported in your browser
VIEW IN TELEGRAM
不想删啊…… 早知道用 struct 不合适的,而且它是个贼老的东西了,为了支持动态长度字符串我还加了 hack
性能渣是肯定的... 还是换 Pickle 后端好了
腌黄瓜实在是太过分了,我好不容易给 struct 弄好字符串支持的
早知道就不给弄了,草死了
duangsuse::Echo
完成了! 不过不知道是 pickle 性能高还是 struct 性能高... 反正我懒得写 pickle 版(花好大力气完成的复古
还有一个更过分的(主要是因为我不了解序列化的泛用性...)
from marshal import dumps 可以 dump Python 的 code object ,而且它就是用来生成 .pyc 文件的那个
虽然不能跨语言版本,但我要的代码缓存就是这个啊……

In [19]: %timeit marshal.dumps(c)
703 ns ± 4.27 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

而且它还超级快……
看来只有要压缩的情况下我写的代码才有一丢丢意义…… (它的存储比 marshal 的结果短... 1字节)
This media is not supported in your browser
VIEW IN TELEGRAM
struct,json,yaml,pickle,marshal 等序列化便利库我都用过,无非就是流 dump/load 和便利性 dumps/loads #Python #backend #bin

对于二进制读写的数值读写、字节序解释我也清楚的很, Kotlin Dokuss 和 SomeAxml(挂名) 项目都包含了基本二进制流和读写抽象

序列化(serialize)的用途一般是以二进制表示某种数据, marshal 和 pickle 虽然都是对象序列化,显然 marshal(封送) 更广义、更内部, C# 里也有这个名词,用于在进程间传递数据对象的深拷贝,也类似 android.os.Parcel
说起来王垠也真是日理万机,发封邮件他都不回😂 #statement

比冰封发了也不原谅或CovScript老李说了就直接踢更厉害呢……

我们就不应该相信大佬会为你一个人费时间,是吧?
真的好敬仰 RednaxelaFX 那样即既没有腔调、又能写出简单易懂文章的人,可惜他最近不在线了。
其实我最开始是以为王垠的许多观点和我一致,才借着回答文章里的问题的机会发邮件的。

其实王垠和我差太多了,我以为那些他表达的观点是我所认同的地方,都是他在谈大道理的地方。他自己当然没有做到这些观点的意愿,比如他说失败的经验很重要,但他从不提及初学者可能的失败;他教你区分知识的深度和广度,却从不告诉你还有什么有趣的书和链接;他夸某某教授与众不同、懂得大智若愚的道理,自己却“这个惹怒我了”、“那个费了很大力气、很有价值,不分享”

其实小白视王垠为大佬无非是他科普以及个性的确很好而已,或许也有清华辍学 title 的成分。

我把他视为大佬也无非是看到他弄过 PySonar/RubySonar 的类型推导语言工具、 Ydiff(树前序比较,这个我也写的出来...),以及那一百行 CPS(continuation-passing-style,假设所有call都不return)优化所谓无人写出的 Scheme 代码(这个倒没太大异议,毕竟 #Python 的红姐也最多实现了 PVM 的代码生成后端,没有 x86.)

其实见得多点的人都知道,知乎上 CS/PLT(程语理论) 大佬是很多的。王垠对 PLT 的理论科普太缺乏了(尽管他始终在做,但始终只有简单入门的部分),尽管他的博客也可以说是“业界清流”,也不是能让人完全满意的那种。

说到底就是肯做科普的人太少了,而且绝大部分 2~3 年资的大佬文章并不重视易懂性,显然是他们从不重视。 当然现在也还有星野大佬 blog.hoshino9.org 这种易读性可以的大佬存在,拭目以待吧。
补充一句: #Python #PLT #cs 红姐 其实是 github.com/thautwarm
https://pythonhunter.org/episodes/ep11

https://github.com/anqurvanillapy
另外 ANQUR 也是 Python 大佬
#JavaScript 的 贺老 就是贺师俊、 阮老师 就是 阮一峰

这些是昵称/尊称。
Forwarded from dnaugsuz
对了,现在的类型推导能不能收集值需求处的类型标记呢?

fun <T> &Box::<T>.force() = item as T
val box = Box::<Any>(1)
val i: Int = box.force()


如果要支持 val xs: List<Int> = mutableListOf() 这种代码好像也需要这种推导
Forwarded from dnaugsuz
我还有一个内存对象建模的问题(

如果去掉 &T 、将 struct 的 type 默认作为 reference ,然后给 Int 等值类型加优化、支持内联函数 ,接着就能区分 T* (就不必为和&的一致放前面了) 和 T? 了,这样有没有什么问题 🤔
如果某个 struct 在型参里但既不是 reference 也不是 pointer 会怎么样? 不太写 C++ 呢……
记得 reference 好像是特殊处理的 pointer 吧

假设 TypeModifier 的构造法可以自动把 *& 给铺平成 List ,保留 isConst ,这种设计怎么样(只是问问)
Forwarded from dnaugsuz
嗯…… 也是,记得你的 ASTNode 只有 fun Context.codegenForThis 一个方法,没有仅用于类型推导并填充的
如果用 Context.hasCodegen 又太脏了, 现在是只能在 Function.instantiate 里拿不到赋值处的 ASTNode 吧... (话说这函数的 typeArguments, argumentTypes 命名还有点绕 x)

(话说 TypeParameterTable.scope 为了避免无尽递归使得它的 receiver 也必须是 singleton object 啊... 的确是有点不优雅)
(之前在 ParserKt 里也遇到了递归 toString 的问题,我是这么解决的,不知道有没有帮助)
duangsuse::Echo
呃... 既然都说到这一步了就顺带讲一下我之前关于 动态作用域/词法作用域的见闻,虽然我知道没人感兴趣的。 动态作用域(dynamic scoping)就是你们能想到的,末端是全局作用域的嵌套表。 理解为栈,当前层的key被赋值、最顶层的表里的key被取值,所以栈帧销毁后解析会有不同的结果。 动态作用域没什么问题,也被用于诸如(嵌套命名空间)类型名解析的地方,除非函数可以作为值——比如 (set! a 1) (def get-kst() (lambda () a) ) (def main(a) (get…
func.instaniate(typeArgs, argTypes) 总感觉太 English 了... 如果用 instance 又不是动词,制造不一致性,或许 ofTypes, getInstance 之类的会好看些 🤔
不过仅因为英文单词不常见就重命名合理吗?

不过 Mivik 的 PersistenceGroupingMap 挺有意思的,这是用来解析 trait impl 函数们的,包含 fun collect(key:K): List<List<V>> 方法... 不过我觉得这不像
噢其实它的返回是 MutableList<Iterable<V>>, 然后 get(K): List<V> = collect(k).readOnly.let(::ChainIterable)... 不过也是实现了,我就觉得 ChainIterable 应该用在这种地方。

不过这不是重点, GroupingMapcollect(K) 方法,而 ChainMap 则可以有 shallowCopy() (flatCopy?)方法来保存命名环境,虽然这里是静态生成的闭包所以无需这么做……
This media is not supported in your browser
VIEW IN TELEGRAM
编程时,命名使用不常见的英文单词应该被替换吗?例: onEncountered -> onHappend
Anonymous Poll
33%
应该
67%
不该
duangsuse::Echo
呃... 既然都说到这一步了就顺带讲一下我之前关于 动态作用域/词法作用域的见闻,虽然我知道没人感兴趣的。 动态作用域(dynamic scoping)就是你们能想到的,末端是全局作用域的嵌套表。 理解为栈,当前层的key被赋值、最顶层的表里的key被取值,所以栈帧销毁后解析会有不同的结果。 动态作用域没什么问题,也被用于诸如(嵌套命名空间)类型名解析的地方,除非函数可以作为值——比如 (set! a 1) (def get-kst() (lambda () a) ) (def main(a) (get…
梗概一下 Mivik/kamet 自我停止更新后增加特性的建模要点 #Kotlin #CS #CE #PLT

== 参数化类型 类型形参
val name: String
check, toSting
Simple(name)
data Trait(name, trait) check = type.implemented(trait) || (type is Type.Dynamic && type.trait == trait)
data This(trait) : Trait("This", trait)

== 类型推导 已知表: TypeParameterTable (ThreadLocal)
<R> scope(block: TypeParameterTable.() -> R): R
set(typeParams: List<TypeParameter>, typeArgs: List<Type>)
map(typeParams): List<Type>
mapOrNull(typeParams) List<Type>?
equals(typeParam: TypeParameter, type: Type): Boolean = isEnabled && ...
这些命名我觉得应该叫 putActual( "<T, R>", "<Int, String>" ), fill("<T, R>"), fillOrNull, makeEqual(typeParam, type)

== Traits
sealed /*data*/ class Trait(val name: String)
implementedFunctions: Iterable<Function.Generic>
abstractFunctions: List<Function.Dynamic>
prototypes: List<Prototype>
然后有子类(抽象和未解析都属 Abstract)
abstract class Abstract(name: String) : Trait(name)
Named(name: String) : Abstract(name)
class Base internal constructor 大概就是默认实现,加个 rename(newName)
Generic(base: Trait, typeParams: List<TypeParameter>): Abstract(genericName(base.name, typeParams))
加个 resolveGeneric(typeArguments: List<Type>): Trait.
Actual(generic: Trait, typeArgs: List<Type>) : Abstract(actualGenericName(generic.name, typeArgs))

其 Impl: data class TraitImpl(trait: Trait, type: Type, functions: List<Function.Generic>) { val table: LValue }
会生成一个虚表 (constArray: Function.Static) ,这依赖 constant method ordering. 然后可以选择是 vtable 存 struct 里还是用 fat pointer (inst,vtable)

目前还不支持 (intersection) upper-bounds <T: Closeable>

== 类型拓展
既有 Nothing,Unit, bool/char, (U) byte/short/int/long/float/double, Array/Struct/Function
Pointer,Reference(虽然我觉得都是 TypeModifier, 而且它们的 isConst 是共用的)

Named,TypeParameter(的包装)

Generic(val base: Type, val typeParameters: List<com.mivik.kamet.TypeParameter>): Abstract()
Actual(val generic: Type, val typeArguments: List<Type>): Abstract()
This(val trait: Trait) : TypeParameter(com.mivik.kamet.TypeParameter.This(trait))
UnresolvedThis : Abstract()

嗯…… Abstract 子类而不直接在 sealed class 里面抛错误是个不错的设计,但或许应该叫 AbstractedAbstraction?

== Dynamic Type (trait objects)
Dynamic(val trait: Trait, val type: Type?) : Abstract()
DynamicReference(val trait: Trait, val type: Type?, isConst: Boolean): Reference(Dynamic(trait, type), isConst)
Impl(val trait: Trait) : Abstract()
duangsuse::Echo
梗概一下 Mivik/kamet 自我停止更新后增加特性的建模要点 #Kotlin #CS #CE #PLT == 参数化类型 类型形参 val name: String check, toSting Simple(name) data Trait(name, trait) check = type.implemented(trait) || (type is Type.Dynamic && type.trait == trait) data This(trait) : Trait("This", trait)…
Mivik 真的很厉害呢…… 不愧是 OI 生,知道那么多我不懂的东西 (汗)
之前写的 Android 文本编辑代码高亮视图也是太大佬了,我不敢想……

类型推导里的 makeEqual 也挺有趣的,这不就是 unification 里 unify 算法的基本做法吗:
sealed class Sym {
data class Var(val name: String): Sym()
data class Val(val value: Any?): Sym()
}
fun State.unify(a:Sym, b:Sym): Any? {
val va=get(a); val vb=get(b)
return when {
(a == b) -> a
(a is Sym.Var) b.also { assign(a, b) }
(b is Sym.Var) a.also { assign(b, a) }
else -> null
}
}

这里用 null 与否来判断是否成功,但总体和 makeEqual(typeParam, type) 是一样的
ps. Kotlin 的 scope function 真的绝赞

Mivik 其实并不是一个 Rust 狂魔,但他有能力把 Rust 与 Kotlin 结合在一起成为他自己的 Kamet ,这不是死知识或者单纯的抄袭,在前人的基础上他也做到了融合与扩展。
或许在 LLVM 的帮助下设计一个编译器并不困难,仅仅复刻一门语言写个蓝皮书也不困难,但从零开始设计并实现一门类似 C++ 的语言绝对不是个小工程;即便有 Kotlin 的帮助,也足以显现扎实的理论基础和工程水平。 把注意力全部放在功能拓展上,是和仅仅耍弄术语概念、刻意编写晦涩臃肿的代码、努力营造“专业软件”氛围的工程师完全不同的方向。 一点名词也不用却做到了它们代表的真实内涵,这才是「专业」所不能够理解的深刻。

即便作为普通的 OI 生,我相信他也是非常有能力的一个,以后在大学也绝对是能进入顶级计算机科学社的水平
This media is not supported in your browser
VIEW IN TELEGRAM
duangsuse::Echo
编程时,命名使用不常见的英文单词应该被替换吗?例: onEncountered -> onHappend
duangsuse 除了泛向的 CLI/复用库设计 外可能没有什么专业,除了 codegen / bin+text serialize 俩好像也没啥了,不能后端也不能前端 GUI 也不太会... 太泛泛了

Kamet 里又出现了一次 Prototype 这个词, Lua 里这个词不止是 FunctionDecl 还是包含其实现 code 的,真不知道该不该有 prototype, 它的语义太混乱了

编程语言和自然语言是有区别的,我们是真的对严谨性有要求,而且不广为认知地,比数学更严谨。
所以我个人观点绝对是讨厌利用不常见的英文单词的,比如 lift, comprehension 等(往往这些词还有一大堆变形会被人混用)。
绝对不要以为你是在用英文编程就可以自由用英文的 trick 了,编程的世界只有结构关系逻辑,没有自然语言的理解,所以命名应该直白地反应其构件与其他构件间的关系,直白的东西自然是无歧义的。指望代码读者了解你心理的小九九很不明智。

说起来 Map<K, V>Map<K 的区别也挺奇怪的…… 词法处理的时候会遇到歧义问题,不知道不用词法处理会如何...