/tmp/duangsuse.sock
数据流和某些数据本身的回溯真的是不好做的,lifetime 也很难分析 就像这次我奇怪的递归查找一样,其实这不是最好看最高效能的方法(虽然它也很好)。 设计思路永远应该是第一,可是实现的方法就有那么多种,怎么才能对自己的架构拥有良好的直觉呢? 架构是个更大的问题,可是对于连数据生存周期和依赖都看不透的我来说有点高大上 了。 虚表做并且缓存的事情,我让实例去做,但是编程中我也发现 对于高阶函数 UpValue 数据生存周期的选择和分析,真是不好做啊, 感觉自己可能莫名其妙就引用错了 UpVal…
如果想要覆盖『父类』(实质是自己的 prototype)的架构器,很不幸,不可能
因为你的父类架构器总在你之前调用。
如果想要使用某个类的父类架构器,可以
1. 指名道姓地引用,
1. 用名字去引用父类的方法
2. 修改 oop 模块的 member_creation
以上 (2) 项目都是玩玩而已,实际上完全没有必要(跑
如果想要拥有静态方法和静态字段,则需要建立
面向对象的混入(mix-in) 必须通过修改 vtable 虚表查找和 oop 模型来建立,因为要混入额外的成员查找路径
因为你的父类架构器总在你之前调用。
如果想要使用某个类的父类架构器,可以
1. 指名道姓地引用,
animal.ctor(o)
2. 修改 oop 模块的源码,让 __newindex 元方法在冲突的时候定义 dog.super_ctor, 或者直接使用 dog.super.ctor
如果面向对象实例行为的覆盖想要使用父类的操作:1. 用名字去引用父类的方法
2. 修改 oop 模块的 member_creation
__newindex, 在发现覆盖的时候定义一个 super_XXX 就可以以上 (2) 项目都是玩玩而已,实际上完全没有必要(跑
如果想要拥有静态方法和静态字段,则需要建立
companion object
使用静态(需要和实例级别的成员完全隔离)的时候也得完全隔离(虽然实际作用域上是行为和状态都不分开,实例作用域可以随便引用静态成员,和 Lua OOP 里的相称,不过 LuaOOP 里 cat.name 是不能当成『类』的『静态成员』看待的,只有实例成员才会向上查找继承树)object = inherit.class()
animal.helper = object.new()
animal.helper.feed_animal = function ...面向对象的混入(mix-in) 必须通过修改 vtable 虚表查找和 oop 模型来建立,因为要混入额外的成员查找路径
/tmp/duangsuse.sock
... 我打算浅尝辄止了,因为事情的确比较多... 我不想在 #Lua 和 #OOP 上花太多精力 简单讲一下,LinkIterable 和 InvocationChain 也非常简单,LinkIterable take 一个 object、一个 chainf、一个 hasnextf,具体怎么做就是通过 hasnextf 确认是否有下一项、 chainf 箭头完成状态切换。 InvocationChain 就是 ListIterator 控制,使用完全相同参数调用的函数 chain 而已,利用副作用在受管函数间传递,实现了…
LinkIterable 可以用来实现基于 super 指针的超类成员查找InvocationChain 则可以实现对架构器链条的调用(非 prototype 模式的,子类架构器可以选择是否调用超类架构器来初始化)不过还是先写... 《基于状态机的流处理程序和文本解释器》 休息一下~
Traceback.java
3.8 KB
#Java 咳咳,既然频道只有认识我的几位 dalao,我就发下链接了。其实这个是我重写 drakeets 上面的。
利用
tracefmt("main") 来生成对 console application 的回溯追踪test2::Traceback← 86
test
::↑← 85
类似这样,它能提示很多信息,不止一个 name
/tmp/duangsuse.sock
Traceback.java
我特意下载了图片,不知道隔壁实现的可以看看:
我现在已经不敢评价他的代码了,每次涉及一点点负面都要解释半天真麻烦啊。
所以代码我一个字都没有动,都是战战兢兢地完全复制下来的 0_0
我们直接跳过
我现在已经不敢评价他的代码了,每次涉及一点点负面都要解释半天真麻烦啊。
所以代码我一个字都没有动,都是战战兢兢地完全复制下来的 0_0
/** @author Drakeet Xu */
object Debugs {
fun stackTrace(self: Any, @IntRange(from = 2) limit: Int = 3): String? {...}
}
其中,实际实现:if (!BuildConfig.DEBUG) return null
val result = StringBuilder()
var length = 0
for ((i, it) in Thead.currentThread().stackTrace.withIndex()) {...}
return result.toString()
在循环里,我们处理格式化问题。if (i < 4 || it.methodName.contains("\$default")) continue
如果还在访问开始的 4 项 (0,1,2,3) (反射了上面的 Thead.currentThread().stackTrace.withIndex() 和自己的调用记录),或者方法名包含 $default(一般自动生成的方法名包含此)我们直接跳过
if (length > 0) result.append(" <- ")
如果不是输出的第一项,则我们输出一个箭头,目标是实现字符串列表的 join
if (self.javaClass.name != it.className) { result.append(it.className).append(".") }
如果不是当前应用程序的类,则附上类名信息result.append(it.methodName.replace("\$app_debug",""))
输出项目方法名,去掉其中的 $app_debug 部分length++
if (length >limit) break
如果已经输出了 n 项,就停止输出。
/tmp/duangsuse.sock
我特意下载了图片,不知道隔壁实现的可以看看: 我现在已经不敢评价他的代码了,每次涉及一点点负面都要解释半天真麻烦啊。 所以代码我一个字都没有动,都是战战兢兢地完全复制下来的 0_0 /** @author Drakeet Xu */ object Debugs { fun stackTrace(self: Any, @IntRange(from = 2) limit: Int = 3): String? {...} } 其中,实际实现: if (!BuildConfig.DEBUG) return…
其中,
实际的逻辑
上面的『状态机』部分就有一个好,它是自律(self-managed) 的
其实编程中一般被抽象为实例(模块)或高阶方法、generator,它只是保留状态,随时可以挂起。
就像上面的 forEach,其实完全可以删掉,变成『输入流对接到状态机 🐤 上』
输入流结束后,
partitionWhile 使用了状态机模式实现。partitionWhile:
input List<T> xs
input Predicate<? super T> p
output Pair<List<T
>, List<T>> res
这是此算法的签名 where part (0), takeall; part -> takeall
两个状态。计算可以这么描述forEach x : xs两个同步操作、三个输入信号 take, drop, x
let drop = p.test(x), take = !drop
dropIt = res.component0.add(x)
takeIt = res.component1::add(x)
实际的逻辑
part <- drop = dropIt
part <- take = takeIt => takeall
我们在获得了第一个 take 的项目后同时通过状态转移进入了 takeall 状态takeall <- drop/take = takeIt
takeall 状态里,无论 take 还是 drop 的结果都是 takedstate* <- take = takeIt
所以才说我写的代码烂,因为理论稍微看一下就知道,已经覆盖了所有情况。上面的『状态机』部分就有一个好,它是自律(self-managed) 的
其实编程中一般被抽象为实例(模块)或高阶方法、generator,它只是保留状态,随时可以挂起。
就像上面的 forEach,其实完全可以删掉,变成『输入流对接到状态机 🐤 上』
输入流结束后,
res 里面就是整个算法的结果了。#Java 下面我会对 Promise 进行 Jawa 建模,过后有神秘分享哦(非技术向(跑,其实不值得期待
什么是 Promise 呢?英文中 Promise 的意思是保证。这里的 Promise 的意思则是 ECMAScript 6 新推出异步编程的一项特性。
异步编程是什么? Android 开发者会举出一种简单例子:
别的例子,AsyncTask 封装(还有一个)
不要忘了,最终执行你程序的还是机器处理器,所以所谓『异步』还是机器提供的特性。
『异步』,有时候是从其他『线程』在做的处理,但多数情况下都和处理器中断有关。
为了演示方便和篇幅考虑,我选择用汇编给 x86 DOS 写类似上面的那个例子... 按下按键的时候就(越过 DOS 操作系统地)输出字符
https://wiki.osdev.org/Interrupts
http://spike.scu.edu.au/~barry/interrupts.html#ah02
总之,我们可以认为『异步』就是不在我们的『串行』程序逻辑执行过程中被处理的东西,它有一个额外的处理进程。
而异步和我们有个毛线的关系?关系只在不同的『处理进程』发生联系的时候出现,例如需要有某种『信号』在线程间传递,打断正常的串行执行(或许这种打断是被预期的,也可能并没用打断,而是主动执行分派),让异步信号得到处理。
这是『异步信号』(类似 Qt 的信号/插槽)模型,比较通用。因为其他进程的执行状态,抽象成信号也是很直白的。不过注意这个『信号』是抽象的,不代表信号就应该怎么样地(例如在『线程』 A)被处理。
当然,也有『回调』,实际上就是把信号处理固定在任务执行的线程进行了(
以上是信号的抽象,可以认为是一种
所谓 Promise,它的意思是这项特性『保证』了异步任务的状态转移存在某种规律:
states
pending (reject)~> rejected (catch)
初始状态是 pending,代表任务正在执行
除了这样以外没用其他可能,不能从 resolved 变回 pending 或者转移到 rejected,这就是 Promise 的含义。
那么终于进入正题了:Java 里该如何抽象?
然后有个
还应该实现 Promise.resolve, Promise.all, Promise.race, Promise#done, Promise#catch 方法 🤔
什么是 Promise 呢?英文中 Promise 的意思是保证。这里的 Promise 的意思则是 ECMAScript 6 新推出异步编程的一项特性。
异步编程是什么? Android 开发者会举出一种简单例子:
Button.OnClickListener exitApplication = (_) -> { finish(); };
assert exitApplication == new Button.OnClickListener() {
@Override void onClick(View _) { this.finish(); }
};
btnExit.setOnClickListener(exitApplication);
finish() 是 Activity 的方法,它标记当前活动状态为已结束。别的例子,AsyncTask 封装(还有一个)
class AsyncTask<R>(work: () -> R): AsyncTask<Void, Nothing, R> {
private var result: R
var onResult: Function<R, *>?
override fun doInBackground(vararg parms: Void) { result = work() }
override fun onPostExecute(result: R) = onResult?.invoke(result)
}
val dl = AsyncTask { downloadUrl("https://baidu.com/favicon.ico") }
dl.onResult = { println(it.size) }
dl.execute()
Web stackholder 则会举出更简单的例子(因为浏览器环境毕竟和 app 不同的原因,权限控制有区别,请大家忽视处理上的一些区别...):btnExit.onclick = () => window.close();
Qt 和 GObject 的开发者则会使用 Signal & slotsconnect(btnExit, SIGNAL(onClick()), this, SLOT(closeAllWindows()));C# 的开发者会使用 C# 的 Event
+=
btnExit.click += () => Environment.Exit(0);最直白的例子还是 C/C++ 使用 Signal 的时候,此时没有那么多额外的东西干扰视线(比如对象对数据的封装,有时候可以把对象理解为操作被抽提的模块)
#include <csignal>当然最最直白的特性还是为特定机器编程时设置的 interrupt 处理器(跑
#include <iostream>
using namespace std;
void doTrapSigInt() {
signal(SIGINT, [](int s) { cout << "SIGINT ("<<s<<") Received" << endl; });
}
[[noreturn]] int main() {
doTrapSigInt();
for(;;){}
}
不要忘了,最终执行你程序的还是机器处理器,所以所谓『异步』还是机器提供的特性。
『异步』,有时候是从其他『线程』在做的处理,但多数情况下都和处理器中断有关。
为了演示方便和篇幅考虑,我选择用汇编给 x86 DOS 写类似上面的那个例子... 按下按键的时候就(越过 DOS 操作系统地)输出字符
https://wiki.osdev.org/Interrupts
http://spike.scu.edu.au/~barry/interrupts.html#ah02
bits 16啊又跑偏了... 上面的程序在 DOSBox 里测试是失败的 不知道为什么...(求不喷没用 marco)
kbdval db 0x60
pic db 0x20
sys db 0x21
DOS_displaychar db 0x02
ivt_kbd db 9*4
_entry:
cli
mov word [ivt_kbd], kbdInt
mov word [ivt_kbd+2], 0
sti
mov al, 'D'; call putc_al
mov al, 'o'; call putc_al
mov al, 'n'; call putc_al
mov al, 'e'; call putc_al
mainloop:
hlt ; wait next interrupt
jmp mainloop
kbdInt:
push eax
in al, kbdval
call putc_al
mov al, pic
out pic, al
pop eax
iret
putc_al:
mov ah, DOS_displaychar
mov dl, al
call sys
ret
总之,我们可以认为『异步』就是不在我们的『串行』程序逻辑执行过程中被处理的东西,它有一个额外的处理进程。
而异步和我们有个毛线的关系?关系只在不同的『处理进程』发生联系的时候出现,例如需要有某种『信号』在线程间传递,打断正常的串行执行(或许这种打断是被预期的,也可能并没用打断,而是主动执行分派),让异步信号得到处理。
这是『异步信号』(类似 Qt 的信号/插槽)模型,比较通用。因为其他进程的执行状态,抽象成信号也是很直白的。不过注意这个『信号』是抽象的,不代表信号就应该怎么样地(例如在『线程』 A)被处理。
当然,也有『回调』,实际上就是把信号处理固定在任务执行的线程进行了(
以上是信号的抽象,可以认为是一种
Thenable, 只有一个方法 then(Listener),反正信号除了可以『监听』也没啥用了。所谓 Promise,它的意思是这项特性『保证』了异步任务的状态转移存在某种规律:
states
pending (0), resolved, rejected
pending (resolve)~> resolved (then)pending (reject)~> rejected (catch)
初始状态是 pending,代表任务正在执行
new Promise((resolve, reject) => { resolve(1) }).then((it) => console.log(it))
pending 时通过 resolve 箭头,我们状态转移到了 resolved 状态,并且 then 将会接收到此信号pending 时通过 reject 箭头,我们状态转移到了 rejected 状态,并且 catch 将会接收到此信号除了这样以外没用其他可能,不能从 resolved 变回 pending 或者转移到 rejected,这就是 Promise 的含义。
那么终于进入正题了:Java 里该如何抽象?
interface Thenable<R> { void then(Consumer<? super R> next); }
interface Failable<R> extends Thenable<R> { void then(Consumer<? super Result<R>> failable_next); }
这是我们对最基础『异步任务』的抽象:可以失败的东西然后有个
abstract class Promise 来扩展它还应该实现 Promise.resolve, Promise.all, Promise.race, Promise#done, Promise#catch 方法 🤔
Gist
Essay: Android cancellable asynchronous task API abstractoin in Kotlin
Essay: Android cancellable asynchronous task API abstractoin in Kotlin - Essay-Android-AsynchronousTaskAbstractoin.kt
🤔 Java 有个不好就是有时候太莫名其妙了,比如方法的
final 修饰、interface 的 abstract 修饰等等,语法上就不应该存在