Forwarded from Deleted Account
二进制 IO,要不要试试 org.duangsuse.bin? 🌚
GitHub
duangsuse-valid-projects/SomeAXML
🥬 Android binary XML file reader/writer. Contribute to duangsuse-valid-projects/SomeAXML development by creating an account on GitHub.
Forwarded from Deleted Account
-
-
-
-
好吧如果那个是做在协议上支持的就不能了
-
- 最后
- Packet.writeVarInt 是专门的位运算算法,实现应该和框架层隔离开
- 不要用 Packet.Builder,用 PacketWriter,Builder 不是用来写结构化数据的。
@Deprecated("Should not use ...for internal") 全都应该用 internal 修饰符替了-
this.apply 不要用了,apply 本来就是指定 this 的。Builder 里使用要严格按照一致的缩进和形式使用-
fun ping(payload: Long) 换成异步 non-blocking 的更好-
fun pingLatency() = ping(System.currentTimeMillis()).let { System.currentTimeMillis() - it }
可以 import kotlin.time.* 再 fun pingLatency() = measureTime { runPing() },不必把 begin_time 做成参数好吧如果那个是做在协议上支持的就不能了
-
if (serverPort !in 1..65535) throw IllegalArgumentException 可以写成 require(serverPort in 1..65535) {"Illegal port $serverPort, require value in 1..65535"} - 最后
companion object 的那段实在是太“空”了,不易读,最好得改- Packet.writeVarInt 是专门的位运算算法,实现应该和框架层隔离开
do {
val lowbits = i and 0x7F
i = i ushr 7
val signbit = i != 0
val byte = if (signbit) lowbits and 0x80 else lowbits
writeByte(byte)
} while (i != 0)
- Packet.Builder.append(Int|Long) 是有二进制位操作的数值上的算法,应该和 Packet.writeVarInt 泛化合并- 不要用 Packet.Builder,用 PacketWriter,Builder 不是用来写结构化数据的。
fun <T> Iterable<T>.fliterIndex(predicate: Predicate<T>) = withIndex().filter ( predicate(value) }.map(IndexedValue<*>::index)
fun <T> Iterable<T>.shuffleFilter(predicate: Predicate<T>): Pair<List<T>, List<Int>> {
val shuffled = shuffle()
val indices = shuffled.filterIndex(predicate)
return shuffled to indices
} fun <T> List<T>.shuffleKeepIndex(index: Int): Pair<Int, List<T>> {
val unallocated = indices.toMutableSet()
val newList = copy()
val keptIndex = Random.nextInt(unallocated.indices)
newList[keptIndex] = this[index]; unallocated.remove(keptIndex)
unallocated.forEach { newList[it] = this[index] }
return keptIndex to newList
} 不对
fun List<T>.shuffleKeepIndex(index: Int): Pair<Int, List<T>> {
val newList = copy().also { removeAt(index) }
val keptIndex = Random.nextInt(indices)
newList.insertAt(keptIndex, this[index])
return keptIndex to newList
} 也不对
依据原有 Collection 还是依据 indices 建模都不好啊…… 1 vs. N input index/predicate 的情况都不好弄啊……
fun <T> MutableList<T>.shuffleKeepIndex(index: Int): Pair<Int, List<T>> {
val keptIndex = Random.nextInt(indices)
val newList = indices.map { if (it == keptIndex) this[index] else this.removeAt(0) }
return keptIndex to newList
} 下面这个是针对 source collection 建模的,没必要用 mutable iterator
fun <T> Iterator<T>.shuffleMerge(value: T): Pair<Int, List<T>> {
val mergedIndex = Random.nextInt(0 until size)
val newList = (0 until size).shuffled().map { if (it == mergedIndex) value else next() }
return mergedIndex to newList
} #Kotlin
总之:
import kotlin.random.*
fun <T> Collection<T>.shuffleMerge(value: T): Pair<Int, List<T>> {
val iterator = iterator()
val mergedIndex = Random.nextInt(indices)
val newList = indices.map { if (it == mergedIndex) value else iterator.next() }
return mergedIndex to newList
} 很明显需要两个数据,要么先 shuffle 再 search 要么然早就知道 index 是何,然后改另一个
fun <T> Collection<T>.shuffleMerge(value: T): Pair<Int, List<T>> {
val newRange = 0..lastIndex+1
val mergedIndex = Random.nextInt(range)
val iterator = iterator()
val newList = newRange.shuffled().map { if (it == mergedIndex) value else iterator.next() }
return mergedIndex to newList
}Forwarded from Deleted Account
其实我也算是一个重视性能的人,不然我不至于为了测试个算法性能专门写一个 profile “框架”。
但把性能和功能比起来我也能舍鱼而取熊掌。
JavaClass.kt 实现了对 Java class file 常量池的读写,只用了 120 行。
另一边我举个例子,zvm 的 ClassFile.java,单单开始实际读取 constant pool 的算法都是在 120 行后了(定义顺序都没按照ClassFile的顺序来),然后直到 225 行一共写了 100 多行。
可以看一下,意思大概是一样的。
不过我写的一个类相当于别人的一个 if branch,我写一行等于死板方法写10行、我改一行等于“常见”方法改10行。
现在要我去维护那种代码,我算是无法维护了……
我用的二进制位运算数值读取,从理论上讲好像这种算法还比 java.io.DataInputStream 里的那种 ...|(i3<<24)|(i4<<16) 要快不少,因为它的临时分配更少而且计算量也貌似更集中。
但我在意的不是那个,是我可以写出来有条有理有示例,至少它会比 JDK 里那段魔法要好看。
现在我在写 ParserKt,并且拿它实现了一个普通的四则计算器,不到 60 行。
所以如果你还是觉得性能很重要,建议把自己写过的代码多手动重写几遍,比如我上面提到的 ParserKt 我就用三种以上的语言,重写了 11 遍有余,才有了现在的 ParserKt。
写多了慢慢你就会厌烦那种事必躬亲、为机器代劳的编程了。
那么重视性能多半是喜欢精雕细琢,喜欢精雕细琢的人关于编程往往比较极端,不是真·大佬就是不太经常编程的人。
但把性能和功能比起来我也能舍鱼而取熊掌。
JavaClass.kt 实现了对 Java class file 常量池的读写,只用了 120 行。
另一边我举个例子,zvm 的 ClassFile.java,单单开始实际读取 constant pool 的算法都是在 120 行后了(定义顺序都没按照ClassFile的顺序来),然后直到 225 行一共写了 100 多行。
可以看一下,意思大概是一样的。
不过我写的一个类相当于别人的一个 if branch,我写一行等于死板方法写10行、我改一行等于“常见”方法改10行。
现在要我去维护那种代码,我算是无法维护了……
我用的二进制位运算数值读取,从理论上讲好像这种算法还比 java.io.DataInputStream 里的那种 ...|(i3<<24)|(i4<<16) 要快不少,因为它的临时分配更少而且计算量也貌似更集中。
但我在意的不是那个,是我可以写出来有条有理有示例,至少它会比 JDK 里那段魔法要好看。
现在我在写 ParserKt,并且拿它实现了一个普通的四则计算器,不到 60 行。
所以如果你还是觉得性能很重要,建议把自己写过的代码多手动重写几遍,比如我上面提到的 ParserKt 我就用三种以上的语言,重写了 11 遍有余,才有了现在的 ParserKt。
写多了慢慢你就会厌烦那种事必躬亲、为机器代劳的编程了。
那么重视性能多半是喜欢精雕细琢,喜欢精雕细琢的人关于编程往往比较极端,不是真·大佬就是不太经常编程的人。
Telegram
duangsuse::Echo
不过说起来最近我真是随便写点代码都快能当框架用了…… 这是有毒么
Forwarded from Deleted Account
建议有条件的人去看看那个 https://codon.com/hello-declarative-world
Forwarded from Deleted Account
duangsuse 是计算机科学爱好者,偏向程序表达与转化(包含编译原理什么的)
喜欢Kotlin和OOP,最近随便写点想写的东西,主要是复用库。
喜欢Kotlin和OOP,最近随便写点想写的东西,主要是复用库。
我打算先弄完我这 Hosts,然后再随便检查一下写个 JSON 解析器
然后我想写汉字数值的解析器和输出……
然后想写 LayoutPattern
然后我想写汉字数值的解析器和输出……
然后想写 LayoutPattern
/tmp/duangsuse.sock
我打算先弄完我这 Hosts,然后再随便检查一下写个 JSON 解析器 然后我想写汉字数值的解析器和输出…… 然后想写 LayoutPattern
汉字数值输出主要是 ascending find (max cmpLE)
和 div / mod
和 div / mod
还好,我用修复了的 never(); always(); isStickyEnd() 和提出的 clamWhile 能够解决一些问题
Check(never()) { if (!isStickyEnd()) clamWhile(!nlChar, Line.Unknown, "unknown line") else it }
/tmp/duangsuse.sock
汉字数值最特殊的地方在于有 十一 和 七百亿 这种,哈哈
我不打算写汉字数值的,但打算写普通
汉字的有一个特点,它的前置单位要递归,才支持 七百亿 这种
普通的没什么困难,就是累加和 max cmpLT、div/mod 好了
1min2s 这种的汉字的有一个特点,它的前置单位要递归,才支持 七百亿 这种
普通的没什么困难,就是累加和 max cmpLT、div/mod 好了
以 ANTLR 的威力,其实 EOF 问题也只是不存在罢了
但 ParserKt 可以解析数值的序列、Token 的序列,ANTLR 不能
而且那样 EOF 字符便不能合法存在了
我知道仅仅不允许 EOF 字符的说法很可笑,但 ParserKt 是泛型框架
但 ParserKt 可以解析数值的序列、Token 的序列,ANTLR 不能
而且那样 EOF 字符便不能合法存在了
我知道仅仅不允许 EOF 字符的说法很可笑,但 ParserKt 是泛型框架
/tmp/duangsuse.sock
我不打算写汉字数值的,但打算写普通 1min2s 这种的 汉字的有一个特点,它的前置单位要递归,才支持 七百亿 这种 普通的没什么困难,就是累加和 max cmpLT、div/mod 好了
写不了,整 StickyEOF 和 EOF Char 的问题已经心力交瘁,晚安
/tmp/duangsuse.sock
写不了,整 StickyEOF 和 EOF Char 的问题已经心力交瘁,晚安
StickyEnd(nlChar or item(EOF), notParsed) { clamWhile(!nlChar, Line.Unknown, "unknown line") } 总算是解决了,ParserKt 走向实践之重大隐患
Deleted Account
sealed class Sexp { data class Term(val name: String): Sexp(); data class Nest(val list: List<Sexp>): Sexp() } lateinit var sexp: Pattern<Char, Sexp> val str = Until(elementIn(' ', *parens.items()), asString(), anyChar) val atom = Convert(str) { Sexp.Term(it)…
sealed class Sexp { data class Term(val name: String): Sexp(); data class Nest(val list: List<Sexp>): Sexp() }
lateinit var sexp: Pattern<Char, Sexp>
val str = Until(elementIn(' ', '(', ')'), asString(), anyChar)
val atom = Convert(str) { Sexp.Term(it) }
val nestItems = SurroundBy(parens.map(String::first).toPat(), JoinBy(item(' '), Deferred{sexp}).mergeConstantJoin())
val nest = Convert(nestItems) { Sexp.Nest(it) }
sexp = Decide(nest, atom).mergeFirst { if (it is Sexp.Term) 0 else 1 }Forwarded from Deleted Account
我也重复了一下
个人建议:下次
-
- 切忌把 Kotlin IO 写回 Haskell 式 IO,一旦发现代码太“空”,要及时调整,
-
个人建议:下次
-
iter.joinToString("") { "$it" } 这类可读性不高的还是用 iter.joinToString("", Char::toString) 代替好了,尤其是 dollar string 不能滥用。- 切忌把 Kotlin IO 写回 Haskell 式 IO,一旦发现代码太“空”,要及时调整,
let 什么的是用来提升可读性的,不要用它降低代码密集度。-
n, p 这样的名字可以说是 meaningless…… n 叫 accumulator 吧。尤其是那个 p,怎么能叫 p 呢……Gist
CustomBaseNumberKt
CustomBaseNumberKt. GitHub Gist: instantly share code, notes, and snippets.