#JavaScript #FP 分享一些十分不得了(迫真)的心得:我修复了 dropWhile 函数,然后这里我写了惰性递归的 makeCats 造猫(绝望) combination 函数,无论输入数据有多长、重复多少遍都可以利用惰性求值工作,不会像辣鸡过程式一样卡住(数据窗口太大了)
Forwarded from Deleted Account
递归惰性求值的 combination,你调用
const fp = require('./fp');
let xs = fp.stm.lazyCombination("abcdefghijklmnopqrstuvwxyz")(1926);
fp.stmaux.take(100, a);
都可以,反观非惰性求值版本的,反向的数据窗口大小太大了,根本算不出来。(不过递归也可能栈溢... 只能都惰性求值最好)const fp = require('./fp');
let xs = fp.stm.combination("abcdefghijklmnopqrstuvwxyz")(1926);
fp.stmaux.take(100, a); // 卡住
/tmp/duangsuse.sock
行!很完美
FP.js 里面写的那个 chainRec.... 左递归/右递归解析器不是那个用来解析二元运算的,就是普通构造,而且 parserc 的情况也是不可能只是使用这种组合子去组合....
可以编写表达式链解析器,很麻烦的,而且不支持多字符(两个以上就无法撤销或者说继续 lookahead 了,如果最后表达式链解析到 sep 子结构失败的时候,是要撤销掉字符读取的)的 operator (不过利用 Feed 就很简单了)
那个只是玩具而已,就是解析 日卡卡 成(right) [日, [卡, [卡, []]] 这种东西(Array.prototype.concat, [])是为这种和倒序什么的... 反正就是玩具而已
可以编写表达式链解析器,很麻烦的,而且不支持多字符(两个以上就无法撤销或者说继续 lookahead 了,如果最后表达式链解析到 sep 子结构失败的时候,是要撤销掉字符读取的)的 operator (不过利用 Feed 就很简单了)
那个只是玩具而已,就是解析 日卡卡 成(right) [日, [卡, [卡, []]] 这种东西(Array.prototype.concat, [])是为这种和倒序什么的... 反正就是玩具而已
/tmp/duangsuse.sock
这堆松耦合的函数,通过一个通用的返回值模板,居然真的可以正常工作!
question: 如何使用 FP.js 的 parserc 模块构造一个简单的解析器呢?
FP.js 提供了(至少是对我来说...)很方便的一些结构和函数(比如,dropWhile、char Feeder、seq parserc、lookAhead1、andThen 什么的)
可是作为它的使用者,不会用 也是没有办法的。
下面 教一些简单的 FP.js parserc 简易(迫真... 这个不是很优雅,准确的说我有点受到 Python 之前曾用 LL(1) 的误导)方式
并且,会使用 FP.js 的解析组合子模块,解构 GeekSpec 精简版的代码(
FP.js 提供了(至少是对我来说...)很方便的一些结构和函数(比如,dropWhile、char Feeder、seq parserc、lookAhead1、andThen 什么的)
可是作为它的使用者,不会用 也是没有办法的。
下面 教一些简单的 FP.js parserc 简易(迫真... 这个不是很优雅,准确的说我有点受到 Python 之前曾用 LL(1) 的误导)方式
并且,会使用 FP.js 的解析组合子模块,解构 GeekSpec 精简版的代码(
/tmp/duangsuse.sock
question: 如何使用 FP.js 的 parserc 模块构造一个简单的解析器呢? FP.js 提供了(至少是对我来说...)很方便的一些结构和函数(比如,dropWhile、char Feeder、seq parserc、lookAhead1、andThen 什么的) 可是作为它的使用者,不会用 也是没有办法的。 下面 教一些简单的 FP.js parserc 简易(迫真... 这个不是很优雅,准确的说我有点受到 Python 之前曾用 LL(1) 的误导)方式 并且,会使用 FP.js 的解析组合子模块,解构…
首先,既然要使用 FP.js 的解析组合子模块,首先要知道它暴露了什么接口。
此外:
Feeder 是输入字符/对象流的称呼,它上面可以使用:
lastIsCR / lastIsLF / lastIsCRLF / eof / hasNext 判断方法
duplast / reset1Tho 方法(reset1Tho 是给一些不消耗字符但是父 解析器会默认 next 的解析器做一个额外的副作用:保存一个字符)
loc / desc 方法:用于描述
logs / leave 方法:解析组合子的上下文支持利用栈,如果提供了栈,则 logs 和 leave 方法对应 push 和 pop。否则,什么都不肝(用于区分解析模式是调试与否)
lastItem / nextItem : lookAhead1 迭代器的标准数据视窗
next / nextNext : 移动数据视窗
>
>
FP.js 的 Feeder 对象会自动为你解决 CR / LF / CRLF 的换行符问题,三者中任意一种都能正确处理,不会出现行号不一致的情况。
>
>
—— 解析器们
上面提到的 wsP(), ws0P(), kwP() 什么的,全都是可以复用松耦合的解析器。
绝大部分解析器(可能解析失败的那种),为了提供一个良好的用户界面,都存在着一个
+ ws0P 是不可能失败的解析器(因为它要解析空格的数目,但是也可以是 0 个,就是说不可能解析不成功)
+ wsP 接受 msg 和 fmt,若是感受不到空格,返回
例子:
(tips: 如果项目本身定义的四元素 CR/LF/Tab/Space 不满足你对空格的需求,可使用 setWs 函数改变默认集合,当然我修改后直接 push 缺失的项目也可以)
+ elemP 接受 (iset, m, fmt),其中 fmt 默认为
>
上面的例子不是字符流的(FP.js 的解析组合子有意泛化一些),下面是一个字符流的例子:
>
> pp('不和谐')
(显然这只有一项,不过过会就能够看到松耦合组合子的强大组合能力了)
+ kwP(kwstr, msg, fmt) 是关键字的解析组合子。
默认 fmt 是
>
+ charP (ch, m, fmt)
这个家伙消耗一个字符,返回一个字符。
+ satisfy(p, m, fmt) 这是最后一个弟弟(划掉)解析器了,就是取一个项目,判断其是否符合条件谓词 p,若符合则成功,否则失败。
seq, possible, lookahead1, someFold, manyFold 这是用于组合子解析器的单位satisfy, charP, elemP, kwP, wsP, ws0P 这是用于 seq 和 many / some 解析器的单位此外:
Feeder 是输入字符/对象流的称呼,它上面可以使用:
lastIsCR / lastIsLF / lastIsCRLF / eof / hasNext 判断方法
duplast / reset1Tho 方法(reset1Tho 是给一些不消耗字符但是父 解析器会默认 next 的解析器做一个额外的副作用:保存一个字符)
loc / desc 方法:用于描述
logs / leave 方法:解析组合子的上下文支持利用栈,如果提供了栈,则 logs 和 leave 方法对应 push 和 pop。否则,什么都不肝(用于区分解析模式是调试与否)
lastItem / nextItem : lookAhead1 迭代器的标准数据视窗
next / nextNext : 移动数据视窗
const p = require('./fp').parserc;
比如说:let f = new p.Feeder('Hello, cruel world.\n(but...)');
> f.desc()
'<feed>:1:0 (pos=0@<begin>)'>
f.loc()
'<feed>:1:0' >
f.next()
'H'>
f.loc()
'<feed>:1:1'
>
while (f.next() != '.');
> f.desc()
"<feed>:1:19 (pos=19@`.', next=`\n')" FP.js 的 Feeder 对象会自动为你解决 CR / LF / CRLF 的换行符问题,三者中任意一种都能正确处理,不会出现行号不一致的情况。
>
while (f.next() != '.');
> f.desc()
"<feed>:2:5 (pos=25@`.', next=`.')"FP.js 的 Feeder 本身就是一个流的封装,所以你可以使用所有 FP.js 提供的流操作:
const s = require('./fp').stm;
—>
s.dropWhile(x => x === '.', f.stream);
[ '.', '.' ]>
s.desc()
"<feed>:2:5 (pos=25@<eof>, next=`.')"不过,使用这样的东西会打破 Feeder 的封装,所以正确的方法是引入
fp.fn.bound, 然后把 bound(s, 'next') 传入需要流参数的地方—— 解析器们
上面提到的 wsP(), ws0P(), kwP() 什么的,全都是可以复用松耦合的解析器。
绝大部分解析器(可能解析失败的那种),为了提供一个良好的用户界面,都存在着一个
fmt 函数和 error message 的系统:+ ws0P 是不可能失败的解析器(因为它要解析空格的数目,但是也可以是 0 个,就是说不可能解析不成功)
+ wsP 接受 msg 和 fmt,若是感受不到空格,返回
pfail(fmt(feeder, msg)), fmt 的默认值为返回 msg.例子:
var ps = p.wsP('有空格的话会好很多');
var pp = p.run(ps);
> pp('')Either { inner: '有空格的话会好很多', left: true }
> pp(' ')Either { inner: 1, left: false }
> pp(' ')Either { inner: 3, left: false }
(tips: 如果项目本身定义的四元素 CR/LF/Tab/Space 不满足你对空格的需求,可使用 setWs 函数改变默认集合,当然我修改后直接 push 缺失的项目也可以)
+ elemP 接受 (iset, m, fmt),其中 fmt 默认为
(s.eof()? 'Unexpected EOF. ':'') + 'Expecting one of ['+iset.join(', ')+']' +_sp(m)
例如,>
ps = p.elemP('富强x民主x文明x和谐x自由x平等x公正x法治x爱国x敬业x诚信x友善'.split('x'), '不能是不和谐的项目呢。');
[Function: containsP]>
var pp = p.run(ps);
> pp(['富强'])Either { inner: '富强', left: false }
> pp(['不富强'])Either {
inner:
'Expecting one of [富强, 民主, 文明, 和谐, 自由, 平等, 公正, 法治, 爱国, 敬业, 诚信, 友善] 不能是不和谐的项目呢。',
left: true }
> pp(['艹'])Either {
inner:
'Expecting one of [富强, 民主, 文明, 和谐, 自由, 平等, 公正, 法治, 爱国, 敬业, 诚信, 友善] 不能是不和谐的项目呢。',
left: true }
上面的例子不是字符流的(FP.js 的解析组合子有意泛化一些),下面是一个字符流的例子:
>
ps = p.elemP('江胡习赵王董刘波64'.split(''), '非常抱歉,输入过于和谐呢。'); pp = p.run(ps);
[Function: runParser]> pp('不和谐')
Either {
inner:
'Expecting one of [江, 胡, 习, 赵, 王, 董, 刘, 波, 6, 4] 非常抱歉,输入过于和谐呢。',
left: true }
> pp('江不和谐')
Either { inner: '江', left: false }(显然这只有一项,不过过会就能够看到松耦合组合子的强大组合能力了)
+ kwP(kwstr, msg, fmt) 是关键字的解析组合子。
默认 fmt 是
(s.eof()? 'Unexpected EOF. ':'') + 'Expecting keyword <'+str+'>@'+i+ _sp(m)
失败的时候会用 feeder 和 i 来(失败的匹配位置)调用 fmt 函数>
ps = p.kwP('你们啊,Naive!', 'Too young.'); pp = p.run(ps);
> pp('你们')Left('Unexpected EOF. Expecting keyword <你们啊,Naive!>@2 Too young.')
> pp('你们啊,Naive!')Right('你们啊,Naive!')
很多大一点的组合,会抛出 fmt 返回的异常对象+ charP (ch, m, fmt)
这个家伙消耗一个字符,返回一个字符。
> ps = p.charP('🐸'); pp = p.run(ps);
> pp('蛤')Left('expecting 🐸')
> pp('🐸')Right('🐸')
Too young! + satisfy(p, m, fmt) 这是最后一个弟弟(划掉)解析器了,就是取一个项目,判断其是否符合条件谓词 p,若符合则成功,否则失败。
satisfy 因为 FP.js parserc 已经有很多字符流的弟弟解析器,不能在解析普通字符流时很好地发挥实力,必须在解析诸如命令行参数 argv 的时候,才能派上用场。ps = p.satisfy(x => x.startsWith('--'), '需要一个 -- 开头的参数'); pp = p.run(ps);
> pp(['foo.txt'])Left('需要一个 -- 开头的参数')
> pp(['--f', 'foo.txt'])Right('--f')
—总是觉得曾经在酷安过的一些人变的奇怪了呢... 为什么 我应该以 『您』 来称呼... 为什么我说了几次还是被称为“您”
难道我就真的有这么令人讨厌?!因为我总是炫耀自己的技术,而其实我不懂的东西还有很多,所以我值得被人... 如此特殊的看待?
难道我就真的有这么令人讨厌?!因为我总是炫耀自己的技术,而其实我不懂的东西还有很多,所以我值得被人... 如此特殊的看待?
/tmp/duangsuse.sock
总是觉得曾经在酷安过的一些人变的奇怪了呢... 为什么 我应该以 『您』 来称呼... 为什么我说了几次还是被称为“您” 难道我就真的有这么令人讨厌?!因为我总是炫耀自己的技术,而其实我不懂的东西还有很多,所以我值得被人... 如此特殊的看待?
This media is not supported in your browser
VIEW IN TELEGRAM
本频道和之前的 duangsuse::Echo 都非常密集的在发一些类似鸡毛蒜皮的技术相关细节,是的,它们不『内敛』
而且都不是好看的东西,都不是 Geek 和 Geek 程序员们喜欢的东西,它们非常鸡毛蒜皮而且不好看、不实用。
他们很显眼,而且我的确有刻意在宣传一些广播...
但是这就意味着我炫耀、我自负、我不够友好吗?我真的没有把自己喜欢的这些东西当成过表演,我讨厌只是为了做给人看的那种事情... 只是因为我要『分享』,顺便自己学习一下而已。
我真的觉得很奇怪.... 为什么会对我这样,因为之前的几次撕逼?还是因为所有人都发生了改变?因为我自己也背负了什么东西而我没注意到?而且我现在还在炫耀?是因为我没有去做一个隐藏自己的『大佬』?
没人告诉我,我真的猜不到...
而且都不是好看的东西,都不是 Geek 和 Geek 程序员们喜欢的东西,它们非常鸡毛蒜皮而且不好看、不实用。
他们很显眼,而且我的确有刻意在宣传一些广播...
但是这就意味着我炫耀、我自负、我不够友好吗?我真的没有把自己喜欢的这些东西当成过表演,我讨厌只是为了做给人看的那种事情... 只是因为我要『分享』,顺便自己学习一下而已。
我真的觉得很奇怪.... 为什么会对我这样,因为之前的几次撕逼?还是因为所有人都发生了改变?因为我自己也背负了什么东西而我没注意到?而且我现在还在炫耀?是因为我没有去做一个隐藏自己的『大佬』?
没人告诉我,我真的猜不到...
唉... 如果真的是这样那还简单了。 我完全可以自己发自己的。
就像本频道,现在关注数平均阅读量不到 duangsuse::Echo 的零头。
实际上我不在乎有多少人看,我在乎有多少人看了以后能理解、明白,得到哪怕是一点点的见识甚至知识、系统的知识甚至新技能,或许以后还做的比我好。
我真的不在意什么阅读量、什么粉丝,我只是想给可能关心的人分享而已
不仅仅我不以阅读量、关注论事,而且对于看到、订阅 ::Echo 的人,其实得知很大一部分(甚至全部,包括之前我以为的一些至少有类似爱好的大佬)都不会关心我现在可能在关心的一些方面的知识后,我真的感觉很失望,我的分享没有起到任何作用,知识被人快速跳过了而已,没有哪怕一个点是被 get 到了的,也没人去编程实践、或者进行理论上的分析。
我觉得哪怕是有人稍微往里面看一点,一点能发现我真的不是在装大佬、真的不是刻意地在做什么莫名其妙的事情、我真的不是在炫耀什么
可惜我没看到哪怕是一个人 真正有 这一点意识,大概他们都去写论文、补习、刷题了(唉...
我真的不懂,为什么『裸体』的知识这么容易被人唾弃、讨厌,难道只有做出好看的东西,那些应用、后端、web、设计,你才有资格去『分享』?难道这些不配出来吓唬人?即使我的这一点分享,连冰山一角都算不上
有能耐的人应该去看看组合子逻辑和形式验证、机器学习、信号处理、程序分析程序变换、算法、PLD(可编程逻辑控制器) 编程,我说的『长文』是多么浅显的内容啊,难道因为这类知识要稍微『不文静』『外向』一点,就是万恶的?因为它在刻意伪装很厉害,真实很废?
难道有人走路就不会都能飞?
现在看来,很多群聊大概是完全无法承受我这闲人的密度吧... 虽然我真的是只发成品的...
就像本频道,现在关注数平均阅读量不到 duangsuse::Echo 的零头。
实际上我不在乎有多少人看,我在乎有多少人看了以后能理解、明白,得到哪怕是一点点的见识甚至知识、系统的知识甚至新技能,或许以后还做的比我好。
我真的不在意什么阅读量、什么粉丝,我只是想给可能关心的人分享而已
不仅仅我不以阅读量、关注论事,而且对于看到、订阅 ::Echo 的人,其实得知很大一部分(甚至全部,包括之前我以为的一些至少有类似爱好的大佬)都不会关心我现在可能在关心的一些方面的知识后,我真的感觉很失望,我的分享没有起到任何作用,知识被人快速跳过了而已,没有哪怕一个点是被 get 到了的,也没人去编程实践、或者进行理论上的分析。
我觉得哪怕是有人稍微往里面看一点,一点能发现我真的不是在装大佬、真的不是刻意地在做什么莫名其妙的事情、我真的不是在炫耀什么
可惜我没看到哪怕是一个人 真正有 这一点意识,大概他们都去写论文、补习、刷题了(唉...
我真的不懂,为什么『裸体』的知识这么容易被人唾弃、讨厌,难道只有做出好看的东西,那些应用、后端、web、设计,你才有资格去『分享』?难道这些不配出来吓唬人?即使我的这一点分享,连冰山一角都算不上
有能耐的人应该去看看组合子逻辑和形式验证、机器学习、信号处理、程序分析程序变换、算法、PLD(可编程逻辑控制器) 编程,我说的『长文』是多么浅显的内容啊,难道因为这类知识要稍微『不文静』『外向』一点,就是万恶的?因为它在刻意伪装很厉害,真实很废?
难道有人走路就不会都能飞?
现在看来,很多群聊大概是完全无法承受我这闲人的密度吧... 虽然我真的是只发成品的...
Telegram
duangsuse::Echo
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。
技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。
技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Forwarded from Deleted Account
我开始觉得这些会貌似占满整个屏幕的分享链接和贴代码是错误的决定,
如果大家 觉得对交流有妨碍的话,请务必要告诉我,我可以发短一些(
如果大家 觉得对交流有妨碍的话,请务必要告诉我,我可以发短一些(