/tmp/duangsuse.sock
23 subscribers
303 photos
3 videos
92 files
337 links
从 duangsuse::Echo (@dsuse) 跟进出来的分支,将在作者恢复原帐号访问的时候合并删除。
Download Telegram
/tmp/duangsuse.sock
今天晚上,我还会完成文法布局的 Pattern 编写 可以认为,ParserKt 现在对 read-only pattern 和序列 validate 的支持已经比较完备了 对于文法布局的支持应该会像对 infix chain 的一样,不会有问题
不是特别顺利,对级联收尾的理解有偏差
之前的知识是,不能用异常。但现在我也看了 Pattern<IN, Tuple2<List<T>, Int>>,那个方案不可行

ParserKt 是 one-pass 的解析器,绝对没有 MarkReset 的机会,所以对布局解析器来说,

h1
h2
h3
h3
h1

这里面最后一个 h1 的位置,实际上调用栈最顶端的最后一个 h3 负责读取它,但如果读取消耗了,解析来的 h2 就又不知道往哪里关了。
(如果支持 mark/reset 的话,只要预取 indent 判等后决定是否消耗即可,其他情况都是输入序列错误)

所以说每次要收尾所有 > indent 的层次,然后才能实现这个解析器。
这一点也不说特别难,但 ParserKt 里不是很好解决,因为我们的设计是
function where 像这个这个 where 是我们放这个 pattern 的地方
而且它不仅仅要做到级联,还不能暴露出框架的流结构的这个 one-pass……
我希望不要把它做成一个 abstract class,简单一点,不能让它管理这个递归的 nesting tree 数据结构,要不然至少对用户会很麻烦。

现在好像是只能用异常了,因为它就是一个 Pattern,可以被任何其他 pattern 使用…… 要做到级联收尾必须这么做,而且这么做我们就可以用上 FoldPattern 的 API,更规范一些

如何 show 这又是另外一个问题,不过我现在的意见是,无法支持,因为布局的输出,只能存那么一点信息(没法多存布局的信息进去,顶多可能被扩展嵌套结构,但就不是我们的事了),的确没法弄好,Pattern 的使用是动态的。
/tmp/duangsuse.sock
不是特别顺利,对级联收尾的理解有偏差 之前的知识是,不能用异常。但现在我也看了 Pattern<IN, Tuple2<List<T>, Int>>,那个方案不可行 ParserKt 是 one-pass 的解析器,绝对没有 MarkReset 的机会,所以对布局解析器来说, h1 h2 h3 h3 h1 这里面最后一个 h1 的位置,实际上调用栈最顶端的最后一个 h3 负责读取它,但如果读取消耗了,解析来的 h2 就又不知道往哪里关了。 (如果支持 mark/reset 的话,只要预取…
大意就是,除了异常以外没有办法在两层 LayoutPattern.read 之间传递控制权,因为使用处是不确定的
除非使用 abstract class 硬性建模何时开启新 pattern,否则这个信息没法通过返回值传递出去,即便能手写起来复杂性也不可接受。

LayoutPattern 注定是递归结构,所以 caller 必须去 handle 它的 closing indent level 返回值,对应用来说那必须手写模板代码,我觉得比起那样还是异常靠谱一些(虽然不可能有泛型,要强制转换了……)

这个和 infix pattern 不一样,它毕竟得是一个 unstable feature……
现在这么实现最主要的问题是得有一个 level 0,不能让异常漏处 Pattern 模型的范畴……

好像不必了,因为每层都是 if (baseLevel > indent) return reducer.finish() 的嘛
#China #freedom 😢休了三天假,发现 CloudHammer 的端口变了,换了个 endpoint,又可以用了
Forwarded from Deleted Account
比如说解析一个 2D 布局的列表:
[] where
abcs
123s
[] where
winnie
donkey

具体的架构 很难说明白
但是异常一抛,调用 Layout read 的子解析器的 collect 过程就会被打断,最后 abnormal terminate 什么都不能返回
Forwarded from Deleted Account
我知道,现在还是 one-pass 的,我决定还是用另外一种不依赖外部递归,直接把 nesting tree 和 visitor 做到框架里支持的另一种方法
Forwarded from Deleted Account
直接在内部做好递归解析的问题,不依赖外部了,然后 layout 的开启就分
item@(function somefn) tail@(where)
...children
item tail children 三个来保证,直接在框架里递归解析,然后收集结果也是在框架层做、用户用 Visitor 去翻译到目标 AST
Forwarded from iseki
下午的时候我又被怼了😢
Forwarded from Deleted Account
好可怜呦
可怜之人必有可恨之处
Forwarded from Deleted Account
嘛,说着玩玩,iseki 不要伤心
Forwarded from Deleted Account
被dalao怼是很平常的事情,不必记在心上,该干啥干啥
Forwarded from Deleted Account
你造么,这是我当年在本地最好的初中上学的时候班主任对我说的话。
Forwarded from Deleted Account
现在把它送给你
Forwarded from Deleted Account
最后祝你 身体健康
Forwarded from Deleted Account
标题我都想好了,《地区头校班主任对学生说了这么一句话,竟改变了他的一生!
Forwarded from Deleted Account
哈哈哈哈哈哈 闹着玩的,我又不做媒体
Forwarded from Deleted Account
既然 iseki 都被大佬喷了,那我就在这里直播 y=1; x=y=z 的 unify 过程 #PLT

首先说说我们的目标是求得 x=1; y=1; z=1,使用的方法是 unification —— 利用相等关系,让两个 Value(Val/Var) 在一个 State 里实际上划上等号

而一个 Var 呢,我们可以认为是一个 "Symbol",它的 equals 实现为全等 (x === y),就可以了。

microKanren 有 six primitives: State, Variable, fresh(introduce), Eq, Either, Both
前三个是最基础的 unification 需求,后三个是关系式编程(relational programming) 里最重要的关系

毕竟是在 Telegram 直接写了,我就不说 Either 和 Both 这种高级操作了(它们能 satisfyIn 的 state 都可能不只一个)

fun main(vararg args: String) {
val xyz = State()
xyz.intro("x", "y", "z") {
val (x, y, z) = it
y.eq(Val(1))
x.eq(y); y.eq(z)
}
println(xyz) //State{x: 1, y: 1, z: 1}
}

在 Kotlin 里面以 EDSL 的风格 去完成……
首先我们依赖的需要知道啥东西能够 unify 又怎么去 unify,或者说我们得对 Value 的子类型实现 unifyIn(state, other) 操作

我们知道相等关系是有对称性(symmetric) 的 (x=y, y=x),所以“解构”式的操作只需要有一边定义就 OK 了,然后因为 Kotlin 是强类型的可以加入类型检查。

typealias Consumer<T> = (T) -> Unit
typealias MonoTriple<T> = Triple<T, T, T>
typealias MonoPair<T> = Pair<T, T>

typealias StateMap = MutableMap<Value.Var, Any?>
typealias Variable = Value.Var

class State(private val map: StateMap = mutableMapOf()): StateMap by map {
fun intro(x1: String, x2: Sting, op: Consumer<MonoPair<Variable>>) {
val xs = bind(x1, x2)
op(Pair(xs[0], xs[1]))
}
fun intro(x1: String, x2: String, x3: String, op: Consumer<MonoTriple<Variable>>) {
val xs = bind(x1, x2, x3)
op(Triple(xs[0], xs[1], xs[2]))
}
fun bind(vararg names: String): List<Value.Var> {
val variables = names.map(::Variable)
for (variables
return variables
}
override fun toString() = "State$map"
}

interface Unifible<T> {
fun unifyIn(state: State, other: Unifible<T>)
}

sealed class Value(open val value: Any?) {
data class Val(value: Any?): Value(value) {
override fun toString() = "Val($value)"
}
data class Var(val name: String, val binding: State) {
override fun equals(other: Any?) = this === other
override fun hashCode() = super.hashCode()
override fun toString() = "Var($name)"
}
}

艹我写不下去了,太长了
Forwarded from Deleted Account
具体怎么实现 unify 以及 unify 的对称性的代码复用留给 iseki 大佬自己研究去吧,我重写我的 ParserKt 去了……