谈范畴论:无id箭头如何
负片夜间模式(Canvas, img_cache.js, initNext(), show()=show(next);hide(this), hide()=hide(this);show(prev))
f: a -> b to forall a b. f: a -> b
负片夜间模式(Canvas, img_cache.js, initNext(), show()=show(next);hide(this), hide()=hide(this);show(prev))
digraph 某人 {
rankdir=BT;
somebody [label="某人", shape=record];
me [lable="我"];
motherOf [label="某人的母亲"];
me -> somebody [label="coprod"];
motherOf -> somebody;
} f: a -> b to forall a b. f: a -> b
duangsuse::Echo
🤔duangsuse 昨天晚上想到了一些话,愿意分享给大家。 #statement duangsuse(虽然一点也不好)是如何编程的呢? 他编程,是一个从整到零,再从零到整的过程。 首先是把一个相对比较大的目标,拆分成许多能够比较简单实现的小目标。 比如,把一个操作纷繁复杂的类(class),抽提出实现了很多接口的类。 接着是和自己争论实现的难点和复杂性,继续重新拆分和重新组织继承、数据依赖这样的关联,偶尔还会为一些经常联系在一起的东西(比如 Database, Controller) 起一些首字母简写,记住。…
还有就是这个,此外还应该提醒学会数据的依赖分析,这个其实主要还是看思想,实践是最好的方法。 #learn
比方说:
还有,input 本身可能有状态,在控制流图(CFG, Control Flow Graph)和计算、副作用的产生中可能有怎么样的变化,必须清楚。
最基本的:给你一个 val c,你要知道求出它需要依赖什么数据,如果有些断言要做,你得知道哪些情况叫『正常程序状态』『正常代码路径/程序路径』有哪些则是可能错误的。
另外,要知道一些东西不能太注意刻板的风格,要更加在意可读性。
比如,像 Android Gradle 插件里的
首先我们知道
再如,minSdkVersion 和 targetSdkVersion 不是一个区间范围(没有说高于 targetSdkVersion 不能用的),但可以认为它们应该被写在一行内,不会引起歧义也并不莫名其妙。
versionCode 和 versionName 也是一样的。
偶尔该加的分号要加,这点和『优雅的顺序』思想是一致的。
这样,他们在基于行号的VCS里如果改一个记录会显示只有一行的变动,不过相信没人会必要这个吧。
然后是要有抽提的逻辑,比如,我们这里有一个Android活动:(不要喷,只是个例子而已,另外错了请不失风度地指出,谢谢)
我们也不说其实 Activity 用 Intent 模型虽然是不得以(因为建模如此,而且语言层面也不好做什么)导致但不好看的问题了(理论上更优雅的Activity应该是带架构器参数而不是动态取参数的,否则也不该是类的形式,单实例就够了)
我们也不说 Kotter Knife 没有用 Annottion Processor 以及 Kotlin 的 first class delegates (delegated properties) 的事了。
我们也不说其实 onClick= 完全可以写在 init{} 里这件事,没必要覆盖 onCreate 这件事了……
我们也不考虑 onCreate 和其它 lifecycle event 比如 onResume 有啥区别了……
我们也不谈 Qt 的 signal/slot、.NET 的 event、Android 的传统 Listener 什么的有啥异同。
这里说说上面的一大堆
以前辣鸡Jawa弄得什么 anonymous subclass instance,害得那时候又年轻又阳光又帅气的我都看不懂那些代码,嘤嘤嘤。
相信写了很久Java但是不知道
一句话:
val buttons = listOf(btn0, btn1, btn2)
val texts = "wtf wttf wtttf".split(" ")
for ((btn, text) in buttons.zipWith(texts)) btn.
稍微有点常识的人不难看出,里面那个 { _ -> } 的闭包依赖 for 里面某次的 text 数据引用。
对这里的闭包关键的一点是:for 有多少次迭代就有多少 { _ -> ...text... } 产生,所以说偶尔闭包其实也不能那么『直观』地看尽管它本身设计目的之一就是为了直观(其实也没有……)。
然后 Kotlin 的 single abstract method interface
然后有些东西我也不懂
另:试试多加许多的 Button 然后动态创建(不是说用Anko)
最后的最后我想说一个问题,当然是我之前的一次误解 #web #JavaScript #fix
它有没有调用自己?答案是没调用自己,只是它做的操作引用到了自己而已。
递归的情况栈深度是除『基线』外每层调用往上涨的,非递归情况不变或者下降。
setTimeout 哪怕是timeout=0,也只可能在当前
(当然这不是递归最根本的特征,我只是详细说一个侧面的特征方便学习研究之用而已)
好吧这也不一定,尽管JavaScript是很单线程的语言,timeout=0 的具体情况也是看是否能抢断当前执行子程序的执行权而定的,这里假设timer需要等待应用程序的逻辑没在执行,而是回到底层的运行时库在维护工作状态时才能工作。
比方说:
import java.lang.System.`in` as stdin这就要求你有看出这个 c「偶尔」需要依赖 input 的(对象状态)意思。
val input = Scanner(stdin)
val a = 1
val c = a + if (p) a else input.nextInt()
还有,input 本身可能有状态,在控制流图(CFG, Control Flow Graph)和计算、副作用的产生中可能有怎么样的变化,必须清楚。
最基本的:给你一个 val c,你要知道求出它需要依赖什么数据,如果有些断言要做,你得知道哪些情况叫『正常程序状态』『正常代码路径/程序路径』有哪些则是可能错误的。
另外,要知道一些东西不能太注意刻板的风格,要更加在意可读性。
比如,像 Android Gradle 插件里的
android {} DSL首先我们知道
compileSdkVersion 是不能缺的,而且对 android {} 来说只用指定一次也没同样重要的东西,所以它可以不折行直接放在 android { 后,目的是体现它与这块定义的关联性。再如,minSdkVersion 和 targetSdkVersion 不是一个区间范围(没有说高于 targetSdkVersion 不能用的),但可以认为它们应该被写在一行内,不会引起歧义也并不莫名其妙。
versionCode 和 versionName 也是一样的。
偶尔该加的分号要加,这点和『优雅的顺序』思想是一致的。
这样,他们在基于行号的VCS里如果改一个记录会显示只有一行的变动,不过相信没人会必要这个吧。
然后是要有抽提的逻辑,比如,我们这里有一个Android活动:(不要喷,只是个例子而已,另外错了请不失风度地指出,谢谢)
class SomeButtonfulActivity: Activity() {
//KotterKnife
val btn0: Button by bindView(R.id.main.btn_0)
val btn1: Button by bindView(R.id.main.btn_1)
val btn2: Button by bindView(R.id.main.btn_2)
override fun onCreate(savedState: Bundle) {
super.onCreate(savedState)
//no-op ...?
btn0.onClickListener = {_ -> toast("wtf")}
btn1.onClickListener = {_ -> toast("wttf")}
btn2.onClickListener = {_ -> toast("wtttf")}
}
}
我们就不说 Activity 本身可继承、可抽提这件事了(可以对其中 onCreate, onResume 的逻辑等各另加组合,抽象出简单适体一点的版本给子类实现)我们也不说其实 Activity 用 Intent 模型虽然是不得以(因为建模如此,而且语言层面也不好做什么)导致但不好看的问题了(理论上更优雅的Activity应该是带架构器参数而不是动态取参数的,否则也不该是类的形式,单实例就够了)
我们也不说 Kotter Knife 没有用 Annottion Processor 以及 Kotlin 的 first class delegates (delegated properties) 的事了。
我们也不说其实 onClick= 完全可以写在 init{} 里这件事,没必要覆盖 onCreate 这件事了……
我们也不考虑 onCreate 和其它 lifecycle event 比如 onResume 有啥区别了……
我们也不谈 Qt 的 signal/slot、.NET 的 event、Android 的传统 Listener 什么的有啥异同。
这里说说上面的一大堆
btnx.onClick { _ -> toast("...") } 怎么抽提以前辣鸡Jawa弄得什么 anonymous subclass instance,害得那时候又年轻又阳光又
相信写了很久Java但是不知道
new XXX() {@Override...} 啥意思的人不止我一个,以致于后来换Java8了,很多Android开发者依然不知lambda为何物。另外一些开发者则出于某些媒体拙劣的宣传把虚拟机的invokedynamic扩展和lambda挂钩了,根本不去注意一下Java8的代码dexer出来带RuntimeDesugar(其实Java8的()->也的确是sugar)。一句话:
val buttons = listOf(btn0, btn1, btn2)
val texts = "wtf wttf wtttf".split(" ")
for ((btn, text) in buttons.zipWith(texts)) btn.
onClickListener= { _ -> toast(text) }
稍微有点常识的人不难看出,里面那个 { _ -> } 的闭包依赖 for 里面某次的 text 数据引用。
对这里的闭包关键的一点是:for 有多少次迭代就有多少 { _ -> ...text... } 产生,所以说偶尔闭包其实也不能那么『直观』地看尽管它本身设计目的之一就是为了直观(其实也没有……)。
然后 Kotlin 的 single abstract method interface
@FunctionalInterface 实现就不用说了然后有些东西我也不懂
另:试试多加许多的 Button 然后动态创建(不是说用Anko)
typealias Consumer<T> = (T) -> Unit
Map<String, Consumer<User>> 怎么样?其实动态创建还是动态注册监听差不多。最后的最后我想说一个问题,当然是我之前的一次误解 #web #JavaScript #fix
function fixedRateSchedule(time_ms, op) {
op(); setTimeout(() => fixedRateSchedule(time_ms, op), time_ms);
//也可以直接用 Function.prototype.bind
//语义上我们创建了一个依赖它上次调用的参数(是全等)引用的 fixedRateSchedule 闭包,实际上是不是新闭包可以自己用 (===) 判断。
}
你们说这个函数有没有『递归(recurse)』?它有没有调用自己?答案是没调用自己,只是它做的操作引用到了自己而已。
递归的情况栈深度是除『基线』外每层调用往上涨的,非递归情况不变或者下降。
setTimeout 哪怕是timeout=0,也只可能在当前
fixedRateSchedule实例的栈帧弹出(返回)后执行(要不然就不叫timer了),所以栈深度不变,没有递归。
(当然这不是递归最根本的特征,我只是详细说一个侧面的特征方便学习研究之用而已)
好吧这也不一定,尽管JavaScript是很单线程的语言,timeout=0 的具体情况也是看是否能抢断当前执行子程序的执行权而定的,这里假设timer需要等待应用程序的逻辑没在执行,而是回到底层的运行时库在维护工作状态时才能工作。
接下来准备弄Binarie…… 🤔
弄完我把这周学校里的绝句设计笔记拿来抄抄。
ParserKt 明天再和新的计算器一起写
弄完我把这周学校里的绝句设计笔记拿来抄抄。
ParserKt 明天再和新的计算器一起写
duangsuse::Echo
https://github.com/graninas/software-design-in-haskell
Haskell 拿来设计real-world大材小用了,何况我估计也没人会拿它做那事🤔emmmm
呵呵呵呵呵呵…… 忍不住想到会不会 Monad Activity 什么的,真是令人困惑呢。
呵呵呵呵呵呵…… 忍不住想到会不会 Monad Activity 什么的,真是令人困惑呢。
Scala 的特性也很高级,有各种 implicit 还多态还 case pattern matching,可是做工程也是没几个人用,估计是被人嫌太复杂
Kotlin 在 Java..Scala 是折中的,既做好语法设计,也不过分简单,还不太难学。
Kotlin 在 Java..Scala 是折中的,既做好语法设计,也不过分简单,还不太难学。
duangsuse::Echo
然后看看一些基本的算符…… inc后 dec前 plus加+ minus减- times乘* div除/ mod取余 unaryMinus取负-@ 扩展的位运算,我打算把他们放在专门的包里 and与「位交」 or或「位并」xor异或「位异」 shl左移「左移」shr右移「右移」 val KProperty0<*>.isInitialized: Boolean 量 fun TODO(reason: String): Nothing fun Throwable.addSuppressed(exception:…
abstract class EnumMap<K, EV>(private val map: Map<K, EV>): Map<K, EV> by map {
constructor(values: Iterable<EV>, key: (EV) -> K): this(values.map { key(it) to it }.toMap())
}
inline fun <K, reified EV: Enum<EV>> EnumMap(noinline key: (EV) -> K) = EnumMap(enumValues<EV>().asIterable(), key)
// f**k 不行啊
enum class Abc123(private val digit) {
A(1), B(2), C(3);
companion object: EnumMap<Int, Abc123>(Abc123::digit)
}
艹,忘记reified只能用于内联函数上了从学校带来的一张被作为草稿的卷子直接打上来的:
做梦一般又默写了一遍,反正我是想的 sourceSets, compileOptions, kotlinOptions 都是为了支持Kotlin+默认JDK 8然后居然就记住了,莫名其妙地。
//setting.gradle
rootProject.name = 'projectName'
include ':subName'
//build.gradle
buildscript {
ext {
kotlin = 'org.jetbrains.kotlin:kotlin'
adtVersion = '3.2.1'
kotlinVersion = '1.3.41'
}
repositories { jcenter(); google() }
dependencies {
classpath("com.android.build:gradle-build-tools:$adtVersion")
classpath("$kotlin-gradle-plugin:$kotlinVersion")
}
}
allprojects {
repositories { jcenter(); google() }
}
apply plugin: 'com.andriod.application' //|library
apply plugin: 'kotlin-android'
dependencies {
implementation("$kotlin-stdlib-jdk8:$kotlinVersion")
}
android { compileSdkVersion(25)
defaultConfig {
applicationId("com.example")
minSdkVersion(9); targetSdkVersion(26)
versionCode(1); versionName("1.0")
}
buildTypes {
def proguardDefault = getDefaultProguradFiles("progurad-rules.pro")
release { minifyEnabled(true); proguardFiles(proguardDefault) }
}
sourceSets {
main.java.srcDirs += "src/main/kotlin"
}
compileOptions {
def Java8 = JavaVersions.JAVA_1_8
sourceCompatiblity = Java8
targetCompatiblity = Java8
}
kotlinOptions {
jvmTarget = "1.8"
}
} 做梦一般又默写了一遍,反正我是想的 sourceSets, compileOptions, kotlinOptions 都是为了支持Kotlin+默认JDK 8然后居然就记住了,莫名其妙地。
import java.nio.ByteOrder as NioByteOrder
typealias Cnt = Int
typealias Idx = Int
typealias IdxRange = IntRange
typealias Buffer = ByteArray
infix fun IdxRange.untilSize(size: Cnt): IdxRange = this until (this+size) //0 until (0+10): 0..9
inline val IdxRange.size: Cnt get() = (last - first).inc() //0..0: (0-0)+1
typealias Nat8 = Int
typealias Nat16 = Int
typealias Char16 = Char
typealias Int8 = Byte
typealias Int16 = Short
typealias Int32 = Byte
typealias Int64 = Byte
typealias Rat32 = Float
typealias Rat64 = Double
interface MarkReset { fun mark() fun reset() }
fun <R> MarkReset.positional(op: Producer<R>): R
fun positionalTask(): Closeable //JVM
interaface ReadControl: MarkReset, Closeable {
val position: Cnt; val estimate: Cnt
fun skip(n: Cnt)
}
override tailrec fun seek(n: LongCnt) {
if (n == 0L) return //EOS
val skipped = this.skip(n)
if (skipped != 0L) seek(n - skipped)
} // for JVM InputStream
override var position: Idx = 0
protected set // for JVM InputStream
interface WriteControl: Flushable, Closeable
interface ByteReader {
fun readByte(): Byte
fun readTo(destination: Buffer, indices: IdxRange)
fun readToFill(destination: Buffer)
fun takeBytes(count: Cnt): Buffer
}
interface ByteWriter {
fun writeByte(b: Byte)
fun writeFrom(source: Buffer, indices: IdxRange)
fun writeAllFrom(source: Buffer)
}
interface DataReader {
fun readNat8():Nat8 fun readNat16():Nat16
fun readChar16():Char16
fun readInt8():Int8 fun readInt16():Int16
fun readInt32():Int32 fun readInt64():Int64
fun readRat32():Rat32 fun readRat64():Rat64
}
interface DataWriter {
fun writeNat8(x:Nat8) fun writeNat16(x:Nat16)
fun writeChar16(x:Char16)
fun writeInt8(x:Int8) fun writeInt16(x:Int16)
fun writeInt32(x:Int32) fun writeInt64(x:Int64)
fun writeRat32(x:Rat32) fun writeRat64(x:Rat64)
}
enum class ByteOrder { LittleEndian, BigEndian }
interface ByteOrdered { var byteOrder: ByteOrder }
fun systemOrder(): ByteOrder = when (NioByteOrder.nativeOrder()) {
NioByteOrder.LITTLE_ENDIAN -> ByteOrder.Little
NioByteOrder.Big_ENDIAN -> ByteOrder.Big
}
abstract class BaseDataReader(private val sourceOrder: ByteOrder): ByteOrdered, DataReader {
protected val shouldSwap get() = byteOrder != sourceOrder
}
interface Reader: DataReader, ByteReader, ReadControl, ByterOrdered
interface Writer: DataWriter, ByteWriter, WriteControl, ByterOrdered
typealias Shift<I> = I.(Cnt) -> Iintegral to sequence of Byte
typealias ByteSelect<I> = I.(I) -> Byte
typealias ByteUnion<I> = I.(Byte) -> I
1234 -> 1,2,3,4kotlin:
^popleft(shl(8*n)&and)
inline fun <I> integralToBytes(n: Cnt, byte_left: Byte,sequence of Byte to integral
crossinline shl: Shift<I>, crossinline and: ByteSelect<I>, i: I): Sequence<Byte> = sequence {
var accumulator = i
for (_t in 1..n) {
yield(accumulator.and(byte_left))
accumulator = accumulator.shl(Byte.SIZE_BITS)
}
}
1,2,3,4 -> 1234:kotlin:
(shl&or...&or)^pushright
1,2,3,4 -> 0(zero: I)
1,2,3,4 -> 0 shl 8 or 1
2,3,4 -> 1 shl 8 or 2
3,4 -> 12 shl 8 or 3
...
inline fun <I> bytesToIntegral(zero: I,rotate byte order
crossinline shl: Shift<I>, crossinline or: ByteUnion<I>, bytes: ByteIterator): I {
var accumulator = zero
for (byte in bytes) {
accumulator = accumulator.shl(Byte.SIZE_BITS).or(byte)
}
return accumulator
}
1 2 3 4 ->(rotate) 4 3 2 1
pop^(shr&and) push^(shl&or) kotlin:
inline fun <I> rotateIntegral(n: Cnt, byte_right: I,
crossinline shr: Shift<I>, crossinline and: ByteSelect<I>,
crossinline shl: Shift<I>, crossinline or: ByteUnion<I>, i: I): I {
var source = i; var rotated = i
for (_t in 1..n) {
val rightmost = source.and(byte_right).also { source = source.shr(Byte.SIZE_BITS) }
rotated = rotated.shl(Byte.SIZE_BITS).or(rightmost)
}
return rotated
}
duangsuse::Echo
typealias Shift<I> = I.(Cnt) -> I typealias ByteSelect<I> = I.(I) -> Byte typealias ByteUnion<I> = I.(Byte) -> I integral to sequence of Byte 1234 -> 1,2,3,4 ^popleft(shl(8*n)&and) kotlin: inline fun <I> integralToBytes(n: Cnt, byte_left: Byte, crossinline…
我想,这可能就是所谓的Literal Programming吧,或者即便不一样、有本质上的区别,也是一样高的代码质量,因为每一个步骤都说得清清楚楚,不带含糊冗余的东西,即便有bug也不需要debug,再看一遍就好了。
那个用 Sequence 是为了表述清楚一点的,实践上我可能害怕 Kotlin 不能给它弄成小体积点的形式…… 所以得换成继承自基于 ByteIterator 的超类。
那个用 Sequence 是为了表述清楚一点的,实践上我可能害怕 Kotlin 不能给它弄成小体积点的形式…… 所以得换成继承自基于 ByteIterator 的超类。
digraph BinarieReader {
SingleMarkReset; MarkReset;
SingleMarkReset -> MarkReset;
BufferStack [color=red];
ByteReader;
Colsable;
ReadControl;
Closable -> ReadControl;
MarkReset -> ReadControl;
DataReader;
ByteOrder;
ByteOrdered;
ByteOrder -> ByteOrdered [style=dotted];
BaseDataReader(Little) [color=red];
DataReader -> BaseDataReader;
ByteOrdered -> BaseDataReader;
ByteOrder -> BaseDataReader [style=dotted, color=blue];
Reader;
FileReader;
InputStream;
BufferStack -> Reader;
BaseDataReader -> Reader;
ByteReader -> Reader;
ReadControl -> Reader;
InputStream -> Reader [style=dotted, color=blue];
Reader -> FileReader;
}从 SingleMarkReset 到 MarkReset 最大的一个问题是真正可重入:
可是如果直接在 1,2,3 流里,每次 mark 去 push 上一层 buffer,然后 reset 的时候 pop 再加进当前 reset buffer(当然必须 insertAllAt(0) 或者干脆 reset buffer: Stack+pushAll reversed (a),因为 mark/reset 是按『后进先出』的),这样的方式来实现 MarkReset,会导致 reset buffer 本身不可 reset 的问题:
(a): 或者把记录用buffer也做成stack的LIFO(仅)样子
解决方法之一就是即便在 reset 后依然往(如果BufferStack不空)里面加东西。
还有一个复杂一点的方法是使用Buffer可以嵌套下一层Buffer的BufferStack。类似
还有一个更复杂的方法就是移动数据流视图时给每层都复制一遍,同上也是完全替换。
最后刚才说,Binarie 肯定不会区别什么 SingleMarkRest/MarkReset,因为二进制模式基本都是很简单的,不需要嵌套+预取式读取(而且那么做内存利用效率上可能存在严重问题,即便优化也比较难以实现得好看,所以都是按照原平台的方式实现)。
ParserKt 在支持类似 REPL 这样的目标时(『回车执行』『Tab 补全』什么的其实都是应该用 SyntaxTreeListener 之类的实现,此外绝句支持 partial 解析(也就是采取『镇静策略』兼容输入的一些错漏),所以不存在 Tab 不能用的问题。)就可以利用递归下降解析组合子的便利性,不需要修改任何代码了。
[1,2,3]假设这是一个利用索引(也就是一个简单的 Index)MarkReset 的东西,同时也可以完成这样的事:
mark()
next() //1
next() //2
reset()
next() //1
1,2,3
mark() //[0]
mark() //[0,0]
next() //1
next() //2
reset() //pos=0, [0]
next() // 1
reset() //pos=0, [0]
next() //1
可是如果直接在 1,2,3 流里,每次 mark 去 push 上一层 buffer,然后 reset 的时候 pop 再加进当前 reset buffer(当然必须 insertAllAt(0) 或者干脆 reset buffer: Stack+pushAll reversed (a),因为 mark/reset 是按『后进先出』的),这样的方式来实现 MarkReset,会导致 reset buffer 本身不可 reset 的问题:
(a): 或者把记录用buffer也做成stack的LIFO(仅)样子
1,2,3
mark() //[]
mark() //[] []
next() //1, [][1]
next() //2, [][1,2]
reset() //[]
next() // 1
reset() //
next() //2 <- wrong 解决方法之一就是即便在 reset 后依然往(如果BufferStack不空)里面加东西。
还有一个复杂一点的方法是使用Buffer可以嵌套下一层Buffer的BufferStack。类似
[1, [2, 3]] [2, 3] 这样,不过就需要每次 reset 完全替换或者说清空原 buffer。还有一个更复杂的方法就是移动数据流视图时给每层都复制一遍,同上也是完全替换。
最后刚才说,Binarie 肯定不会区别什么 SingleMarkRest/MarkReset,因为二进制模式基本都是很简单的,不需要嵌套+预取式读取(而且那么做内存利用效率上可能存在严重问题,即便优化也比较难以实现得好看,所以都是按照原平台的方式实现)。
ParserKt 在支持类似 REPL 这样的目标时(『回车执行』『Tab 补全』什么的其实都是应该用 SyntaxTreeListener 之类的实现,此外绝句支持 partial 解析(也就是采取『镇静策略』兼容输入的一些错漏),所以不存在 Tab 不能用的问题。)就可以利用递归下降解析组合子的便利性,不需要修改任何代码了。
duangsuse::Echo
import java.nio.ByteOrder as NioByteOrder typealias Cnt = Int typealias Idx = Int typealias IdxRange = IntRange typealias Buffer = ByteArray infix fun IdxRange.untilSize(size: Cnt): IdxRange = this until (this+size) //0 until (0+10): 0..9 inline val IdxRange.size:…
Reader 可以是跨平台的,我去看看 Kotlin stdlib 的 io 包
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/index.html
……
还好Kotlin没有多做封装,kotlin.io 只有JVM的定义,要不然我的封装就没有意义了。
……
https://kotlinlang.org/api/latest/jvm/stdlib/org.w3c.files/-blob/index.html
这是我们的『InputStream』
(JS平台需要不一样的这个东西,所有平台提供同一个 Reader/Writer 但无法统一它造于什么东西)
https://kotlinlang.org/api/latest/jvm/stdlib/org.w3c.files/-file-reader/index.html
需要这个东西来从用户文件提供
https://kotlinlang.org/api/latest/jvm/stdlib/org.khronos.webgl/-array-buffer/index.html
https://kotlinlang.org/api/latest/jvm/stdlib/org.khronos.webgl/-data-view/index.html
这个是重头戏,但没有 readLong,只有 JVM 平台有……
看来Common的定义只能缩水了?
但是,全部平台都有
以及 Seq, Repeat, Cond 解析器,和 little, big; int8, int16,... 这些子结构
一时间支持 JVM 和 JS,Native 不能立刻支持。
其实 ByteReader 就是我们对 InputStream 的抽象的……
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/index.html
……
还好Kotlin没有多做封装,kotlin.io 只有JVM的定义,要不然我的封装就没有意义了。
……
https://kotlinlang.org/api/latest/jvm/stdlib/org.w3c.files/-blob/index.html
这是我们的『InputStream』
(JS平台需要不一样的这个东西,所有平台提供同一个 Reader/Writer 但无法统一它造于什么东西)
https://kotlinlang.org/api/latest/jvm/stdlib/org.w3c.files/-file-reader/index.html
fun readAsArrayBuffer(blob: Blob) 需要这个东西来从用户文件提供
ArrayBuffer https://kotlinlang.org/api/latest/jvm/stdlib/org.khronos.webgl/-array-buffer/index.html
ArrayBuffer(length: Int)需要这个东西来弄 InMemoryWriter 的 constructor
https://kotlinlang.org/api/latest/jvm/stdlib/org.khronos.webgl/-data-view/index.html
这个是重头戏,但没有 readLong,只有 JVM 平台有……
fun getUint32(
byteOffset: Int,
littleEndian: Boolean = definedExternally
): Int
看来Common的定义只能缩水了?
但是,全部平台都有
interface BinPattern<ST> {
fun read(reader: Reader): ST
fun write(writer: Writer, data: ST)
val byteSize: Cnt?
}
abstract class Tuple<E>(override val size: Cnt, initial: E): Sized {
private val storage = Array(size) {E}
operator fun get(index: Idx): E = storage[index]
operator fun set(index: Idx, value: E) { storage[index] = value }
data class Index<T: Any>(val index: Idx) {
@Suppress("UNCHECKED_CAST")
operator fun getValue(self: Tuple, _p: KProperty<*>) = self[index] as T
operator fun setValue(self: Tuple, _p: KProperty<*>, value: T) { self[index] = value }
}
protected fun <T> index(no: Idx): Index<T> = Index(no)
fun toString(limit: Cnt): String = "Tuple(${xs.joinToString("|", limit = limit)})"
}
operator fun <E> Tuple<E>.component1() = this[0]
operator fun <E> Tuple<E>.component2() = this[1]
operator fun <E> Tuple<E>.component3() = this[2]
operator fun <E> Tuple<E>.component4() = this[3] 以及 Seq, Repeat, Cond 解析器,和 little, big; int8, int16,... 这些子结构
一时间支持 JVM 和 JS,Native 不能立刻支持。
其实 ByteReader 就是我们对 InputStream 的抽象的……
Kotlin
kotlin.io - Kotlin Programming Language