duangsuse::Echo
『讷,这就是核心部分的代码了,没有问题我去睡觉了』
哦,对了,不得不说一下
其实 RangeMap 本来应该是
RangeMap 是一个在有序的序列存储后端上执行二分查找的算法,所以可以达到这样的时间/空间复杂度
(其实本身不是特别复杂,不过作为一个类封装起来会好用很多)
RangeMap 到底是怎么工作的其实 RangeMap 本来应该是
template<> RangeMap<int, int>, 反正它的真名是 RayRangeMap,利用数学的『射线』进行建模优化的算法,也就利用 Comparable 泛化了一下……val rm = RangeMap<Int, String>()理论上,RangeMap 只需要
rm[0 until 1] = "0"
rm[1 until 4] = "123"
rm[4 until 6] = "45"
assert (0 in rm)
assert (3 in rm)
assert (rm.containsEdge(0))
assert (6 !in rm)
assert (rm[0] == "0")
assert (rm[3] == "123")
assert (rm[5] == "45")
assert (rm.containsShadow(5))
O(log2 n) 的复杂度即可查找到某一个项目,并且比 HashMap 节省空间。RangeMap 是一个在有序的序列存储后端上执行二分查找的算法,所以可以达到这样的时间/空间复杂度
(其实本身不是特别复杂,不过作为一个类封装起来会好用很多)
class Array写不出 算了
def lookupFirstGE(near, beg = 0, endInclusive = size-1)
puts("#{beg} until #{endInclusive}")
viewport = endInclusive - beg
if viewport == 0 then return self[beg] end
if viewport == 1 then return self[endInclusive] end
mid = (viewport+1) / 2; item = self[mid]
return case
when item == near then item
when item > near then lookupFirstGE(near, beg, mid-1)
when item < near then lookupFirstGE(near, mid+1, endInclusive)
end
end
end
duangsuse::Echo
class Array def lookupFirstGE(near, beg = 0, endInclusive = size-1) puts("#{beg} until #{endInclusive}") viewport = endInclusive - beg if viewport == 0 then return self[beg] end if viewport == 1 then return self[endInclusive] end mid = (viewport+1)…
说实话,今天我都有点不想写 RangeMap 了,毕竟昨天因为害怕写不完的缘故,我凌晨两点才睡觉…… 彼时我喉咙还有点发炎,现在是非常发炎
(而且那一部分核心代码应该是必须得重写了,我没考虑到不能向下圆整的问题,我也不确定
(而且那一部分核心代码应该是必须得重写了,我没考虑到不能向下圆整的问题,我也不确定
(a+1)/b 是否就是向上圆整了)
duangsuse::Echo
『讷,这就是核心部分的代码了,没有问题我去睡觉了』
我打算用循环写,毕竟循环更灵活,可以解决 floor div 导致的代码繁复问题,也不会陷入死循环(因为我不需要给 GT 的情况『留空』了,我只需记录最后 GT 的索引即可)
不写了、放弃了、累死了,这 Annotation Processor 是多麻烦,一个 AST 想解构还不容易啊…… 如果用 Visitor pattern 会方便很多,可我需要能够检查 path 的 Tree/Visitor,不知道有没有这种 API,这次只能暂时以二分查找最小的
(it >=k) 结尾吧,写点其他的吧…… #task我还用 Resource Bundle,resources 简直就一大坑,我不该一上来就用 resources 的! #Java
或许我下次应该找一个大佬分享一下写 APT 的技巧,比如说,
我真的不想光写一个那啥,但是不用 Visitor 和对象内部状态解决那个树的访问问题实在太过分了,可有些东西我不知道该怎么办啊…… 一些东西容易混淆,比如 Class 的 type param list 和 TypeParameter…… 语法上是一样的
或许我下次应该找一个大佬分享一下写 APT 的技巧,比如说,
@NamePrefix("pref") class 怎么要求里面的 executable, filed, localvar 啊都拿这个做前缀…… 比如 @hasGetter @hasProtectedSetter @data 怎么实现……我真的不想光写一个那啥,但是不用 Visitor 和对象内部状态解决那个树的访问问题实在太过分了,可有些东西我不知道该怎么办啊…… 一些东西容易混淆,比如 Class 的 type param list 和 TypeParameter…… 语法上是一样的
duangsuse::Echo
不写了、放弃了、累死了,这 Annotation Processor 是多麻烦,一个 AST 想解构还不容易啊…… 如果用 Visitor pattern 会方便很多,可我需要能够检查 path 的 Tree/Visitor,不知道有没有这种 API,这次只能暂时以二分查找最小的 (it >=k) 结尾吧,写点其他的吧…… #task
#PL 通俗的方法是使用
的
《深入理解 Java 虚拟机》那本书教的不对啊!
package javax.annotation.processing.util; 的
ElementScanner8<R, P>#scan(Element e); 《深入理解 Java 虚拟机》那本书教的不对啊!
javax.annotation.processing 不能拿来修改和生成语法树节点啊!!!空欢喜我一场!package javax.annotation.processing;
public interface Filer {...} 呀,不错嘛,还提供有能够生成代码的东西(这样 GeekSpec 就可以直接利用 Java APT 集成了,也是个好想法)。一个 javac 包含 locale, options, sourceVersion, messager, filer, types, elements 等多个好用的组件或信息
可见 annotation processor 还是很强大的,有意思的是,Annotation processor 连 IDE 的补全 API 都有
getCompletions(e, AnnotationMirror, ExecutableElement, userText): Iterable<out Completion>This media is not supported in your browser
VIEW IN TELEGRAM
想要学习一下怎么写 #Java Annotation Processor 的同学们快来看辣,花了我两个小时……
也是个好康的,比 《深入理解 Java 虚拟机(第二版)》上的那个还简单,我没检查
(虽然 APT 也未必是一个怎么样的技术,不过了解一下入门总还是好的,起码可以基于元数据编译期静态代码生成)
就是用一个 Visitor Pattern (
也是个好康的,比 《深入理解 Java 虚拟机(第二版)》上的那个还简单,我没检查
A__SNAKE 这种双下划线的情况,全用的 regex,而且没有一个类超过一百行代码,绝对很省事(虽然 APT 也未必是一个怎么样的技术,不过了解一下入门总还是好的,起码可以基于元数据编译期静态代码生成)
import org.intellij.lang.annotations.Language;可能没有比这个版本写的更简单的了…… 原版是基于状态机和索引字符 codePointAt(int) + java.lang.Character,十分不好看
public enum CaseJudge {
snakeCase("(_?\\p{javaLowerCase})+"), ...;
@FunctionalInterface interface Checker { boolean isValid(String name); }
final Checker checker;
CaseJudge(@Language("regexp") String regex) { this(s -> s.matches(regex)); }
CaseJudge(Checker checker) { this.checker = checker; }
}
就是用一个 Visitor Pattern (
ElementScanner8<Void/*res*/, Void/*arg0*/>) 先序遍历来检查语法树里的名字
duangsuse::Echo
居然花了两个小时!不过好歹是写完了 #Java
大家从
javac -cp out/production/name_checker/ -processor NameChecker src/BAD.java 里的这个 class NameChecker extends BaseNameChecker {
public synchronized void init(ProcessingEnvironment);
public boolean process(Set<out TypeElement> annotations, RoundEnvironment);
}
开始看就好了,process 就是检查一下,就上 ElementScanner#scan
duangsuse::Echo
大家从 javac -cp out/production/name_checker/ -processor NameChecker src/BAD.java 里的这个 class NameChecker extends BaseNameChecker { public synchronized void init(ProcessingEnvironment); public boolean process(Set<out TypeElement> annotations, RoundEnvironment);…
效果:
处理程序NameChecker与[]匹配并返回false。 (
src/BAD.java:4: 警告: `BAD' should be capitalized
当然,processor 也可以做更复杂的事情,比如检查类型(hides, overrides, subtype 什么的),除了不能改原有的代码……
处理程序NameChecker与[]匹配并返回false。 (
@SupportedAnnotationTypes("*"))src/BAD.java:4: 警告: `BAD' should be capitalized
public class BAD<tt> {
^
src/BAD.java:4: 警告: `tt' should be screamSnakeCasedpublic class BAD<tt> {
^
src/BAD.java:9: 警告: `NOT_A_CONSTANT' should be camelCasedpublic static int NOT_A_CONSTANT = _FORTY_TWO;src/BAD.java:11: 警告: `simpleArg' should be snakeCased
^
protected void BADLY_NAMED(Object simpleArg) {
^
src/BAD.java:14: 警告: Method with the same name of class constructor is confusing public static <tT> void BAD() {
^
src/BAD.java:14: 警告: `tT' should be screamSnakeCased public static <tT> void BAD() {
当然,processor 也可以做更复杂的事情,比如检查类型(hides, overrides, subtype 什么的),除了不能改原有的代码……
👍1