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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
F**king delegates 为什么没有用,然后不能直接 by... Kotlin 一大堆 Property 抽象也看不懂...
duangsuse::Echo
F**king delegates 为什么没有用,然后不能直接 by... Kotlin 一大堆 Property 抽象也看不懂...
This media is not supported in your browser
VIEW IN TELEGRAM
啊我的 Delegate 写错了啊!只是 Serializable by 的话当然没有自动代理实现 Date... 对象代理用的也不对,应该引用 property 的

我应该写个 TimeStamp 接口然后一起的...
累死了... 真的好无聊,我居然一直在做码农的工作呢。
https://github.com/duangsuse/TelegramMessageScanner-KotlinMulti-Failed/blob/master/src/commonMain/kotlin/org/duangsuse/messagescanner/model/Date.kt

白写了这么久,可惜 Kotlin Common 居然有这些东西本来应该自带的,Kotlin 的 Doc 上也有说有 Common 版本的,IDEA 的 project template 居然都没法直接用,真是令人心累啊...(跑
duangsuse::Echo
可以使用。不过我觉得 Regex 可以修改以减少后序处理的过程。 import java.util.regex.*; pat = Pattern.compile("(^|\\s)#(?!#)((\\S(?<![\\(\\)]))+)") m = pat.matcher("#abc #dev") m.reset() while (m.find()) { println(m.group().trim()) }
🤔 一旦开始写的东西,都是一些对真正的业务逻辑来说可有可无的东西时,就比较危险了...

下面 duangsuse,唉,希望早日能有快速完成任何实际工程的能力吧。


Maven 的 POM 怎么写又忘了,我思量着要不要先拿大家都觉得很垃圾的 Java 8 来完成这个扫描器

<dependenciesManagement>
<dependencies>
<dependency>
<groupId>org.duangsuse</groupId>
<artifactId>telegram_message_scanner</artifactId>
<version>1.0.0</version>
<scope>main</scope>
<dependency>
</dependencies>
</dependenciesManagement>

Gradle 的也很难记,Gradle 的 Configuration、Task、Artifact、Plugin、Dependencies、Repositories 也不好记... gradle 用一些 fileTree, doLast, extendFrom, copy, delete, each 什么的... 累。
This media is not supported in your browser
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
duangsuse::Echo
😲 Sticker
duangsuse 不好的地方主要在于记忆不好,比如上次我记得我记了 Maven 的一些模型侧面,可是现在全忘了:

记得一个 Maven 包有(默写的,记住的):

ArtifictId, GroupId, VersionName
Name, PackagingType, Description, Url

Developer name, developer id

SCM, SCM Connection, SCM developer connection

Licence, licence name, licence url

可是,实际上还有
+ SCM(url)
+ Licence(dist)

太微不足道了,如果要开发 Qt 程序呢?有些 signal 和 slot 怎么记... 界面的东西


如果 duangsuse 能写出类似这样的代码,可能会稍微安心一点,可是好像没有写出过(或许吧)。

其实 duangsuse 真的会写位运算... 就差 OI 级别的位运算了。
啊还是 Qt/C++ 优雅,试试。
可是 Qt 的视图模型比较不方便,太看重 Fixed size 了,容器类没有 Gravity,视图不能 size match parent,很难受,Qt 也有列表控件模型(Model-View based、Item model based)
duangsuse::Echo
可是 Qt 的视图模型比较不方便,太看重 Fixed size 了,容器类没有 Gravity,视图不能 size match parent,很难受,Qt 也有列表控件模型(Model-View based、Item model based)
🤔 已经手工写了一个小例子出来,希望能愉快的使用 C++ 和 Qt Widgets、QObject(Signal&Slots)
之前的 randomSelection,用了 Qt4 Widgets、Qt event、QTextStream、Timer、QLabel、qrand、qgetenv 等。

duangsuse 已经会使用 Qt 进行文件 IO 和简单的 configuration 读取等操作,Qt 算法库(比如 QVector,QString)基本能用,对 Qt 基本视图模型(Point、Widget、Layout、Widget Proprerties、Plattle、Color、Geometry)和基本工具(QTimer)也有了解。
This media is not supported in your browser
VIEW IN TELEGRAM
可是写了很多垃圾代码,却只能在自己还会的地方练习,因为自己不会的地方几乎要熬夜去学(跑

准备继续写那个拖了很久的 TelegramMessageParser...
Maven 🤔 我觉得我需要 subproject
#Java #Kotlin #JVM #CS #PL #dev 🤔

duangsuse 发现自己对 Java 在集合类里泛型问题的又有了新一层的理解。

为什么容器类需要用泛型?

因为肯定是希望 List<Animal> 能够去 addAll(List<Cat>) 的呢。
Java 里默认的泛型形变,是 Invarant(不变) 的
这种情况下,虽然我们知道 Cat 是 Animal,但是 List<Cat> 却和 List<Animal> 不存在子类型 subtyping 关系!
如果我们要编写一个 addAll(??? other) 函数,保证类型安全(List<Cat> 显然不应该保存 List<Animal>!),并且让 Java 的类型检查器可以做检查的话,就必须指定泛型型变!

在这里,根据 Java 的 PECS(Producer-Extends-Consumer-Super)原则,我们知道 addAll 的类型,显然应该是 void addAll(List<? extends T> input);
但是为什么呢? 🤔

这里你只会了解到和程序设计语言类型有关的信息,Kotlin 的类型投影什么的不会讲。


泛型的『型变』是什么?
泛型的型变就是告诉 Java 类型检查器,一种泛型类的子类型关系,和它的参数化类型有什么样的联系。
这样,我们就可以实现类型安全的容器类泛化类型操作。

+ 协变(covariant):Cat 是 Animal,List<Cat> 也是 List<Animal>
+ 逆变(contravariant):Cat 是 Animal,List<Animal> (这时可能被用作输出) 是 List<Cat>
+ 不变:无论 Cat 是不是 Animal,List<Cat> 和 List<Animal> 之间没有太大的关系

在这里,子类型的『级别』,父类型为小子类型为大,以 lessThan 序排行,可能类似这样:

1. Object(kotlin.Any)
2. Animal
3. Cat

Kotlin 里面,泛型的 in T 指定了可取类型的下界 — 可选类型 ? 必须是 super TT 的超类)才可以,而 Animal 的确 superCat,所以可取类型必须 (lessThan Cat)
它实现了泛型的逆变 —

有类型 P 是类型 C 的父类型,P lessThan C
类型 F<? super C>F<P> 的父类型 (_<P> lessThan _<? lessThan C>)

Kotlin 里面,泛型的 out T 指定了可取类型集合的上界 — 可取类型 ? 必须是 extends TT 的子类型)才可以,而 Cat 的确 extends fromAnimal,所以可取类型必须 (greaterThan Animal)
它实现了泛型的协变 —

有类型 P 是类型 C 的父类型,P lessThan C
类型 F<? extends C>F<P> 的子类型 (_<P> greaterThan _<? greaterThan C>)

其实我们想说,为了类型安全,List<Animal> 的容器里,可以放的东西类型应该是:

? extends Animal
也可以说是 ? greaterThan Animal,反正比 Animal 能就可以了(跑)

我们希望所有对象都的确实现了 Animal(可以装 Animal 和它的子类扩充)
所以,我们需要一个 producer — List<? extends Animal> 来喂数据,进行 addAll 操作(利用一个 Iterable<T>,这里 T 就肯定是某种 Animal, 或者说我们利用 T get(); 方法肯定会拿到 Animal

反过来说,popAll 呢?

PECS,我们知道现在该用 in T🤔

fun popAll(output: Collection<in T>): Unit

或者说,

void popAll(Collection<? super T> output);

我们不希望任何容器,包括 output 被放上不好的东西(某种不是 Animal 的东西!)
所以,当『输出到集合(使用 void add(T item); 方法)』的时候,不如反转一下子类型关系!(相对于 addAll
这样,output(装着某种 T) 就只会被 add 上一些 extends T 的东西(这个类型自己),保证了类型安全

这就使用了泛型的逆变
非常的难受,但这居然还比 Gradle、CMake 要简单一点?(可能不是
duangsuse::Echo
非常的难受,但这居然还比 Gradle、CMake 要简单一点?(可能不是
看了一下 IDEA 的 #Java 语言版本提示,我默写一下:

1.3: Plain Old Java (2000)
1.4: assert keyword (2002)
5: Autoboxing, enum, generics (2004)
6: @Override in interfaces (2006)
7: ARM, Diamond, multi-catch (2011)
8: Lambda and Type annotations (2013)
9: Modules, private fields in interfaces (2017)
10: Local variable inference (2018)
11: Local variable syntax for lambda parameters (2018)

没有成功,但是也快了,只是 Java 7 的默写错了,别的有漏的。
啊,提起 Java,这门『垃圾』语言(和 CSharp、Kotlin、Rust 等相比就是垃圾了,差一点没 Julia、R、Fortran 之类的厉害?'跑,,,,),也未必是被大部分人完全理解的呢。

那么我们今天来完全理解一下,自 1995 年从 Oak 更名,1997 年的 Java 1.1 开始,之间提到 2004 年语法糖飞跃的 Java 5,再到最近 2018 年的 Java 11 结束,我们会看到所有的 Java 语法。(其实语法上的已经足够浅层次了,但是即使这样,很多人都能注意到自己没见过的 Java 语法)

当然,定义什么的冗长(好歹 James 老头子也是博士学位啊!)所以得感谢 ANTLR

🤔 #Learn #PL #OOP