同样的代码,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!而且还是『部分地』访问!
有再大帮助也没有暖用
duangsuse::Echo
为什么我感觉像是在吃 💩
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.util.ElementScanner6;
import static javax.tools.Diagnostic.Kind.*;
@SupportedAnnotationTypes("NamePrefixed")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class Processor extends BaseProcessor {
public Processor() {}🤔 #Java #Type #PLT 其实在 Java 内部也是存在 Union type (∪) 和 Intersection type (∩) 的
Union type (A∪B) 视为一个值的集合,它的值可能是 A 或 B 的一种
这种情况就是 Java 1.7 引入的 multi-catch
Intersection type (A∩B) 视为一个值的集合,它的值同时属于 A 和 B。
∩ 对称着逻辑运算符 logical and (∧),它的意思是 x∈A ∧ x∈B
Union type (A∪B) 视为一个值的集合,它的值可能是 A 或 B 的一种
这种情况就是 Java 1.7 引入的 multi-catch
(A∪B) = {x | x∈A ∨ x∈B}
(Int∪String) = {1,2,3,"A","B","C",...}
try { scanUserInput(); }
catch (EOFException | ReadError | ParserError e) { e.printStackTrace(); }
(Java 好慢啊!!!虽然 Kotlin 也没有明确的更多 Union 扩展)Intersection type (A∩B) 视为一个值的集合,它的值同时属于 A 和 B。
∩ 对称着逻辑运算符 logical and (∧),它的意思是 x∈A ∧ x∈B
(A∩B) = {x | x∈A ∧ x∈B}
(String∩Object) = {"a", "str", ...}
(Exception∩RuntimeException) = RuntimeException
这种情况就是 Java 一直以来不常见的语法:Type parameter with intersection (&) bound<T extends Comparable<T> & Preety> List<Pretty.Document> preetyOrdered(List<T> inputs);
duangsuse::Echo
import javax.annotation.processing.*; import javax.lang.model.SourceVersion; import javax.lang.model.element.*; import javax.lang.model.util.ElementScanner6; import static javax.tools.Diagnostic.Kind.*; @SupportedAnnotationTypes("NamePrefixed") @Support…
The apt reflective APIs provide a build-time, source-based, read-only view of program structure. (FUCK YOU!) 😭
char hexDigit(int b) { return (b >= 10)? 'a'+(b -10) : '0'+b; }This media is not supported in your browser
VIEW IN TELEGRAM
我可能要思考一下,毕竟我得专门为这类事情建立一个 Gradle task (plugin)... 来生成代码
虽然这不是不可行,可其实我只需要修改部分代码,而不是利用 APT 的接口加上 JavaPoet 完全自己生成代码(然后再通过 Javac 编译),那么就不得不使用类似字节码修改的方式来完成
emmm.... 代码生成不难,但是毕竟是第一次做,太麻烦了,不如暂时拉倒。
虽然这不是不可行,可其实我只需要修改部分代码,而不是利用 APT 的接口加上 JavaPoet 完全自己生成代码(然后再通过 Javac 编译),那么就不得不使用类似字节码修改的方式来完成
emmm.... 代码生成不难,但是毕竟是第一次做,太麻烦了,不如暂时拉倒。
Forwarded from dnaugsuz
Java 有个 Project lombok
可是我不敢相信它真的能做到写得好看,我非常需要 Kotlin 的
我想的是写成 Kotlin 那样
即便构造语法树结构有些冗长,但是如果有效也是好的,哪怕是字节码都行
可关键是目前这种只能上第三方 Task 的情况有点超出预期了,唉
可是我不敢相信它真的能做到写得好看,我非常需要 Kotlin 的
data, in, out, get, set 来简化代码(辣鸡 Java 不支持啊!)我想的是写成 Kotlin 那样
即便构造语法树结构有些冗长,但是如果有效也是好的,哪怕是字节码都行
可关键是目前这种只能上第三方 Task 的情况有点超出预期了,唉
dnaugsuz
基本满意,可是我真的很想给这些 Annotation 弄成 alllower 的…… 我讨厌无论实际语义如何都用『统一』的代码风格
居然连 @Builder 都有了,我瞬间有一种官方逼死同人的感觉,本来我也想写的…… 😿 看来意义降低一半了