duangsuse::Echo
慢慢来吧,先写 RangeMap 算…… 🤔
辣鸡 Java 的
我 TM 都看不清哪些是我该 override 的了
default in interfaces (mixin) 真是辣鸡,辣眼睛。我 TM 都看不清哪些是我该 override 的了
辣鸡 Java 的 stdlib 实在是太愚蠢了,尽写一些无关紧要的接口定义,本来可以划分的它偏放在一起
duangsuse::Echo
而且,居然是 unchecked!真不知道是不是没提供新的,基于 Parametrized types 的版本
因为 Java 没有真实泛型,都是基于泛型擦除的 compile-time only 实现,害得我都不得不 unchecked cast 了,气死我了
比方说它非得弄个 get(Object) 的 API,虽然擦除后 get(K), get(Object) 都是 get(Object),我 TM…… 还得被,而且,我拿不到 reified 的类 Class<T>,不可能自然也不应该运行时检查类型
Java 辣鸡!!!
比方说它非得弄个 get(Object) 的 API,虽然擦除后 get(K), get(Object) 都是 get(Object),我 TM…… 还得被,而且,我拿不到 reified 的类 Class<T>,不可能自然也不应该运行时检查类型
Java 辣鸡!!!
我们怎么能这样批评 Java 呢,Java 君活得那么努力,努力到写了 90% 都是 boilerplate,我还以为我在做什么不得了的事情,以至于花了很长时间。
其实都是 🌬!emmmm
其实都是 🌬!emmmm
我还以为我 100+ 行写了什么不得了的东西,其实他们要测试,你知道为什么要测试吗?因为一大堆全都是无聊的代码!
为什么一些无聊的东西还需要测试?因为人的精力是有限的,无聊的东西看多了,有用的东西就容易写错!!!
为什么一些无聊的东西还需要测试?因为人的精力是有限的,无聊的东西看多了,有用的东西就容易写错!!!
但是不管写多长都 1.2K 的体积很令我满意,当然我知道,缩减体积不是程序员该做的事情,可是我就是讨厌 Kotlin 过了一遍 Proguard 还是 50K+ 的类文件大小……
反正 Java 还可以翻译到 Kotlin 的
反正 Java 还可以翻译到 Kotlin 的
同样的代码,Haskell 里就是
Kotlin 里也不困难
可是 Java 里要写十几行,我 (TMD) 快写疯了!
{-# LANGUAGE GADTs #-}
data Ray t a = (Ord t) => Shadow t a | (Ord t) => White t Kotlin 里也不困难
sealed class Ray<out T: Comparable<T>, out V> {
data class White<T>(val c: T): Ray<T, *>
data class Shadow<T, V>(val c: T, val x: V): Ray<T, V>
} 可是 Java 里要写十几行,我 (TMD) 快写疯了!
写了半天这类无聊的东西,那个至关重要的二分查找我都快忘记了 💭
而且因为他们很多,还得写不少测试
我终于明白为什么 Java 都是『大项目』了
而且因为他们很多,还得写不少测试
我终于明白为什么 Java 都是『大项目』了
This media is not supported in your browser
VIEW IN TELEGRAM
MD 个 🍻,气死我了,看来没时间不敢用 Java
说起来,没 Kotlin Multiplatform,JS/JVM 还得分着写(虽然有别的翻译器)
那更浪费时间
还是 TypeScript 好
可我不喜欢动态类型
Kotlin 的类文件体积不好缩减
不管动态不动态,JDK Collections Framework 这种把一大堆什么 putAll, isEmpty, entrySet(), values(), containsKey() 不给 default 的,简直是魔鬼!
难道我的 KvMap 要扩展它的接口?难道我的 KvMap 不该在 pass 掉一些辣鸡操作的前提下扩展支持 Map 的接口???
吃完饭我会讲一下 RangeMap 的理论
尼玛,我以为我效率多高呢。
说起来,没 Kotlin Multiplatform,JS/JVM 还得分着写(虽然有别的翻译器)
那更浪费时间
还是 TypeScript 好
可我不喜欢动态类型
Kotlin 的类文件体积不好缩减
不管动态不动态,JDK Collections Framework 这种把一大堆什么 putAll, isEmpty, entrySet(), values(), containsKey() 不给 default 的,简直是魔鬼!
难道我的 KvMap 要扩展它的接口?难道我的 KvMap 不该在 pass 掉一些辣鸡操作的前提下扩展支持 Map 的接口???
吃完饭我会讲一下 RangeMap 的理论
尼玛,我以为我效率多高呢。
@data @override @pure @fun @overrideFun等我先把这些 kt4java Annotation 实现再说
@in @out @some
@get @set @protectedGet @protectedSet
duangsuse::Echo
@data @override @pure @fun @overrideFun @in @out @some @get @set @protectedGet @protectedSet 等我先把这些 kt4java Annotation 实现再说
├── [ 1.8K] Data.class
├── [ 1.1K] KvMap$1.class
├── [ 917] KvMap$KvPair$Mutable$Of.class
├── [ 505] KvMap$KvPair$Mutable.class
├── [ 2.0K] KvMap$KvPair$Of.class
├── [ 667] KvMap$KvPair.class
├── [ 2.5K] KvMap$Mutable.class
├── [ 4.5K] KvMap.class
├── [ 447] OperationNotSupportedException$Mutability.class
├── [ 1.1K] OperationNotSupportedException.class
├── [ 1.6K] RangeIE$IntRange.class
├── [ 1.6K] RangeIE$LongRange.class
├── [ 381] RangeIE.class
├── [ 1.7K] RangeMap$Mutable.class
├── [ 990] RangeMap$Ray$Shadow.class
├── [ 1.1K] RangeMap$Ray$White.class
├── [ 1.1K] RangeMap$Ray.class
├── [ 1.7K] RangeMap.class
└── [ 258] RayRangeMap.class
其实为什么不用 Kotlin,还要加上 annotation processing 也用 Java,这张看得很明白
Kotlin 必须有 Kotlin Runtime,那可大啊,而且小不了…… Scala 也一样
他们的通病……
有时候,我觉得如果利用 Annotation 扩展,Java 也不一定会怎么样差……
你们看了我上面的消息,肯定认为我恨死 Java 了,其实我真的不是恨 Java,我『恨』的是辣鸡编程风格。
我是函数式风格的程序员,看不惯一大堆 boilerplate 代码(何况我要对正在编写的东西实时进行模拟的,太多行代码会严重影响我的手感,太复杂的继承结构和数据封装、无必要的抽象更是会导致我像吃了 💩 一样难受)。
很多人不知道怎么写 Annotation Processor(不过知道怎么用),但是绝大部分人都会写 C Macro,我相信很多 Rust 的程序员也都会写和 regex 语法很像的
macro_rules!
对于我来说,代码生成、修改 AST 就是我的老本行…… 混饭吃的东西,当然这个不是不可说(其实我也是从周老的《JVM 最佳实践》抄的)怎么说呢,我先举一段 #Kotlin 代码,如果连这个都搞不懂就不要看了(当然也看不懂,因为你连括扑「排序」都不会,还需要学习啊),用我写出来的库吧。
sealed class SumTree {
data class Group(val children: Iterable<SumTree>): SumTree()
data class Tip(val n: Int): SumTree()
interface Visitor<out R> {
fun see(x: Tip):R fun see(g: Group):R }
fun <R> rewriteBy(vis: Visitor<R>): R = when (this) {
is Tip -> vis.see(this)
is Group -> vis.see(this)
}
}
object Sumer : SumTree.Visitor<Int> {
override fun see(x: SumTree.Tip) = x.n
override fun see(g: SumTree.Group) = g.children.sumBy { sum(it) }
private fun sum(t: SumTree) = t.rewriteBy(this)
}
>>> SumTree.Group(listOf(1,2,3).map(SumTree::Tip).asIterable())
Group(children=[Tip(n=1), Tip(n=2), Tip(n=3)])
>>> SumTree.Group(listOf(1,2,3).map(SumTree::Tip).asIterable()).rewriteBy(Sumer)
6
(之前我一直以为我有 see: Sumer.(Tip) -> R; Sumer.(Group) -> R 就万事大吉了,艹,还得 Visit fun 专门去 instance check(其实我也可以抽象出一个
Tip.plus(Tip): T,这样就能直接在一个群(group),而不是 List<Int> 什么的里执行计算也就是 Javac 的 Inline annotation processor JSR-269 API 啦,
javax.annotation.processing.AbstractProcessor
你要处理生成的,就是 javax.lang.model.element, Java 的 AST,可惜是不可改变的一段代码,我举个简单的例子,比如说给方法的名字加前缀:
(其实已经不简单了…… 比较长,而且实现的东西不多……
看来自动生成代码还是要更多努力才行的,不过我不是说 Javac 这样就理所应当。
骚一点的(类似 Python decorator 的手段,我把部分数据加在特定的
@interface 上,而不是 Annotation Processor 看的那种上面)simple-ap.zip
11.6 KB
🐴 的,Annotation Processor 那么花,居然只能用来「访问」部分数据,它不能改变源语法树!
@NamePrefixed(prefix = "Aa") public class A {}
[DuangSUSE@duangsuse]~/Projects/essay/simple-ap/out/production/kt4java% javac -cp . -processor Processor ../../../src/A.java -XprintRounds -XprintProcessorInfo循环 1:
输入文件: {A}
注释: [NamePrefixed]
最后一个循环: false
处理程序Processor与[NamePrefixed]匹配并返回true。
注: Prefix: Aa from [NamePrefixed]
警告: Name A does not started with Aa
循环 2:
输入文件: {}
注释: []
最后一个循环: true
1 个警告
请问,
原来它只能用来『访问』AST!而且还是『部分地』访问!
有再大帮助也没有暖用