duangsuse 2020-03-12 18:31:39
@定理证明器 不过说起来,ANTLR 4 是无法处理 Layout 和 non-CFG 的,ParserKt 可以用 LayoutPattern 直接支持,如果觉得有什么建议可以看看 https://github.com/ParserKt/examples/blob/master/extendedSyntax/src/commonMain/kotlin/LayoutInts.kt
此外,NumUnitPattern 可以在三行内定义 1min30s 这种数值单位格式的读取和显示,不过我写过有趣点的操作是读取汉字数值
(并且顺带写了个同时支持汉字和阿拉伯数字的计算器REPL)
https://github.com/ParserKt/examples/tree/master/hanCalc/src/commonMain/kotlin
ParserKt 本质上感觉是序列模式匹配(解析状态化文法的能力是与生俱来的),而不止是字符流(虽然 ANTLR 也有吹自己能处理二进制格式,不过我觉得对所有解析器实现这都是高射炮打蚊子,emmm)
超高校级的门卫 2020-03-12 19:03:46
parser = 序列模式匹配
超高校级的门卫 2020-03-12 19:05:28
你们怎么都这么喜欢scannerless
超高校级的门卫 2020-03-12 19:06:46
似乎和我当年一样,是一个parserc
超高校级的门卫 2020-03-12 19:06:59
parsec enhanced
超高校级的门卫 2020-03-12 19:07:06
好的,我认可了。
超高校级的门卫 2020-03-12 19:07:38
这个表达力很强,但是性能呢
超高校级的门卫 2020-03-12 19:09:11
我的意见啊,non-CFG,有个回溯,非常简单。以及你有做左递归处理吗?有做分支合并之类的优化嘛?
超高校级的门卫 2020-03-12 19:15:36
antlr已是历史,是成型的,已知会被淘汰的"现在的临时的技术"。你和它比就算你是它的闭包也没有意义,人们只会用antlr是因为技术潮流迭代是比较缓慢的。
你要比的话,业界你至少也得和各方面最好的比。nonCFG你可以去研究它的性能优化
duangsuse 2020-03-12 19:31:22
@超高校级的门卫 感谢大佬指点(`・ω・´)ノ
duangsuse 2020-03-12 19:36:07
差不多是这样,ParserKt 和少部分 parser combinator 一样会提供从输入到解析结果的数据表示管理(而不仅仅是到 List 什么的),比如 Repeat 会被 Fold asString() asList() 甚至 asInt() asLong() asMap() 什么的parse = extract data from sequence = transform inputs into simpler form
超高校级的门卫 2020-03-12 19:37:33
parse会把flatten的序列变成结构化序列
超高校级的门卫 2020-03-12 19:37:54
asInt这种叫做action/rewrite
duangsuse 2020-03-12 19:39:34
Feed 是一个非常简单的模型,只有 peek 和 comsume()我实现了 SliceFeed 和 StreamFeed,前者用于 CbarSequence, List 什么的,后者用于 InputStream 等整个解析过程都不需要 if hasNext,我用的是 Python 式异常如果要吐槽,我觉得该喷 incremental parsing 和 multi thread、bulk processing(而不是一次一字符) 啥的
duangsuse 2020-03-12 19:40:46
是的,我把 Iterable.fold 提升了一个层次,变成 interface Fold
所以它就可以在折叠过程中保存一个状态了
超高校级的门卫 2020-03-12 19:40:46
我没喷
duangsuse 2020-03-12 19:41:01
(我是说,如果要的话
今泉影狼 2020-03-12 19:41:30
我就负责表情包制作
超高校级的门卫 2020-03-12 19:41:48
你说的话里太多的东西都是和你的project相关的
超高校级的门卫 2020-03-12 19:42:25
你能不能找到相关知识具体的专业术语对应呢?
超高校级的门卫 2020-03-12 19:43:03
如果你这样下去,退一万步即使你很厉害无人能及,走的再深也没人会care
超高校级的门卫 2020-03-12 19:43:52
在折叠的过程中保持状态并非是你做的第一次尝试
超高校级的门卫 2020-03-12 19:44:45
存在大量的parsing工具可以maintain 一个global的context,乃至针对每个production的local context
duangsuse 2020-03-12 19:44:46
没有(>﹏<),毕竟我觉得,既然都是 parserc 了,编程者自己要负责代码质量我举个最简单的例子, (anyChar and !item(wtf)) 实际上就是 !item(wtf)但即便去掉 and,实际上 SatisfyPattern.not 里也是多包了一层光从 instance 创建性能上谈,是不利的但是这个框架的代码质量也很重要啊…… 不可能为了一切可能的优化都 多写逻辑吧( •̥́ ˍ •̀ )
超高校级的门卫 2020-03-12 19:46:19
我早期写的所有parser框架几乎都有state maintain。但现在我内心实话觉得这些就是菜逼,没用,我自己都不会用。我只会用最快的,写的快,跑的快,debug快
duangsuse 2020-03-12 19:46:26
这个东西其实一半是自用,现在还打算继续重构另外我本该学那些,但后来我发现…… 大佬们太厉害了索性就做些小白都能看懂的东西,跟随 Kotlin 的步伐,别用太多术语和高深抽象的概念。
超高校级的门卫 2020-03-12 19:48:28
很多的优化人写出来都会很难看的。况且没有左递归的话,其实你的表达力非常的有限
duangsuse 2020-03-12 19:49:43
半个月的编写过程里我甚至没用 IDEA(旧电脑性能渣)
还是比较看重代码可读性的,每个部分都有注释提纲。
内联文档当然还是少些好,如果名字和定义的顺序本身就可以表示些什么…… 我干脆一点文档都没写
超高校级的门卫 2020-03-12 19:50:16
你这话别人读起来是有点反智的。你这个项目的progress是不差的,但是我想说你这里做的东西,只是parsec框架实现上很简单的事情。不考虑左递归,很多人可以在数小时乃至数十分钟内写出相差无几的框架。
duangsuse 2020-03-12 19:50:58
@超高校级的门卫 所以我有更“高性能”的 InfixPattern而且我考虑过左递归,在 Feed/Pattern 模型里是完全没问题的,虽然现在我懒得实现了……
超高校级的门卫 2020-03-12 19:51:22
你确定完全没问题?要不要试一下
duangsuse 2020-03-12 19:51:48
我想,问题不在于你花多短时间,在于别人可以节省多少时间和输出代码体积……
duangsuse 2020-03-12 19:52:09

超高校级的门卫 2020-03-12 19:52:21
是的,那我说,别人写的框架用起来还可以比你简洁
超高校级的门卫 2020-03-12 19:52:48
你看过fastparse嘛?
超高校级的门卫 2020-03-12 19:53:07
你知道bnf嘛? parser gen知道吗?
duangsuse 2020-03-12 19:53:08
聪明是好事,可是我是个愚钝的人呢……
所以我只能把有限的智慧,放在优化别人的理解和使用上
超高校级的门卫 2020-03-12 19:53:32
就我看来,你的框架用起来代码特别多
duangsuse 2020-03-12 19:53:47
的确的,但除了简洁,易读也是相当重要的呢
超高校级的门卫 2020-03-12 19:54:29
我以前也和人说过你这样的观点,最终应该是消除冗余的信息,利用(e)dsl
超高校级的门卫 2020-03-12 19:54:49
现在问题来了,简洁,性能,可读性
duangsuse 2020-03-12 19:54:56
定义有结构层次,不滥用语言特性
就像 SurroundBy(clamly(parens), wtf)
会比 wtf surroundBy parens.clamly() 好看一样
超高校级的门卫 2020-03-12 19:55:13
三者,你的评估规则是什么?
超高校级的门卫 2020-03-12 19:55:57
这个例子我认同,过分使用语言特性是不利的
duangsuse 2020-03-12 19:56:15
都很重要如果一定要舍鱼取熊掌,我选可读性,因为程序灵魂的表达才是核心。
超高校级的门卫 2020-03-12 19:56:54
但edsl对相当一部分人,远没有dsl的可读性
超高校级的门卫 2020-03-12 19:57:00
别人会使用bnf
duangsuse 2020-03-12 1
@定理证明器 不过说起来,ANTLR 4 是无法处理 Layout 和 non-CFG 的,ParserKt 可以用 LayoutPattern 直接支持,如果觉得有什么建议可以看看 https://github.com/ParserKt/examples/blob/master/extendedSyntax/src/commonMain/kotlin/LayoutInts.kt
此外,NumUnitPattern 可以在三行内定义 1min30s 这种数值单位格式的读取和显示,不过我写过有趣点的操作是读取汉字数值
(并且顺带写了个同时支持汉字和阿拉伯数字的计算器REPL)
https://github.com/ParserKt/examples/tree/master/hanCalc/src/commonMain/kotlin
ParserKt 本质上感觉是序列模式匹配(解析状态化文法的能力是与生俱来的),而不止是字符流(虽然 ANTLR 也有吹自己能处理二进制格式,不过我觉得对所有解析器实现这都是高射炮打蚊子,emmm)
超高校级的门卫 2020-03-12 19:03:46
parser = 序列模式匹配
超高校级的门卫 2020-03-12 19:05:28
你们怎么都这么喜欢scannerless
超高校级的门卫 2020-03-12 19:06:46
似乎和我当年一样,是一个parserc
超高校级的门卫 2020-03-12 19:06:59
parsec enhanced
超高校级的门卫 2020-03-12 19:07:06
好的,我认可了。
超高校级的门卫 2020-03-12 19:07:38
这个表达力很强,但是性能呢
超高校级的门卫 2020-03-12 19:09:11
我的意见啊,non-CFG,有个回溯,非常简单。以及你有做左递归处理吗?有做分支合并之类的优化嘛?
超高校级的门卫 2020-03-12 19:15:36
antlr已是历史,是成型的,已知会被淘汰的"现在的临时的技术"。你和它比就算你是它的闭包也没有意义,人们只会用antlr是因为技术潮流迭代是比较缓慢的。
你要比的话,业界你至少也得和各方面最好的比。nonCFG你可以去研究它的性能优化
duangsuse 2020-03-12 19:31:22
@超高校级的门卫 感谢大佬指点(`・ω・´)ノ
duangsuse 2020-03-12 19:36:07
差不多是这样,ParserKt 和少部分 parser combinator 一样会提供从输入到解析结果的数据表示管理(而不仅仅是到 List 什么的),比如 Repeat 会被 Fold asString() asList() 甚至 asInt() asLong() asMap() 什么的parse = extract data from sequence = transform inputs into simpler form
超高校级的门卫 2020-03-12 19:37:33
parse会把flatten的序列变成结构化序列
超高校级的门卫 2020-03-12 19:37:54
asInt这种叫做action/rewrite
duangsuse 2020-03-12 19:39:34
Feed 是一个非常简单的模型,只有 peek 和 comsume()我实现了 SliceFeed 和 StreamFeed,前者用于 CbarSequence, List 什么的,后者用于 InputStream 等整个解析过程都不需要 if hasNext,我用的是 Python 式异常如果要吐槽,我觉得该喷 incremental parsing 和 multi thread、bulk processing(而不是一次一字符) 啥的
duangsuse 2020-03-12 19:40:46
是的,我把 Iterable.fold 提升了一个层次,变成 interface Fold
所以它就可以在折叠过程中保存一个状态了
超高校级的门卫 2020-03-12 19:40:46
我没喷
duangsuse 2020-03-12 19:41:01
(我是说,如果要的话
今泉影狼 2020-03-12 19:41:30
我就负责表情包制作
超高校级的门卫 2020-03-12 19:41:48
你说的话里太多的东西都是和你的project相关的
超高校级的门卫 2020-03-12 19:42:25
你能不能找到相关知识具体的专业术语对应呢?
超高校级的门卫 2020-03-12 19:43:03
如果你这样下去,退一万步即使你很厉害无人能及,走的再深也没人会care
超高校级的门卫 2020-03-12 19:43:52
在折叠的过程中保持状态并非是你做的第一次尝试
超高校级的门卫 2020-03-12 19:44:45
存在大量的parsing工具可以maintain 一个global的context,乃至针对每个production的local context
duangsuse 2020-03-12 19:44:46
没有(>﹏<),毕竟我觉得,既然都是 parserc 了,编程者自己要负责代码质量我举个最简单的例子, (anyChar and !item(wtf)) 实际上就是 !item(wtf)但即便去掉 and,实际上 SatisfyPattern.not 里也是多包了一层光从 instance 创建性能上谈,是不利的但是这个框架的代码质量也很重要啊…… 不可能为了一切可能的优化都 多写逻辑吧( •̥́ ˍ •̀ )
超高校级的门卫 2020-03-12 19:46:19
我早期写的所有parser框架几乎都有state maintain。但现在我内心实话觉得这些就是菜逼,没用,我自己都不会用。我只会用最快的,写的快,跑的快,debug快
duangsuse 2020-03-12 19:46:26
这个东西其实一半是自用,现在还打算继续重构另外我本该学那些,但后来我发现…… 大佬们太厉害了索性就做些小白都能看懂的东西,跟随 Kotlin 的步伐,别用太多术语和高深抽象的概念。
超高校级的门卫 2020-03-12 19:48:28
很多的优化人写出来都会很难看的。况且没有左递归的话,其实你的表达力非常的有限
duangsuse 2020-03-12 19:49:43
半个月的编写过程里我甚至没用 IDEA(旧电脑性能渣)
还是比较看重代码可读性的,每个部分都有注释提纲。
内联文档当然还是少些好,如果名字和定义的顺序本身就可以表示些什么…… 我干脆一点文档都没写
超高校级的门卫 2020-03-12 19:50:16
你这话别人读起来是有点反智的。你这个项目的progress是不差的,但是我想说你这里做的东西,只是parsec框架实现上很简单的事情。不考虑左递归,很多人可以在数小时乃至数十分钟内写出相差无几的框架。
duangsuse 2020-03-12 19:50:58
@超高校级的门卫 所以我有更“高性能”的 InfixPattern而且我考虑过左递归,在 Feed/Pattern 模型里是完全没问题的,虽然现在我懒得实现了……
超高校级的门卫 2020-03-12 19:51:22
你确定完全没问题?要不要试一下
duangsuse 2020-03-12 19:51:48
我想,问题不在于你花多短时间,在于别人可以节省多少时间和输出代码体积……
duangsuse 2020-03-12 19:52:09

超高校级的门卫 2020-03-12 19:52:21
是的,那我说,别人写的框架用起来还可以比你简洁
超高校级的门卫 2020-03-12 19:52:48
你看过fastparse嘛?
超高校级的门卫 2020-03-12 19:53:07
你知道bnf嘛? parser gen知道吗?
duangsuse 2020-03-12 19:53:08
聪明是好事,可是我是个愚钝的人呢……
所以我只能把有限的智慧,放在优化别人的理解和使用上
超高校级的门卫 2020-03-12 19:53:32
就我看来,你的框架用起来代码特别多
duangsuse 2020-03-12 19:53:47
的确的,但除了简洁,易读也是相当重要的呢
超高校级的门卫 2020-03-12 19:54:29
我以前也和人说过你这样的观点,最终应该是消除冗余的信息,利用(e)dsl
超高校级的门卫 2020-03-12 19:54:49
现在问题来了,简洁,性能,可读性
duangsuse 2020-03-12 19:54:56
定义有结构层次,不滥用语言特性
就像 SurroundBy(clamly(parens), wtf)
会比 wtf surroundBy parens.clamly() 好看一样
超高校级的门卫 2020-03-12 19:55:13
三者,你的评估规则是什么?
超高校级的门卫 2020-03-12 19:55:57
这个例子我认同,过分使用语言特性是不利的
duangsuse 2020-03-12 19:56:15
都很重要如果一定要舍鱼取熊掌,我选可读性,因为程序灵魂的表达才是核心。
超高校级的门卫 2020-03-12 19:56:54
但edsl对相当一部分人,远没有dsl的可读性
超高校级的门卫 2020-03-12 19:57:00
别人会使用bnf
duangsuse 2020-03-12 1
GitHub
ParserKt/examples
Example parsers for the ParserKt library. Contribute to ParserKt/examples development by creating an account on GitHub.
9:57:35
简洁就是把自然语言变成数学,首先它就不是 Kotlin 的选择
性能是要看 profile 的,而且我相信足够的抽象反而可以在未来带来更好的性能
超高校级的门卫 2020-03-12 19:57:48
别人甚至会讨厌你提供surrounded by这样的组合子
duangsuse 2020-03-12 19:58:23
ParserKt 也有一门 "bnf" DSL 已经设计,还没时间实现
超高校级的门卫 2020-03-12 19:58:42
你如果能把性能优化作为重点,那也是可以的。parsec唯一的优点是类型安全,而其上的优化有大量文章可做
超高校级的门卫 2020-03-12 20:01:38
parsec没有优化的话,中型的parser,比如json这些比LR/LL codegen慢个几千倍不是很难
超高校级的门卫 2020-03-12 20:02:14
常见编程语言的parsing就要更慢了
超高校级的门卫 2020-03-12 20:03:20
https://github.com/lihaoyi/fastparse/blob/master/README.md
超高校级的门卫 2020-03-12 20:03:36
你可以先比一下
超高校级的门卫 2020-03-12 20:03:44
找出你有哪些优点
超高校级的门卫 2020-03-12 20:03:58
他作为一个标杆,是比较菜的
收藏于昨天 群-迂腐的学院派编译技术
#qq #PLT
简洁就是把自然语言变成数学,首先它就不是 Kotlin 的选择
性能是要看 profile 的,而且我相信足够的抽象反而可以在未来带来更好的性能
超高校级的门卫 2020-03-12 19:57:48
别人甚至会讨厌你提供surrounded by这样的组合子
duangsuse 2020-03-12 19:58:23
ParserKt 也有一门 "bnf" DSL 已经设计,还没时间实现
超高校级的门卫 2020-03-12 19:58:42
你如果能把性能优化作为重点,那也是可以的。parsec唯一的优点是类型安全,而其上的优化有大量文章可做
超高校级的门卫 2020-03-12 20:01:38
parsec没有优化的话,中型的parser,比如json这些比LR/LL codegen慢个几千倍不是很难
超高校级的门卫 2020-03-12 20:02:14
常见编程语言的parsing就要更慢了
超高校级的门卫 2020-03-12 20:03:20
https://github.com/lihaoyi/fastparse/blob/master/README.md
超高校级的门卫 2020-03-12 20:03:36
你可以先比一下
超高校级的门卫 2020-03-12 20:03:44
找出你有哪些优点
超高校级的门卫 2020-03-12 20:03:58
他作为一个标杆,是比较菜的
收藏于昨天 群-迂腐的学院派编译技术
#qq #PLT
GitHub
lihaoyi/fastparse
Writing Fast Parsers Fast in Scala. Contribute to lihaoyi/fastparse development by creating an account on GitHub.
超高校级的门卫 2020-03-12 20:04:52
你能作为"有特色"的框架去beat标杆的某些方面,或者成为这个标杆的闭包
duangsuse 2020-03-12 20:07:22
@超高校级的门卫 我也去看过不少同类框架。
他们也的确是“相差无几”,但就我个人来看,他们唯一差的就是,太聪明了…… 太学术了……
比如 https://github.com/h0tk3y/better-parse,它是用了很多很厉害的技术(e.g. codegen),但不是很工程,而且容易被滥用一些 combinator 的 infix notation
不忘掉 BNF 那套繁琐的 terminal / non-terminal 术语,不摒弃以往 scannerless parser框架 的实现模式,怎么可能弄出 ParserKt 这种泛向的框架的说(≧ω≦)
duangsuse 2020-03-12 20:08:21
下次重构后去跑分!现在还在各种优化接口……
超高校级的门卫 2020-03-12 20:09:26
bnf和scannerless不冲突
超高校级的门卫 2020-03-12 20:09:38
你的泛向在哪里
duangsuse 2020-03-12 20:09:46
泛型解析。
超高校级的门卫 2020-03-12 20:10:09
你举例子
duangsuse 2020-03-12 20:10:14
// Generic parsing for [1, a, b] where (b > a) val ints = Seq(::IntTuple, item(1), *Contextual(item<Int>()) { i -> satisfy<Int> { it > i } }.flatten().items() ) ints.rebuild(1,2,3) //[1, 2, 3] ints.rebuild(1,2,1) //notParsed i.rebuild(1,0,1) //[1, 0, 1]
超高校级的门卫 2020-03-12 20:11:47
哪里泛型了?
duangsuse 2020-03-12 20:12:00
https://github.com/ParserKt/ParserKt/blob/master/README.md#introduction
就是这里的代码示例
超高校级的门卫 2020-03-12 20:12:02
这是parsec都能做到的
超高校级的门卫 2020-03-12 20:12:10
你无非做了一个constraint
duangsuse 2020-03-12 20:12:13
输入是 Int
超高校级的门卫 2020-03-12 20:12:25
这不是什么问题
超高校级的门卫 2020-03-12 20:12:36
haskell parsec是母版
超高校级的门卫 2020-03-12 20:12:44
token是泛型的
duangsuse 2020-03-12 20:13:01
可是我见过所有的 Kotlin parserc 都不能 (^ν^)
duangsuse 2020-03-12 20:13:23
而且 Haskell 的 parserc 谈不了性能
超高校级的门卫 2020-03-12 20:13:53
haskell是一个相当快速的语言,你应该多做benchmark
duangsuse 2020-03-12 20:14:08
到处 shallow copy 的 product value mapping 是很难做到服务端的性能要求的
duangsuse 2020-03-12 20:14:43
GHC Haskell 的性能往往要靠特别的优化
超高校级的门卫 2020-03-12 20:14:49
我一直觉得发生shallow copy的是非pure语言使用list的时候
超高校级的门卫 2020-03-12 20:14:59
而haskell整好避免这一点
duangsuse 2020-03-12 20:15:51
而且 Kotlin 是内部支持 imperative 的语言呢,Haskell 是另外的世界
超高校级的门卫 2020-03-12 20:16:21
如果事实如此,那确实是挺不错的。@定理证明器 当年好像没把我的库移植过去完,不然也是个token type可变的
duangsuse 2020-03-12 20:17:31
不过这个里面有不少点子都是我自己想出来的比如 Feed/Pattern (可 read 可 show) 还有 clam, clamWhile, alsoDo, stateAs 什么的
超高校级的门卫 2020-03-12 20:17:37
不过我当年第一个parsing尝试就是在非传统token的type上做的,写完就有人说太naive。我认为不太容易获得认同
超高校级的门卫 2020-03-12 20:17:55
别人看会觉得挺复杂的
超高校级的门卫 2020-03-12 20:18:30
我以前也搞很多新东西,后面发现无非是一个user define的parsec函数
超高校级的门卫 2020-03-12 20:18:57
我对我以前的评价就是,做出了parsec的左递归支持,牛逼。别的,垃圾,闭门造车。
duangsuse 2020-03-12 20:20:58
From big power comes big responsibility比如说,PKT 里 SurroundBy(clamly(parens), stringFor(anyChar)) 你可以在错误提示里获得开括号的 sourceLoc (前提是 input 必须包含 ExpectClose 实例的状态)而手写是这种做法的…… “无结构”写法ANTLR?它做不到,因为它不知道什么是 paired Pattern
超高校级的门卫 2020-03-12 20:23:09
有意思,你可以讲一些你这个开括号错误提示比antlr强在哪儿
超高校级的门卫 2020-03-12 20:23:43
(xxx你会提示(的loc而不是最后一个x的loc?
duangsuse 2020-03-12 20:25:15
不过 SatisfyPattern.clam 和 Pattetn.clamWhile 也的确是受启发的
就是编译原理所谓的“镇静解析策略”
ParserKt 里的 Pattern, read 成功就是 T, 失败了就是 null (notParsed)
所以,clamWhile(pat, defaultValue, messager) 可以提供一个可定制的出错提示
我尽可能把 parserc 在语言可以表达的逻辑的集成方面的优势用到了…… 就那样吧
超高校级的门卫 2020-03-12 20:25:49
这是user define的行为
超高校级的门卫 2020-03-12 20:26:13
用户会选择自己写一个这个功能,而不是记忆你的api
duangsuse 2020-03-12 20:26:57
就像 Java 8 的 obj.someCall()它的 NPE 不会提示 null 的东西是 obj。ParserKt 可以在找不到闭括号的前提下显示expecting ')' (from file:line:column)
超高校级的门卫 2020-03-12 20:28:04
你确定antlr做不到?我认为LL和LR都应该有这个能力,除非parser的失败是在内部的rule
超高校级的门卫 2020-03-12 20:28:29
而内部rule失败,报出外部还没遇到的错误也不太合理
duangsuse 2020-03-12 20:28:42
不过这个错误提示也的确是可定制的相关代码在这里:https://github.com/ParserKt/ParserKt/blob/master/parserkt-ext/src/commonMain/kotlin/org/parserkt/pat/ext/MiscHelper.kt#L48
超高校级的门卫 2020-03-12 20:29:04
这哪个parsec都都可定制
duangsuse 2020-03-12 20:29:16
不确定,但是它不会知道“() 是配对的两个东西”
超高校级的门卫 2020-03-12 20:29:17
这你还要说只有你可定制吗?
duangsuse 2020-03-12 20:29:47
不是只有 ParserKt 可定制,是只有它定制最方便
超高校级的门卫 2020-03-12 20:30:33
这是user define的东西,一定存在kotlin edsl能够对任何parsec后端work
duangsuse 2020-03-12 20:30:58

超高校级的门卫 2020-03-12 20:31:13
你定制方便没有意义,因为用户本来就不期望库里面做一些特殊use case的事情
duangsuse 2020-03-12 20:32:03
谁知道呢?(๑ゝω╹๑)
超高校级的门卫 2020-03-12 20:33:16
像antlr这种次级parser生成器,以及现在的可用parser生成器,都可以正常的报出)没match。至于说要提示没match哪个(,这个需求不具有说服力
duangsuse 2020-03-12 20:35:23
每个实现方式的客观需求都是不同的,Who knows?
不过我就是喜欢有序、有层次的代码,如果正好可配置,那为什么不呢(´∇`)
超高校
你能作为"有特色"的框架去beat标杆的某些方面,或者成为这个标杆的闭包
duangsuse 2020-03-12 20:07:22
@超高校级的门卫 我也去看过不少同类框架。
他们也的确是“相差无几”,但就我个人来看,他们唯一差的就是,太聪明了…… 太学术了……
比如 https://github.com/h0tk3y/better-parse,它是用了很多很厉害的技术(e.g. codegen),但不是很工程,而且容易被滥用一些 combinator 的 infix notation
不忘掉 BNF 那套繁琐的 terminal / non-terminal 术语,不摒弃以往 scannerless parser框架 的实现模式,怎么可能弄出 ParserKt 这种泛向的框架的说(≧ω≦)
duangsuse 2020-03-12 20:08:21
下次重构后去跑分!现在还在各种优化接口……
超高校级的门卫 2020-03-12 20:09:26
bnf和scannerless不冲突
超高校级的门卫 2020-03-12 20:09:38
你的泛向在哪里
duangsuse 2020-03-12 20:09:46
泛型解析。
超高校级的门卫 2020-03-12 20:10:09
你举例子
duangsuse 2020-03-12 20:10:14
// Generic parsing for [1, a, b] where (b > a) val ints = Seq(::IntTuple, item(1), *Contextual(item<Int>()) { i -> satisfy<Int> { it > i } }.flatten().items() ) ints.rebuild(1,2,3) //[1, 2, 3] ints.rebuild(1,2,1) //notParsed i.rebuild(1,0,1) //[1, 0, 1]
超高校级的门卫 2020-03-12 20:11:47
哪里泛型了?
duangsuse 2020-03-12 20:12:00
https://github.com/ParserKt/ParserKt/blob/master/README.md#introduction
就是这里的代码示例
超高校级的门卫 2020-03-12 20:12:02
这是parsec都能做到的
超高校级的门卫 2020-03-12 20:12:10
你无非做了一个constraint
duangsuse 2020-03-12 20:12:13
输入是 Int
超高校级的门卫 2020-03-12 20:12:25
这不是什么问题
超高校级的门卫 2020-03-12 20:12:36
haskell parsec是母版
超高校级的门卫 2020-03-12 20:12:44
token是泛型的
duangsuse 2020-03-12 20:13:01
可是我见过所有的 Kotlin parserc 都不能 (^ν^)
duangsuse 2020-03-12 20:13:23
而且 Haskell 的 parserc 谈不了性能
超高校级的门卫 2020-03-12 20:13:53
haskell是一个相当快速的语言,你应该多做benchmark
duangsuse 2020-03-12 20:14:08
到处 shallow copy 的 product value mapping 是很难做到服务端的性能要求的
duangsuse 2020-03-12 20:14:43
GHC Haskell 的性能往往要靠特别的优化
超高校级的门卫 2020-03-12 20:14:49
我一直觉得发生shallow copy的是非pure语言使用list的时候
超高校级的门卫 2020-03-12 20:14:59
而haskell整好避免这一点
duangsuse 2020-03-12 20:15:51
而且 Kotlin 是内部支持 imperative 的语言呢,Haskell 是另外的世界
超高校级的门卫 2020-03-12 20:16:21
如果事实如此,那确实是挺不错的。@定理证明器 当年好像没把我的库移植过去完,不然也是个token type可变的
duangsuse 2020-03-12 20:17:31
不过这个里面有不少点子都是我自己想出来的比如 Feed/Pattern (可 read 可 show) 还有 clam, clamWhile, alsoDo, stateAs 什么的
超高校级的门卫 2020-03-12 20:17:37
不过我当年第一个parsing尝试就是在非传统token的type上做的,写完就有人说太naive。我认为不太容易获得认同
超高校级的门卫 2020-03-12 20:17:55
别人看会觉得挺复杂的
超高校级的门卫 2020-03-12 20:18:30
我以前也搞很多新东西,后面发现无非是一个user define的parsec函数
超高校级的门卫 2020-03-12 20:18:57
我对我以前的评价就是,做出了parsec的左递归支持,牛逼。别的,垃圾,闭门造车。
duangsuse 2020-03-12 20:20:58
From big power comes big responsibility比如说,PKT 里 SurroundBy(clamly(parens), stringFor(anyChar)) 你可以在错误提示里获得开括号的 sourceLoc (前提是 input 必须包含 ExpectClose 实例的状态)而手写是这种做法的…… “无结构”写法ANTLR?它做不到,因为它不知道什么是 paired Pattern
超高校级的门卫 2020-03-12 20:23:09
有意思,你可以讲一些你这个开括号错误提示比antlr强在哪儿
超高校级的门卫 2020-03-12 20:23:43
(xxx你会提示(的loc而不是最后一个x的loc?
duangsuse 2020-03-12 20:25:15
不过 SatisfyPattern.clam 和 Pattetn.clamWhile 也的确是受启发的
就是编译原理所谓的“镇静解析策略”
ParserKt 里的 Pattern, read 成功就是 T, 失败了就是 null (notParsed)
所以,clamWhile(pat, defaultValue, messager) 可以提供一个可定制的出错提示
我尽可能把 parserc 在语言可以表达的逻辑的集成方面的优势用到了…… 就那样吧
超高校级的门卫 2020-03-12 20:25:49
这是user define的行为
超高校级的门卫 2020-03-12 20:26:13
用户会选择自己写一个这个功能,而不是记忆你的api
duangsuse 2020-03-12 20:26:57
就像 Java 8 的 obj.someCall()它的 NPE 不会提示 null 的东西是 obj。ParserKt 可以在找不到闭括号的前提下显示expecting ')' (from file:line:column)
超高校级的门卫 2020-03-12 20:28:04
你确定antlr做不到?我认为LL和LR都应该有这个能力,除非parser的失败是在内部的rule
超高校级的门卫 2020-03-12 20:28:29
而内部rule失败,报出外部还没遇到的错误也不太合理
duangsuse 2020-03-12 20:28:42
不过这个错误提示也的确是可定制的相关代码在这里:https://github.com/ParserKt/ParserKt/blob/master/parserkt-ext/src/commonMain/kotlin/org/parserkt/pat/ext/MiscHelper.kt#L48
超高校级的门卫 2020-03-12 20:29:04
这哪个parsec都都可定制
duangsuse 2020-03-12 20:29:16
不确定,但是它不会知道“() 是配对的两个东西”
超高校级的门卫 2020-03-12 20:29:17
这你还要说只有你可定制吗?
duangsuse 2020-03-12 20:29:47
不是只有 ParserKt 可定制,是只有它定制最方便
超高校级的门卫 2020-03-12 20:30:33
这是user define的东西,一定存在kotlin edsl能够对任何parsec后端work
duangsuse 2020-03-12 20:30:58

超高校级的门卫 2020-03-12 20:31:13
你定制方便没有意义,因为用户本来就不期望库里面做一些特殊use case的事情
duangsuse 2020-03-12 20:32:03
谁知道呢?(๑ゝω╹๑)
超高校级的门卫 2020-03-12 20:33:16
像antlr这种次级parser生成器,以及现在的可用parser生成器,都可以正常的报出)没match。至于说要提示没match哪个(,这个需求不具有说服力
duangsuse 2020-03-12 20:35:23
每个实现方式的客观需求都是不同的,Who knows?
不过我就是喜欢有序、有层次的代码,如果正好可配置,那为什么不呢(´∇`)
超高校
GitHub
ParserKt/ParserKt
Naive one-pass recursive descent, scannerless parser framework for Kotlin - ParserKt/ParserKt
没有价值的,每一遍完全重写的都会让你对问题和解决方案的理解更进一步,无论算法和模型简单或复杂,我相信都是这样。
这一点,我想一味强调“我只花了3小时” “对我来说这太简单了”的人大概是不会明白吧……
这就是我刚才说的,对自己的“胜利”,还是对他人价值的坚持
duangsuse 2020-03-12 21:53:59
所以最好还是不要“智商量化”了吧……
价值是可以量化的,但是如果作概论,两个人直接变成了偏序关系(传递&反对称)……
是不是这么理解,不是完全战胜就是完全打败,有点太世俗呢……
收藏于昨天 群-迂腐的学院派编译技术
这一点,我想一味强调“我只花了3小时” “对我来说这太简单了”的人大概是不会明白吧……
这就是我刚才说的,对自己的“胜利”,还是对他人价值的坚持
duangsuse 2020-03-12 21:53:59
所以最好还是不要“智商量化”了吧……
价值是可以量化的,但是如果作概论,两个人直接变成了偏序关系(传递&反对称)……
是不是这么理解,不是完全战胜就是完全打败,有点太世俗呢……
收藏于昨天 群-迂腐的学院派编译技术
级的门卫 2020-03-12 20:41:16
不管是实现还是使用,我觉得你都没有比别的框架更有序和有层次。可配置这一点是比较明显的,但你也引入了相当的复杂度,我觉得是混淆了user define和library core。
不管怎么说你能写出parsec改进框架,说明你掌握了模式匹配,已经超越了很多的人。望继续加油
duangsuse 2020-03-12 20:44:41
@超高校级的门卫 是 Scala 的库啊,还能解析 Python,我看看
duangsuse 2020-03-12 20:46:22
@超高校级的门卫 受教了^ω^
duangsuse 2020-03-12 20:55:53
( ゚∀ ゚)不过说起来,个人感觉 FastParse 还是有点冗了
不懂为什么一定要是 runParse(parser, input) ,看起来很多框架都这样的
而且 P("text") 这个语义有点不对啊…… 难道 P 是 regex? 
超高校级的门卫 2020-03-12 20:56:44
runParse是因为大家都相当程度学过haskell,理解,并认可其抽象
超高校级的门卫 2020-03-12 20:57:12
P的语义有什么不对?
超高校级的门卫 2020-03-12 20:57:39
wrap到parser monad中
超高校级的门卫 2020-03-12 20:58:06
类型上更加统一美妙,而不是使用大量没有规律的重载
duangsuse 2020-03-12 20:58:33
说起性能,ParserKt 强调一定要 one-pass (仅过一遍,Feed 流绝不回头)
而多字符判断都是 TriePattern / Contextual 弄的
这个也是 one-pass 同好吗?( ゚∀ ゚)
duangsuse 2020-03-12 20:59:35
其实因为只能过一遍的原因,ParserKt 里都是没有 string pattern 的,都用可变的 TriePattern 替代了
duangsuse 2020-03-12 21:01:11
@超高校级的门卫 (>﹏<)刚才没看见 P 不只是 P("") 一种用法
超高校级的门卫 2020-03-12 21:04:34
多字符判断靠优化做。parsec默认都是不回溯的。peek(1)也不行
duangsuse 2020-03-12 21:05:20
这个解析器是纯的 [a] recurse&destruct?
直接用符号看起来也是蛮 EDSL 的呢……
ParserKt 很强调 one-pass 和 rebuild (flatten Parse result back to input)
所以不存在 | alternation,连 SDRIES (seq, decide, repeat. item, elementIn, satisfy ) 里的 Decide 解析结果都是 Tuple2<Idx/*=Int*/, T> 呢……
超高校级的门卫 2020-03-12 21:05:29
peek(1)后match出一个rule,是parsec里可以有的一种组合子,不知道是否是你的triepattern
超高校级的门卫 2020-03-12 21:05:56
alternative是为了好写,好组合
duangsuse 2020-03-12 21:06:32
是的,不过那个更灵活其实 Contextual+TriePattern 也是可以做到这种的。
超高校级的门卫 2020-03-12 21:06:51
parsec的alternative也有可以优化的办法,你手工dispatch,代码比较多,而且看不到很多优化点
duangsuse 2020-03-12 21:07:55
Contextual 就是有一个 HEAD 一个 BODY,其中 BODY 的解析器依赖 HEAD 的结果构造
超高校级的门卫 2020-03-12 21:08:53
我一般喜欢把这个叫做parsec的parsergen组合子,不过其实他很平凡,没有名字
duangsuse 2020-03-12 21:09:46
所以说现阶段主要是靠实践者手动做分支判断……https://github.com/ParserKt/examples/blob/master/hanCalc/src/commonMain/kotlin/Calc.kt
超高校级的门卫 2020-03-12 21:10:38
我后期parsing学习步入正轨,就是从优化这个开始的
超高校级的门卫 2020-03-12 21:11:18
我建议你还是以学习为主
duangsuse 2020-03-12 21:12:06
其实这个计算器 虽然幼稚,但也比较有意思……
毕竟 TriePattern 是可变的……
另外我现在还是高中生…… 学习为主的话…… 的确是
( ̄o ̄) . z Z 呢
超高校级的门卫 2020-03-12 21:13:53
别把自己是高中生拿出来说,没人会觉得这个是亮点。我觉得挺恶心的。我大学开始学的编程,初中开始学编程能达到我水平的也没几个
超高校级的门卫 2020-03-12 21:14:52
parsec都是可变的,是少数可以支持动态添加rule的parsing技术之一。你的话满是尴尬,我不想多说负面语言。你加油,别回了
duangsuse 2020-03-12 21:14:57
@超高校级的门卫 我清楚这个会被人当做是炫耀但是既然你都问了…… 有一点感觉你会认为我是学后端什么的
超高校级的门卫 2020-03-12 21:15:32
没有,我挺认同你的。但我不喜欢你这一副以目前结果自觉满足的样子
duangsuse 2020-03-12 21:16:37
我 不 满 足
我只是来推销(
超高校级的门卫 2020-03-12 21:16:42
你不配
duangsuse 2020-03-12 21:17:02
如果我满足了,就不会回来
因为我早就被冰封喷过一次
duangsuse 2020-03-12 21:17:11

Miko 2020-03-12 21:17:36
你不配hetui
duangsuse 2020-03-12 21:19:02
自大的人是不会接受批评的
我见过这种人,当然这不代表我不自大
那么怎么再谦虚…… 我不发颜表情了好不好
我已经因为杠性能和语法糖的概念定义
被 Tg 上的 Pythonzh 踢过一次了……
duangsuse 2020-03-12 21:19:51
好吧,原来推销是要避嫌的(
duangsuse 2020-03-12 21:21:39
没事(没关系我只单方面认识冰封dalao来这交流下观念,收获颇丰。
今泉影狼 2020-03-12 21:23:18
@duangsuse 知乎上有两个高中生
duangsuse 2020-03-12 21:23:47
哥巴赫猜想?
今泉影狼 2020-03-12 21:23:57
[轻应用]
今泉影狼 2020-03-12 21:24:15
[轻应用]
今泉影狼 2020-03-12 21:24:24
你看看他们的回答和文章
今泉影狼 2020-03-12 21:24:33
这才是高中生应该有的样子
duangsuse 2020-03-12 21:26:01
确实是,但你也不能否认另一个技术侧面和编程风格的“高中生”毕竟就是,什么人都有,健康的技术不应该只有一种风格。
超高校级的门卫 2020-03-12 21:26:32
这是风格问题?
今泉影狼 2020-03-12 21:26:51
前者除了科技发烧友和 telegram 使用之外应该是你的 superset (
duangsuse 2020-03-12 21:28:52
https://www.zhihu.com/people/newbie-tu-xing-cheng-xu-yuan?utm_source=qq&utm_medium=social&utm_oi=680871912008323072
我觉得这个讲得蛮不错的,有没有讲关系式 unification 在 Kotlin 里的实现的文章 可以推荐下
duangsuse 2020-03-12 21:31:07
@今泉影狼 不,是包含交集的两个不同的集合没有道理去给任何事物评价“谁输谁赢”就好像类型系统,也只是程序设计语言的一部分不管它怎么样集成,也不能代表整个语言本身
duangsuse 2020-03-12 21:33:02
你们定下大佬的标准是完全没问题的
但是,现实世界没有“无用的齿轮”,也不能说某人的能力在何层面都不如另一人
duangsuse 2020-03-12 21:36:42
在我看来,知识不是为了让你打败谁,获得怎样的尊重
而是能让你能更多、更深地为其他人做点什么
所以说可读性很重要,不过这也是相对的…… 但它不意味 对于很复杂的问题,就没有更简单的描述方法了
举例、比喻、提纲、缩写、图示、动画
这全都是进一步加强可读性的方法诶
duangsuse 2020-03-12 21:49:56
我不喜欢数学不止是因为我对数字的记忆和计算能力差,更是因为…… 我的风格相当“工程”
我尽可能少做和最终问题无关的事情
而且比起单纯的阅读学习,更希望能先实践再搜集引用(实际上我很怕复杂以及代数式的概念)
我觉得要创新的话,先理解问题还是先理解解决方式 是很重要条件
如果能先做到理解问题,虽说不一定能做到更好,但至少会有所改变,然后让这些改变物竞天择,累积起来。
重复不是
不管是实现还是使用,我觉得你都没有比别的框架更有序和有层次。可配置这一点是比较明显的,但你也引入了相当的复杂度,我觉得是混淆了user define和library core。
不管怎么说你能写出parsec改进框架,说明你掌握了模式匹配,已经超越了很多的人。望继续加油
duangsuse 2020-03-12 20:44:41
@超高校级的门卫 是 Scala 的库啊,还能解析 Python,我看看
duangsuse 2020-03-12 20:46:22
@超高校级的门卫 受教了^ω^
duangsuse 2020-03-12 20:55:53
( ゚∀ ゚)不过说起来,个人感觉 FastParse 还是有点冗了
不懂为什么一定要是 runParse(parser, input) ,看起来很多框架都这样的
而且 P("text") 这个语义有点不对啊…… 难道 P 是 regex? 
超高校级的门卫 2020-03-12 20:56:44
runParse是因为大家都相当程度学过haskell,理解,并认可其抽象
超高校级的门卫 2020-03-12 20:57:12
P的语义有什么不对?
超高校级的门卫 2020-03-12 20:57:39
wrap到parser monad中
超高校级的门卫 2020-03-12 20:58:06
类型上更加统一美妙,而不是使用大量没有规律的重载
duangsuse 2020-03-12 20:58:33
说起性能,ParserKt 强调一定要 one-pass (仅过一遍,Feed 流绝不回头)
而多字符判断都是 TriePattern / Contextual 弄的
这个也是 one-pass 同好吗?( ゚∀ ゚)
duangsuse 2020-03-12 20:59:35
其实因为只能过一遍的原因,ParserKt 里都是没有 string pattern 的,都用可变的 TriePattern 替代了
duangsuse 2020-03-12 21:01:11
@超高校级的门卫 (>﹏<)刚才没看见 P 不只是 P("") 一种用法
超高校级的门卫 2020-03-12 21:04:34
多字符判断靠优化做。parsec默认都是不回溯的。peek(1)也不行
duangsuse 2020-03-12 21:05:20
这个解析器是纯的 [a] recurse&destruct?
直接用符号看起来也是蛮 EDSL 的呢……
ParserKt 很强调 one-pass 和 rebuild (flatten Parse result back to input)
所以不存在 | alternation,连 SDRIES (seq, decide, repeat. item, elementIn, satisfy ) 里的 Decide 解析结果都是 Tuple2<Idx/*=Int*/, T> 呢……
超高校级的门卫 2020-03-12 21:05:29
peek(1)后match出一个rule,是parsec里可以有的一种组合子,不知道是否是你的triepattern
超高校级的门卫 2020-03-12 21:05:56
alternative是为了好写,好组合
duangsuse 2020-03-12 21:06:32
是的,不过那个更灵活其实 Contextual+TriePattern 也是可以做到这种的。
超高校级的门卫 2020-03-12 21:06:51
parsec的alternative也有可以优化的办法,你手工dispatch,代码比较多,而且看不到很多优化点
duangsuse 2020-03-12 21:07:55
Contextual 就是有一个 HEAD 一个 BODY,其中 BODY 的解析器依赖 HEAD 的结果构造
超高校级的门卫 2020-03-12 21:08:53
我一般喜欢把这个叫做parsec的parsergen组合子,不过其实他很平凡,没有名字
duangsuse 2020-03-12 21:09:46
所以说现阶段主要是靠实践者手动做分支判断……https://github.com/ParserKt/examples/blob/master/hanCalc/src/commonMain/kotlin/Calc.kt
超高校级的门卫 2020-03-12 21:10:38
我后期parsing学习步入正轨,就是从优化这个开始的
超高校级的门卫 2020-03-12 21:11:18
我建议你还是以学习为主
duangsuse 2020-03-12 21:12:06
其实这个计算器 虽然幼稚,但也比较有意思……
毕竟 TriePattern 是可变的……
另外我现在还是高中生…… 学习为主的话…… 的确是
( ̄o ̄) . z Z 呢
超高校级的门卫 2020-03-12 21:13:53
别把自己是高中生拿出来说,没人会觉得这个是亮点。我觉得挺恶心的。我大学开始学的编程,初中开始学编程能达到我水平的也没几个
超高校级的门卫 2020-03-12 21:14:52
parsec都是可变的,是少数可以支持动态添加rule的parsing技术之一。你的话满是尴尬,我不想多说负面语言。你加油,别回了
duangsuse 2020-03-12 21:14:57
@超高校级的门卫 我清楚这个会被人当做是炫耀但是既然你都问了…… 有一点感觉你会认为我是学后端什么的
超高校级的门卫 2020-03-12 21:15:32
没有,我挺认同你的。但我不喜欢你这一副以目前结果自觉满足的样子
duangsuse 2020-03-12 21:16:37
我 不 满 足
我只是来推销(
超高校级的门卫 2020-03-12 21:16:42
你不配
duangsuse 2020-03-12 21:17:02
如果我满足了,就不会回来
因为我早就被冰封喷过一次
duangsuse 2020-03-12 21:17:11

Miko 2020-03-12 21:17:36
你不配hetui
duangsuse 2020-03-12 21:19:02
自大的人是不会接受批评的
我见过这种人,当然这不代表我不自大
那么怎么再谦虚…… 我不发颜表情了好不好
我已经因为杠性能和语法糖的概念定义
被 Tg 上的 Pythonzh 踢过一次了……
duangsuse 2020-03-12 21:19:51
好吧,原来推销是要避嫌的(
duangsuse 2020-03-12 21:21:39
没事(没关系我只单方面认识冰封dalao来这交流下观念,收获颇丰。
今泉影狼 2020-03-12 21:23:18
@duangsuse 知乎上有两个高中生
duangsuse 2020-03-12 21:23:47
哥巴赫猜想?
今泉影狼 2020-03-12 21:23:57
[轻应用]
今泉影狼 2020-03-12 21:24:15
[轻应用]
今泉影狼 2020-03-12 21:24:24
你看看他们的回答和文章
今泉影狼 2020-03-12 21:24:33
这才是高中生应该有的样子
duangsuse 2020-03-12 21:26:01
确实是,但你也不能否认另一个技术侧面和编程风格的“高中生”毕竟就是,什么人都有,健康的技术不应该只有一种风格。
超高校级的门卫 2020-03-12 21:26:32
这是风格问题?
今泉影狼 2020-03-12 21:26:51
前者除了科技发烧友和 telegram 使用之外应该是你的 superset (
duangsuse 2020-03-12 21:28:52
https://www.zhihu.com/people/newbie-tu-xing-cheng-xu-yuan?utm_source=qq&utm_medium=social&utm_oi=680871912008323072
我觉得这个讲得蛮不错的,有没有讲关系式 unification 在 Kotlin 里的实现的文章 可以推荐下
duangsuse 2020-03-12 21:31:07
@今泉影狼 不,是包含交集的两个不同的集合没有道理去给任何事物评价“谁输谁赢”就好像类型系统,也只是程序设计语言的一部分不管它怎么样集成,也不能代表整个语言本身
duangsuse 2020-03-12 21:33:02
你们定下大佬的标准是完全没问题的
但是,现实世界没有“无用的齿轮”,也不能说某人的能力在何层面都不如另一人
duangsuse 2020-03-12 21:36:42
在我看来,知识不是为了让你打败谁,获得怎样的尊重
而是能让你能更多、更深地为其他人做点什么
所以说可读性很重要,不过这也是相对的…… 但它不意味 对于很复杂的问题,就没有更简单的描述方法了
举例、比喻、提纲、缩写、图示、动画
这全都是进一步加强可读性的方法诶
duangsuse 2020-03-12 21:49:56
我不喜欢数学不止是因为我对数字的记忆和计算能力差,更是因为…… 我的风格相当“工程”
我尽可能少做和最终问题无关的事情
而且比起单纯的阅读学习,更希望能先实践再搜集引用(实际上我很怕复杂以及代数式的概念)
我觉得要创新的话,先理解问题还是先理解解决方式 是很重要条件
如果能先做到理解问题,虽说不一定能做到更好,但至少会有所改变,然后让这些改变物竞天择,累积起来。
重复不是
GitHub
ParserKt/examples
Example parsers for the ParserKt library. Contribute to ParserKt/examples development by creating an account on GitHub.
🤔 下次一定要让 ParserKt 的应用走上 web
还有我从一个项目里学到 GitHub 里也可以用 <table border= >
应该可以弄一个新 brief
还有我从一个项目里学到 GitHub 里也可以用 <table border= >
应该可以弄一个新 brief
Forwarded from 层叠 - The Cascading