欸我有了一个主意,ParserKt 的 number show 可以基于 unfold 的去做,那么这个 toString 的流程是可以随便指定的
只要我能够 lateinit var 引用 numUnit 的实例,就可以做到递归 show 出汉字单位前的数值了
只要我能够 lateinit var 引用 numUnit 的实例,就可以做到递归 show 出汉字单位前的数值了
/tmp/duangsuse.sock
我来说说,这 1hr1min1s 和 三千五百万 有啥区别。 1hr1min1s 是累加、三千五百万是更复杂的折叠,因为汉字每个子意群都得带单位。 单位上升(“五百万”)的时候是乘,单位下降(“三千一百”)的时候是加,其实不必递归。 汉字没有 123 这种直接的数字(都是一百二十三)所以一个单位的显示还得递归地去做。 这个 show,不需要区分仅个位或大于十的情况,直接交给能输出数字的子程序即可。 NumUnit 已经做好了这一点,可它做不到最大单位也无法仅含个位情况下的递归输出。 而且如果 units…
我们常说,个、十、百、千、万、十万、百万、千万、亿、十亿、百亿、千亿、万亿、亿亿,可是这么枚举下去可以到 "亿亿亿亿亿亿",何时是个头呢?到 Int.MAX_VALUE 那不是一个正经程序员会做的权变。
所以不能滥用字典树的操作,只有十百千万亿,没有组合单位。
所以不能滥用字典树的操作,只有十百千万亿,没有组合单位。
val hanDigit = MapPattern(mapOf(
*"一二三四五六七八九".asIterable().zip(1..9).toArray())
)
val hanUnit = KeywordPattern<Int>().apply {
mergeStrings("" to 1, "十" to 10, "百" to 100)
mergeStrings("千" to 1000, "万" to 10000)
} >>> val k=NumUnitTrie(hanDigit, hanUnit, IntOps)
>>> k.read("一百一十")
res31: kotlin.Int? = 110>>> k.read("一百一十一")
res32: kotlin.Int? = null>>> k.rebuild("一百一十")
res33: kotlin.String? = 一百一十哈,可是碰到 “三十二万” 就犯难了
/tmp/duangsuse.sock
我来说说,这 1hr1min1s 和 三千五百万 有啥区别。 1hr1min1s 是累加、三千五百万是更复杂的折叠,因为汉字每个子意群都得带单位。 单位上升(“五百万”)的时候是乘,单位下降(“三千一百”)的时候是加,其实不必递归。 汉字没有 123 这种直接的数字(都是一百二十三)所以一个单位的显示还得递归地去做。 这个 show,不需要区分仅个位或大于十的情况,直接交给能输出数字的子程序即可。 NumUnit 已经做好了这一点,可它做不到最大单位也无法仅含个位情况下的递归输出。 而且如果 units…
找到了一个可以复用的点,但不知道是否值得为了它创建子类还是再次损失一点性能
1hr1min1s 也可以写成 1s1hr1min,可是大概有些人愿意做检测,仅允许 1hr1min1s 的情况。可以提供出一个 fun onUnitJoin(u1, u0) 来允许这种检查,可是 read/show 好像无法做到同时复用……
1hr1min1s 也可以写成 1s1hr1min,可是大概有些人愿意做检测,仅允许 1hr1min1s 的情况。可以提供出一个 fun onUnitJoin(u1, u0) 来允许这种检查,可是 read/show 好像无法做到同时复用……
/tmp/duangsuse.sock
我来说说,这 1hr1min1s 和 三千五百万 有啥区别。 1hr1min1s 是累加、三千五百万是更复杂的折叠,因为汉字每个子意群都得带单位。 单位上升(“五百万”)的时候是乘,单位下降(“三千一百”)的时候是加,其实不必递归。 汉字没有 123 这种直接的数字(都是一百二十三)所以一个单位的显示还得递归地去做。 这个 show,不需要区分仅个位或大于十的情况,直接交给能输出数字的子程序即可。 NumUnit 已经做好了这一点,可它做不到最大单位也无法仅含个位情况下的递归输出。 而且如果 units…
我说说绝句里的情况吧。除了负数和小数,刚才我提到的 pattern 都是支持的。
特殊处理大概就三种:
+ 零..九
+ 十一..十九
+ 一千零一
特殊处理大概就三种:
+ 零..九
+ 十一..十九
+ 一千零一
/tmp/duangsuse.sock
val hanDigit = MapPattern(mapOf( *"一二三四五六七八九".asIterable().zip(1..9).toArray()) ) val hanUnit = KeywordPattern<Int>().apply { mergeStrings("" to 1, "十" to 10, "百" to 100) mergeStrings("千" to 1000, "万" to 10000) } >>> val k=NumUnitTrie(hanDigit, hanUnit…
见识到本苏代码的复用性了吧?digitFor 和 MapPattern,一行代码自由切换读取变换算法,无痛迁移 😊
而且比函数式解析组合子更具有明确性,如果你用
正是因为写 Pattern 的时候不仅要 read,甚至要能够 show,而且还得支持 toPreetyDoc,所以敷衍、小聪明的写法就走不下去了,不是真正了解结构,写得了 from 写不出 to,整个完整的解析过程 ParserKt 都给管着,因为解析本身就和数据的表达方式转换脱不了干系。
而且比函数式解析组合子更具有明确性,如果你用
then 来完成 map value 的操作,怎么可能做到 show 的时候再 map back 呢~ 怎么会把 MapPattern 封装成一个类呢~正是因为写 Pattern 的时候不仅要 read,甚至要能够 show,而且还得支持 toPreetyDoc,所以敷衍、小聪明的写法就走不下去了,不是真正了解结构,写得了 from 写不出 to,整个完整的解析过程 ParserKt 都给管着,因为解析本身就和数据的表达方式转换脱不了干系。
/tmp/duangsuse.sock
val hanDigit = MapPattern(mapOf( *"一二三四五六七八九".asIterable().zip(1..9).toArray()) ) val hanUnit = KeywordPattern<Int>().apply { mergeStrings("" to 1, "十" to 10, "百" to 100) mergeStrings("千" to 1000, "万" to 10000) } >>> val k=NumUnitTrie(hanDigit, hanUnit…
我来说一个能解决输出问题,但是不能解决检查问题的:
val hanDigits = "一二三四五六七八九".asIterable().map(Char::toString).zip(1..9)
val hanDigit10s = hanDigits.map { it.run { "十"+first to 10+second } } // 闹着玩的,不能这么干
lateinit var hanShow: (Output<Char>, Int?) -> Unit
val hanDigit = object: KeywordPattern<Int>() {
init { mergeStrings(*hanDigits.toArray(), *hanDigit10s.toArray()) }
override fun show(s: Output<Char>, value: Int?) { if (value == null) return;
if (value in 1..9) super.show(s, value) else hanShow(s, value) }
}
val hanUnit = KeywordPattern<Int>().apply {
mergeStrings("" to 1, "十" to 10, "百" to 100)
mergeStrings("千" to 1000, "万" to 10000)
}
val k=NumUnitTrie(hanDigit, hanUnit, IntOps)
hanShow = k::show
/tmp/duangsuse.sock
我说说绝句里的情况吧。除了负数和小数,刚才我提到的 pattern 都是支持的。 特殊处理大概就三种: + 零..九 + 十一..十九 + 一千零一
我没支持到“亿”,因为那个数太大了
至于几百万的,在 NumUnitPattern 里,这很难实现,于是我避重就轻选择了特化支持 百万、千万这种单位,
但是
……算了,这情况也不好说
至于几百万的,在 NumUnitPattern 里,这很难实现,于是我避重就轻选择了特化支持 百万、千万这种单位,
但是
一千二百又百 (此时的“又”等价“零”)是支持的。……算了,这情况也不好说
/tmp/duangsuse.sock
我没支持到“亿”,因为那个数太大了 至于几百万的,在 NumUnitPattern 里,这很难实现,于是我避重就轻选择了特化支持 百万、千万这种单位, 但是一千二百又百 (此时的“又”等价“零”)是支持的。 ……算了,这情况也不好说
……“百万”的特例化支持,我也觉得是停止的好,因为它扰乱 show 的运作了
还是
还是
三百又万 吧,严谨不少。listOf("十", "百", "千").forEach { val k = this[it]!!*10000; this[it+"万"] = k; this[it+"万零"] = -k } 删了。k < 0 -> op.times(abs(k), i).also { s.error("零 form cannot be used in initial part") } 又删除了个
/tmp/duangsuse.sock
……“百万”的特例化支持,我也觉得是停止的好,因为它扰乱 show 的运作了 还是 三百又万 吧,严谨不少。 listOf("十", "百", "千").forEach { val k = this[it]!!*10000; this[it+"万"] = k; this[it+"万零"] = -k } 删了。 k < 0 -> op.times(abs(k), i).also { s.error("零 form cannot be used in initial part") } 又删除了个
算是勉强侥幸成功,最后又修了关于列号多记的一个小 bug,是我对 Feed 模型不够熟悉造成的。
https://zhuanlan.zhihu.com/p/106578320
我就说说这个『橙式』吧。ParserKt 的复用性可以做到直接处理。(ParserKt 的复用性厉害吧?能写 lexer 能写各种 parser 能处理双向转换,连单位进制换算都能做)
我就说说这个『橙式』吧。ParserKt 的复用性可以做到直接处理。(ParserKt 的复用性厉害吧?能写 lexer 能写各种 parser 能处理双向转换,连单位进制换算都能做)
val 不翻译 = Convert(stringSurroundBy('¥' to '¥', anyChar), { "-" + it }, { it.drop(1) })
val 翻译器 = KeywordPattern<String>().apply {
mergeStrings("函数" to "fun", "量" to "val", "变" to "var")
mergeStrings("若" to "if", "否则" to "else", "判" to "when")
mergeStrings("当" to "while", "对" to "for", "在" to "in")
}
val 翻译 = Piped(翻译器) { "+" + (it ?: takeWhile { c -> c !in 翻译器.routes }.joinToString("")) }
val 橙式构词 = Decide(不翻译, 翻译).mergeFirst { if (it[0] == '+') 1 else 0 }
val 橙式 = Repeat(asList(), 橙式构词).Many()知乎专栏
一个通用中文编程工具——橙式
项目地址:GithubOrangex中 文 编 程 , 最 为 致 命.橙式的目标是给希望使用中文编程的人打造一个完整的工具链.持续更新中...在开发其他相对应工具...使用要求安装有nodejs.安装:npm install orangex -g 橙式帮…
/tmp/duangsuse.sock
https://zhuanlan.zhihu.com/p/106578320 我就说说这个『橙式』吧。ParserKt 的复用性可以做到直接处理。(ParserKt 的复用性厉害吧?能写 lexer 能写各种 parser 能处理双向转换,连单位进制换算都能做) val 不翻译 = Convert(stringSurroundBy('¥' to '¥', anyChar), { "-" + it }, { it.drop(1) }) val 翻译器 = KeywordPattern<String>().apply…
……ParserKt 实现起来唯一麻烦的点就是,TriePattern 的 show 是单向的,需要弄两个 Trie
两个 Trie(正反都有),要同时更新必须新建一个类,或者不允许更新。
两个 Trie(正反都有),要同时更新必须新建一个类,或者不允许更新。
Forwarded from Deleted Account
其实这样不能全怪我吧…… 毕竟这个
你写得可谓是优雅…… 几乎把 Java 写成 C 了,那个命名风格我是看不太懂,有点超乎时代和传统,绝世而独立……
当然在 Kotlin 里这个程序就三行。
当然如果觉得那太魔法(因为引入了一个隐式的 Service 的 this)
List<TTeam> list1 = hadJoinTeam(2, user.getId());
List<TActivity> activities = List.of();
for (int i=0; i<list2.size(); i++) { TTeam it = list2.get(i);
Activity activity = checkActivity(it).getId();
activities.add(activity);
out.println(String.format("下标为%i的值为%s", i, activity/*==activities.get(i)*/.getName() ));
} 你写得可谓是优雅…… 几乎把 Java 写成 C 了,那个命名风格我是看不太懂,有点超乎时代和传统,绝世而独立……
当然在 Kotlin 里这个程序就三行。
val team1 = users.filterInTeam(1)至于 service 数据依赖怎么办,继承抽象类就可以用里面的扩展方法了。
val team2 = users.filterInTeam(2)
val activities = team2.map { it.checkActivity().id }
activities.withIndex().forEach { println("下标为${it.index}的值为${it.value}") }
当然如果觉得那太魔法(因为引入了一个隐式的 Service 的 this)
val teams = listOf(1, 2).map { service.filterInTeam(it, users) }
val activities = teams[1].map(service::checkActivity).map(Activity::id)
最后一行还可以提出来成 fun <T> Iterable<T>.debugPrintln(),有重复代码就直接调用了。