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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
同样是程序员,为什么有的人会把 Java 写成汇编,有的人会把 Kotlin 写成 Haskell? 🤔

有一定编程素质的人写代码是横着写,写十年实质上没有进步的人写一旦时序区间复杂一点代码,一个个子程序像顽石一样竖在那不动,别人想弄明白你干了什么都麻烦的要死
好像别人欠你时间了一样

我以前以为 Oracle JDK 里的东西带黑科技性能加成,看来如今必须要改变一下看法了……

把本来 71 行可以实现的逻辑写成 471 行、为每个子程序哪怕是最细节最实现无关的东西加上堪比千字文的注释、即便代码复用唾手可得我也要 copy/paste,不错,牛逼、大佬。
我终于纠正了之前一个自己都觉得错误的想法…… (如果先 op(count) 而不是 --count,序列就是 9,8,7,...,1) 本来我在块里面 op(); --count; 一般来讲 count=3, while>0 先肯定是第一次循环 op(); count=2, op() count=1 op(),肯定是三次的,区别在于先 --count 第一次 op 会拿到 3-1 = 2 而已…… 我所谓『时序』,其实自己也一点不懂而已,如果要做逻辑器件编程无时序思维是困难的
duangsuse::Echo
我终于纠正了之前一个自己都觉得错误的想法…… (如果先 op(count) 而不是 --count,序列就是 9,8,7,...,1) 本来我在块里面 op(); --count; 一般来讲 count=3, while>0 先肯定是第一次循环 op(); count=2, op() count=1 op(),肯定是三次的,区别在于先 --count 第一次 op 会拿到 3-1 = 2 而已…… 我所谓『时序』,其实自己也一点不懂而已,如果要做逻辑器件编程无时序思维是困难的
不过说起来,这个项目测试有点不好做,我希望以后有机会了,用实际用例来测试

目前还在准备写组合结构的部分,显然组合是可以有 Size 的,没有 Size 的话,可能不允许 reset

但是 File 的话可以随便 Reset,怎么办?怎么兼容这个? 我也不清楚……
#Kotlin 理论没想好,又一个秀破天际,但是没有实际用处的东西,我之前想的 NumEqualize 动态自动 widen 都比这个强的多的多。
它不能解决问题,我没有注意到要『检验一种 InputStream 的 read(byte[]) 是否利用了 read()』是不可能的…… 几乎
实际上,你多建立一个 Filter 就可以检验了,但是有什么意义呢?我觉得这应该直接改掉

Java 程序员写这种本来也不低效的模式怎么都写得这么冗长…… 如果没有优化,这额外开销是我自己无法接受的
卧槽,刚才看到一个 s.read() ; s.read(byte[]) 都是分离开算的才觉得奇怪,明明计算上不存在层次为什么会产生二倍的结果?这才发现是自己逻辑写错了…… 😂
This media is not supported in your browser
VIEW IN TELEGRAM
修了一个至关重要的 bug,可以意味着现在的 Reader 已经可以用了
虽然明天我又要去上学了

当然其实是不保证可以用无问题的,但看起来很稳定一样,因为我一行一行一次一次 UpArrow Kotlin REPL 测试出来的…… 的确是可以用,很正常,尤其是 Reader.File
除了 KotlinIO 的 InputStream.readBytes() 不正常而已,不过这个定义我觉得就有点奇怪,也就见怪不怪了,和 Java 一比是大雾见小雾

URLBuffer 的都是 Reader.Instance 辅助实现的,当然他们都是那个德行,上不来下不去。
不过 Reader.InstanceReader 的基本继承结构我重构了一下,还没测试过是否工作正常,我想应该是没问题的

关键是 Writer... 现在还可怜的要不得
关键是我…… 明明这么努力,还是熬夜,而且莫名觉得熬得还很有意义,因为完成了想做的事情…… 可是一天到晚在这里视力下降就不好了……
关键是剩下的事情…… 虽然是写了一些,但我自己感觉提升不大,有时候看着屏幕会觉得知道该怎么写,闭上眼睛思考一下全不知道是什么东西了,迷人……

关键是,今天晚上肯定不能完成了吧

他们又去找一个在什么大学来着当教授的博士后亲戚,和他一个 IT 的朋友来电话教导我

可我是要写代码而已,又不是上中科大、交大、西安大学、当高学历高素质人才……
不管多没办法总是要去的啊…… 何况这种强度一直下去肯定不是办法,而只有长假到来而且我成天心情好才可以保证不出现过劳死的问题,唉 #life #China #school
说起来,现在写的代码越来越不像以前了。

给人感觉这么大一个类,我怎么就只写了 160 行? 之前感觉这么有用的类,怎么只有 174 行?以前我写个小应用都能写到这个行数的一半,然而这个结构却复杂的多。

不过我的确很讨厌对特殊的情况依然坚持用『同意』『规范』的缩进方式,为了让程序代码更好看,怎么样的缩进我都能用。

编译后 JAR 现在是 85K
其实我本来以为还可以顺便写个人生第一 Scheme(不是,其实是类似 Scheme 的自己设计的语言,支持基本的 sexp 和中缀表达式、raw string call、pass expression、vararg、default arg、mutable lambda capture)

当然是解释器啊,相信不会有人认为我连 visitor pattern 都不会写吧,不会写还有子类型多态的直接化方式啊

如果能够写出来的话,就可以很开心了,因为我就可以用它来写一些 Android 应用了,也打算试试它和 Dokuss 组合对 Android 程序设计会有什么效果,我的希望是在 doku 提供绑定后,二进制文件的读写对象在 MyScheme 里组合,就可以方便地拿来使用了

比如这里有个简单的例子

[require! io]
[require! doku]
[require! terms]

[term! st-frogs (drepeat frog)]
[term! frog
(dseq dutf dint)]

[end]

[define! frogs '(("江泽民" 1989) ("胡锦涛" 1989 * 91) ("一刀" 999))]
[with (file-open "naive-frogs" 'write) \f ->
(write st-frogs f frogs).]

(print
[with (file-open "naive-frogs" 'read)
\f. (read st-frogs f)])


只是它像 Python 的 pack/unpack,名字就不好起,结构体只能是匿名的,十分不方便(虽然 MyScheme 可以提供 tuple destruct 的方式),我想只能在 Kotlin 端先定义 ID 了
#Project #Kotlin 『看蓝猫、学篮猫,我有知识我自豪!』下面我来给大家进行现场的表演…… 组合子结构序列化函数的方式是 Struct 做 receiver, I/O stream, data 做参数返回值。
比如说这里咱们有四个字符,『恭喜发财』~

import org.duangsuse.dokuss.struct.*

class 恭喜发财: ArrayLike(4) {
val a: Char by index(0)
val b: Char by index(1)
val c: Char by index(2)
val d: Char by index(3)
}

咱来读取一下这个结构试试。

val 恭喜发财Doku = Seq(::恭喜发财, char16, char16, char16, char16)

import org.duangsuse.dokuss.*
import java.io.*
val s = Reader.Instance(System.`in`).restream(::BufferedReader)
恭喜发财Doku.read(s)
恭喜发财
Array+(臦||鲖|迥)

s.nativeEndian()
val res=恭喜发财Doku.read(s)
val w = Writer(System.`out`)
恭喜发财Doku.write(w, res)
This media is not supported in your browser
VIEW IN TELEGRAM
晚安。
卧槽,Gradle #java 怎么堕落了?为什么 logo 要改成这酸样?本来酷酷的小象去哪里了?
#Kotlin 又瞎说……我打算来写篇小说来着……
Forwarded from dnaugsuz
写习惯了就好,你还没有上知乎问为什么他们要写后缀……

我觉得这也就是习惯问题,好像之前 ML 什么的都是这么写来着……
一般来说好像喜欢项目定义语法结构前缀关键字的人会夸赞它定义更明确(因为开头是固定的关键字比如 var val fun constructor)、允许考虑标识符的名字多于类型(这样可能有助于你起好名字)、在隐式类型的时候(比如 type inference, gradual typing)方便不少(因为此时类型不必显式写出,C# 和 Java 10 那个 var 又显得不够好看)
喜欢 R fn(T x) {...} 这种的喜欢说它简洁、突出最终值的类型这个重点

使用的类型签名看起来像是这样,以下程序构筑使用了变量右值(value)、左值(一般是 variable)和子程序,多态是简单的函数重载 (overloading)
调戏结果 撸猫(猫 小猫) {...}
调戏结果 撸猫(波斯猫 小猫) {...}
这是 C、C++、Java

程序 撸猫(猫:猫):调戏结果 {...}
程序 撸猫(猫:波斯猫):调戏结果 {...}
这是 Kotlin、Rust、Swift、Python 什么的

typealias Sound = String
abstract class Noisable(private val noise: Sound) {
fun makeNoise(): Unit = println(noise)
}
data class 猫(val name: String, val isMale: Bool): Noisable("Meow")

这个时候,Kotlin 使用 <:> 显然会比沿用 extends 要好。

其实也未必不可以用 extends 什么的,不过 Kotlin 的 <:> 语法实质上不能完全和 Java 的 extends 划等号,因为

+ 这个语法还被用来 val dict: MutableMap<Char, Char> = mutableMapOf() — 这个例子的代码风格好像是不被 Kotlin 推荐的
+ Generic(也就是 OOP 的 Parametric polymorphism,参数化多态,也是 Kotlin 完胜 Java 的地方之一,因为它有比 Java8-11 都强多了的泛型推导) 的 upper-bound(类型参数的继承序(order) 上界)
也是使用 ParamizedType<WTF: Type> 这种语法指定的,虽然 Kotlin 不一定把这个东西叫成 upper-bound aka. ubound,不过 Java 里都叫 Type wildcard capture<? super T>
类型『上』界可以认为是命题 (? > T)… 此处 ? 这个未知类型要『大于』T,也就是说是 T 的 subtype 才能被视为可接受的类型参数,Scala 里这种约束叫 [+T]。
比如 Kolin 里一个 mutableListOf(1) as ArrayList<*> (K2JVM 里是一个 typealias 定义的)的继承关系看起来是这样(虽然看起来 T? 不像是个『简单』类型……):
Any? Any
List<*>? List<*>
MutableList<*>? MutableList<*>
ArrayList<*>? ArrayList<*>

这里每一个第 n+1 的项目,都比上一项『大』,而且这个关系具有传递性(transitive)即 (Number: Any) => (1 is Number) => (1 is Any), 不过不像 T: Comparable<T> 的 cmp 它不具有反对称性(asymmetric)…… 呃不反对称与否我不清楚
Any? 是 Kotlin 的顶类型,所有类型都大于它(是它的子类型),Kotlin 里的 <in T>TAny? 的时候,所有接受 T 的函数相当于要求对应位置为 capture<? super Object> 类型,当然这不是很科学的设计,但也能用(我不是指型变性(variance),它是很科学的,尤其在 Scala 和 Kotlin 里非常好用,毕竟你还是希望有一些只能接受『更小』类型的『值需求』位置)
Nothing 是 Kotlin 的底类型(bottom type),所有类型都小于它(这个类型是不能被 typealias 的,由此你可以注意到 Kotlin 设计是的确很细腻)
<out T>TNothing 的时候,也相当于所有返回 T 的子过程或者说行为、方法(behavior, method) 要求 capture<? extends Void>
当然这不科学,因为没有类型比 Nothing 更大,不过 Nothing 也是任何类型的子类型,而且上面的 Void 应该说是 Nothing? 这个类型,看作实例值的集合它只有一种可能:null, Java 的那个版本是 final 并且 private Void(){} 隐藏架构器的版本,所以它是没有实例的类型。
Kotlin 里的 <*> 是基于 PECS(producer-extends, consumer-super; 或者说生产者-协变, 接受者-逆变) 原则生产消费者模型类型安全的,所以 Map<*, *> 的意思是 Map<? super Nothing, ? extends (Any?)>

也算是支持 subtyping 的类型系统里强化其 completeness (也就是降低假阳性 False positive 的概率,对应的是假阴性 False negative 的 soundness,即允许不一致的类型通过)的一种方案,毕竟你甚至可以 println(System.exit(1)), 从类型安全的角度看这是没有任何毛病的(虽然 Java 里没有返回值就是没有返回值,你不能用 void 去 call println; 或者更准确的说法是 System.exit: (I)V 没有返回值)

不过 Kotlin 首先是多个函数类型 (in T) -> out R, 而且这个还和 fun... 比较对称
如果要和 Java 对称的话,函数的类型只能写的和 C 一样丑:
调戏结果(*)(波斯猫 猫);
我觉得这实在不能和『好看』扯上半点关系…… wtf
Forwarded from dnaugsuz
其实构造函数本身,如果你结合 Kotlin 1.3 和 Java8 来比较、加上倾向杂交一点而不是 Kotlin 式 OOP+FP 多范式的 Rust 什么的,就会发现它也就是个不良的封装而已

为什么一定要 call super 在加不一致的语法糖(Kotlin 里只要父类,当然不是接口实现全部加上无参 superclass constructor 的括号)什么的呢?Kotlin 里把类的 constructor 进一步独立出来,要求所有特化类的 parent 数据依赖都在语法结构层次上直接提供,又重构了一大堆包括 staticcompanion object 的操作,Kotlin 比 Java 更像 OOP 一些了,毕竟重要的东西应该写明显一点嘛

不过对我来说,好像觉得本来就是应该像 Kotlin 这样做的一样,Java 的抽象程度还是不够,何必要函数呢?难道更多时候不是一个表达式就够了么?

Rust 的就是没有专门的构造函数,用的是类似 Json 语法的 struct initializer,不过也是不难看的
毕竟 Rust 不是面向对象的编程语言,即便偶尔可以用一点点多态(trait 什么的)也不能说是特别能使用 subtyping 的主
duangsuse::Echo
#Kotlin 又瞎说……我打算来写篇小说来着……
你会发现我最近写的文字越来越不好看了,没办法,我第一次写,算是不知道的别看、知道的复习一下