Forwarded from Deleted Account
虚表是每次递归查找到了复制,并查树也是
两者都是传递性,不过一个是为了缓存(也是性质)传递、一个是一元相关性传递
两者都是传递性,不过一个是为了缓存(也是性质)传递、一个是一元相关性传递
Forwarded from Deleted Account
cats 就是找某个 node 最远的爹,然后一下解决所有娃子的传递性问题,concat 到一起去
对应的 find 实现是为了践行这个理念,顺便有缓存剪枝
可是具体的,比如 find 的
对应的 find 实现是为了践行这个理念,顺便有缓存剪枝
可是具体的,比如 find 的
(make me dptr) 到底是不是删掉也正确,不清楚...我终于知道为什么很多出版物里都能找到不完美的地方了,原来尽可能去修改就有这么难啊...
本来已经修改了很多地方,换掉了不少有问题或者可以改进的表达,再看一遍,我又找到比原来还多数目的...
本来已经修改了很多地方,换掉了不少有问题或者可以改进的表达,再看一遍,我又找到比原来还多数目的...
目前我依然在修改,将在基本完成后对内容进行最后的校验
今天明天内,我会给它加一些 JavaScript 小挂件来提升阅读体验
目前还在对内容进行校对
今天明天内,我会给它加一些 JavaScript 小挂件来提升阅读体验
目前还在对内容进行校对
Forwarded from 荔枝木
“我的朋友们啊,”他说,“我——我——”
但是他哽住了,他说不下去了。
他转身朝着黑板,拿起一支粉笔,使出全身的力量,写了四个大字:“熊猫万岁!”
然后他呆在那儿,头靠着墙壁,话也不说,只向我们做了一个手势:“关站了,你们走吧。”
但是他哽住了,他说不下去了。
他转身朝着黑板,拿起一支粉笔,使出全身的力量,写了四个大字:“熊猫万岁!”
然后他呆在那儿,头靠着墙壁,话也不说,只向我们做了一个手势:“关站了,你们走吧。”
刚才被冰封批判了一番,两年进步的的确是很少了(
我还有脸讲什么 #Haskell, Monad 都不会
连 Identity/Reader Monad 都还无法默写,真是...
而且我还没有拿 Haskell 写过解释器,一个计算器求值的都是常量、纯的无参表达式,这怎么能叫做解释器呢...
推荐大家去关注 github.com/HoshinoTented 大佬,大小姐很擅长各种算法和 Kotlin... 和 Haskell,我就只是会点无聊的... 泪目
我还有脸讲什么 #Haskell, Monad 都不会
连 Identity/Reader Monad 都还无法默写,真是...
而且我还没有拿 Haskell 写过解释器,一个计算器求值的都是常量、纯的无参表达式,这怎么能叫做解释器呢...
推荐大家去关注 github.com/HoshinoTented 大佬,大小姐很擅长各种算法和 Kotlin... 和 Haskell,我就只是会点无聊的... 泪目
GitHub
HoshinoTented - Overview
impl !Ord for Self {}. HoshinoTented has 41 repositories available. Follow their code on GitHub.
https://blog.hoshino9.org/2019/07/26/how-to-create-a-wonderful-type.html
艹,刚才看星野野大佬的博文才知道
就只告诉我
艹,刚才看星野野大佬的博文才知道
newtype 是简易 Product 的构造方法(不能是 Sum type),之前欧阳继超大佬的猫论指南就只告诉我
newtype 是定义同构类型(newtype Identity a = Identity { runIdentity :: a })...blog.hoshino9.org
Haskell 如何打造爆款数据类型
数据类型是 Haskell 中的重要知识之一这篇文章讲教你从一无所知到随手打造爆款数据类型
啊,那个我没有考虑到,其实... 写的插件还可以讲一下,所以前端给 #HTML #JavaScript
之前因为 Fx 阅读模式里面 link anchor 有 underline(decoration) 所以想加去这个的 CSS,后来才知道本来就没有...
如果有的话,可以
首先是 NSFW Template,这使用到了 HTML5 的新 <template> tag
bound 本来确实可以利用 property/reflect/proxy 来比较魔法的(而且不会担心性能问题,可以缓存)
不过有点长,而且不明显,所以这里用简单的方法
== Abbr view
这个逻辑比较简单,类似 NSFW template。因为在一些设备上不能使用 "hover" 查看 abbrev... 只好在点击时在后面插入内 abbr 的实际容了。
写入的时候先新建一个 attribute,用于记录 abbr 已经被展开,每次 switch 的时候判断一下 shown => hide、hidden => show
== Night
== Reflink Preview
== Music Player
== Footnote Xref
== Contents Tree
之前因为 Fx 阅读模式里面 link anchor 有 underline(decoration) 所以想加去这个的 CSS,后来才知道本来就没有...
如果有的话,可以
a { text-decoration: none; }
接下来简要说说几个小辅助插件了首先是 NSFW Template,这使用到了 HTML5 的新 <template> tag
bound 本来确实可以利用 property/reflect/proxy 来比较魔法的(而且不会担心性能问题,可以缓存)
不过有点长,而且不明显,所以这里用简单的方法
function bound(self, meth) { return self[meth].bind(self); }
function intoIter(xs) { var i = 0;
return function
iterator() { return (i<xs.length)? { value: xs[i++], done: false }
: {done:true}; }; }
function tryIter(xs) { if (!Symbol) return intoIter(xs); return bound(xs[Symbol.iterator](), 'next'); }
function forIter(it, f) { var xc; while (xc = it()) { f(xc.value); if (xc.done) break; } }
function args2ary(argsv) { var ary=[]; forIter(tryIter(argsv), bound(ary, 'push')); return ary; }
Function.prototype.flip = function() { var method = this; return function call() { return method.apply(method, args2ary(arguments).reverse()); }; };
Function.prototype.curry1 = function(x0) { return this.bind(this, x0); }
;
Object.prototype.lets = function(f) { return f(this); }
Function.prototype.andThen = function(g) { var f=this; return function composition(x) { return g(f(x)); }; }
foreach = tryIter.andThen(bound(forIter, 'curry1'));
function makes$_(fname) { return function(it) { return it[fname](); }; }
function makes_() {
var it = new Object();
return new Proxy(it, { get: function(t,a,p){return makes$_(a);} });
}
_ = makes_();
cssSelect = bound(document, 'querySelector');
var merges = bound(document, 'importNode').flip().curry1(true);
其中业务逻辑 部分,上面的留作代码重用function showTemplate(attr, init) {
var templates = cssSelect('template[' + attr + ']=""');
var prepend = function (nd, x) { nd.parentNode.insertBefore(x, nd); };
templates.forEach(function(x) {
var mix = merges(x.content);
if (typeof init =='function') init(mix);
prepend(x, mix);
});
}
function removeElements(cs) { cs.lets(cssSelect).each(_.delete); }
function addCSSClass(cl) { return function(e){ e.classList.add(cl); }; }
showTemplate('nsfw', addCSSClass('nsfw'));
我还得写很多.... 所以代码重用、优先划分好模块非常重要== Abbr view
这个逻辑比较简单,类似 NSFW template。因为在一些设备上不能使用 "hover" 查看 abbrev... 只好在点击时在后面插入内 abbr 的实际容了。
写入的时候先新建一个 attribute,用于记录 abbr 已经被展开,每次 switch 的时候判断一下 shown => hide、hidden => show
== Night
== Reflink Preview
== Music Player
== Footnote Xref
== Contents Tree
/tmp/duangsuse.sock
啊,那个我没有考虑到,其实... 写的插件还可以讲一下,所以前端给 #HTML #JavaScript 之前因为 Fx 阅读模式里面 link anchor 有 underline(decoration) 所以想加去这个的 CSS,后来才知道本来就没有... 如果有的话,可以 a { text-decoration: none; } 接下来简要说说几个小辅助插件了 首先是 NSFW Template,这使用到了 HTML5 的新 <template> tag bound 本来确实可以利用 prope…
... 我不该写 js 的,虽然好像我总是写错代码.... 怎么连 bounds 都忘记了
另外 JavaScript 想写简洁真难啊,看起来明明可以 point-free 的话 就不得不引入新匿名函数了
另外 JavaScript 想写简洁真难啊,看起来明明可以 point-free 的话 就不得不引入新匿名函数了
/tmp/duangsuse.sock
啊,那个我没有考虑到,其实... 写的插件还可以讲一下,所以前端给 #HTML #JavaScript 之前因为 Fx 阅读模式里面 link anchor 有 underline(decoration) 所以想加去这个的 CSS,后来才知道本来就没有... 如果有的话,可以 a { text-decoration: none; } 接下来简要说说几个小辅助插件了 首先是 NSFW Template,这使用到了 HTML5 的新 <template> tag bound 本来确实可以利用 prope…
艹!劳资不滋瓷 ES5 了,辣鸡浏览器看什么文章!
原有风格也不重写了,以后用 babel 算了!(嗳我为啥写 JS 啊)
原有风格也不重写了,以后用 babel 算了!(嗳我为啥写 JS 啊)
记录一种思维方式:
刚才在回答 @Zhai2333 大佬的问题时我提到了树(Trees)
我说(伪jzm 🐸)
我提到了树和 OI,这不禁使我想到了之前看 OI 入门书的二叉树,然后我就不禁考虑到了一个问题:完全二叉树(除了最后一层 leaf 外、每一层都有两个子节点)如果层数是 n 层,那么一共有多少个节点?(弄错问题了... 是第 n 层有多少节点、那个除了递归或者 sum 外,或者手动试着代数化简、我没办法)
本来是很 immediate 的内容(发答案了,就是 (n-1)**2 + 1)
n-1 是因为第 0 层很特殊、 +1 是补回第 0 层
我却想了一会(虽然开始我隐约有正确表达式的直觉,虽然只是一个伸展的树形图样,然后两层之间存在某种运算连接起来的那样)而且还体会到了之前完全不懂数学的恐惧... 😨
现在我得到了答案(莫名其妙就又想到了,噢,原来不每层就是前面的 n-1 层 *2 么)(我的递归素质就有这么差....)
同时又得到了两个思考方法:
1. 考虑递归程序的时候,把每层看成是自己想要的数据。
比如上面的算层数、每个节点就是一个『1』
这样你就能有
给我一种感觉 好像要反过去回溯的时候 才能感受到这种可能...
2. 考虑递归程序的时候,只看一层不够就看两层
bin0 = bin1 + 1 + bin1
bin1 = bin2 + 1 + bin2
....
bin2 = 1
3. 可视化数学计算,这样你就可以把数据结构和数学式子一起对称着看了
比如,要有把乘方看成树形的能力:
首先,我不知道为什么就没有看根节点...
然后,每一层都有 2 个子树、直到 (n-1) 层(最后一层没有子树只有叶子,要不然你也不能非惰性地构造 infinity data structure)
本来我开始没有想出来的原因是我觉得这是递归的,没法直接算...(其实也是可以的)(废话)
后来发现,其实要求第 n 层(第 0 层就是 1),只需算 n**2 即可(每层都叉一次 *2、叉了这么多次,有这么多个 1)
...
唉,现在就只有这点水平
不过你看完后就发现,其实“数学”和编程从本质上看都是没有差别的,解析数学、微积分什么的也是属于数学的 buff,但都是很『基础』的东西
刚才在回答 @Zhai2333 大佬的问题时我提到了树(Trees)
我说(伪jzm 🐸)
但是我想,我见到你们这样热情啊,一句话不说也不好。所以你刚才你一定要——在宣传上将来如果你们报道上有偏差,你们要负责。我没有说这很简单(逆向 JavaScript),没有任何这个意思。但是你问……你一定要觉得要问我……对这类代码保护措施有没有方法。我能不能写 AST 模式识别重构器?AST 处理是编译原理优化编译入门技能,我怎么能不会?...
你们毕竟还 too young(太年轻),明白这意思吧。我告诉你们我是身入树状图了,见得多了!啊,OI 入门的哪一个算法我没讲过?码农他们——你……你们要知道,美国的 @ice1000 ,那比你们不知道高到哪里去了。啊,我跟他谈笑风生!所以说编程啊,要……还是要提高自己的知识水平!懂我的意思——识得唔识得啊?(懂不懂啊?)(逃跑,,,我很菜的,不过希望有点幽默的说
我提到了树和 OI,这不禁使我想到了之前看 OI 入门书的二叉树,然后我就不禁考虑到了一个问题:完全二叉树(除了最后一层 leaf 外、每一层都有两个子节点)如果层数是 n 层,那么一共有多少个节点?(弄错问题了... 是第 n 层有多少节点、那个除了递归或者 sum 外,或者手动试着代数化简、我没办法)
本来是很 immediate 的内容(发答案了,就是 (n-1)**2 + 1)
n-1 是因为第 0 层很特殊、 +1 是补回第 0 层
我却想了一会(虽然开始我隐约有正确表达式的直觉,虽然只是一个伸展的树形图样,然后两层之间存在某种运算连接起来的那样)而且还体会到了之前完全不懂数学的恐惧... 😨
现在我得到了答案(莫名其妙就又想到了,噢,原来不每层就是前面的 n-1 层 *2 么)(我的递归素质就有这么差....)
同时又得到了两个思考方法:
1. 考虑递归程序的时候,把每层看成是自己想要的数据。
比如上面的算层数、每个节点就是一个『1』
这样你就能有
root = 1 + bin这种图的直觉了,然而光有它还不够,你要能看 (1 + 1) | (1 + 1) 换得成什么...
bin = bin + 1 + bin
给我一种感觉 好像要反过去回溯的时候 才能感受到这种可能...
2. 考虑递归程序的时候,只看一层不够就看两层
bin0 = bin1 + 1 + bin1
bin1 = bin2 + 1 + bin2
....
bin2 = 1
3. 可视化数学计算,这样你就可以把数据结构和数学式子一起对称着看了
比如,要有把乘方看成树形的能力:
2**3=4. 最后上面的问题我是怎么解决的,
(2*2)+2
/ \
2 2
首先,我不知道为什么就没有看根节点...
然后,每一层都有 2 个子树、直到 (n-1) 层(最后一层没有子树只有叶子,要不然你也不能非惰性地构造 infinity data structure)
本来我开始没有想出来的原因是我觉得这是递归的,没法直接算...(其实也是可以的)(废话)
后来发现,其实要求第 n 层(第 0 层就是 1),只需算 n**2 即可(每层都叉一次 *2、叉了这么多次,有这么多个 1)
...
唉,现在就只有这点水平
不过你看完后就发现,其实“数学”和编程从本质上看都是没有差别的,解析数学、微积分什么的也是属于数学的 buff,但都是很『基础』的东西
回来的时候我考虑了一下那个 C 莫名其妙的多维度数组的实现,以及为什么我平时用 y-first scanning
y-first 的意思就是说,当我扫描二维矩阵的时候,我会用
因为一般数据都是从左到右扫描输入的,这样的话,按折行(下一个 y)切分会好写一些,不需要去每个去专门索引 matr[x][(0..len]]
前者的图示看起来像是这样:
int matr[y=6][x=4]
得到了
不过这很 naive:因为它只是幼稚的数据描述策略问题而已,还有一个不那么 naive 的:映射到一个一维数组,怎么递归去计算这个
你以为这是一个『n 维数组』,实际上它是一种对存储空间的描述,实际上内存是连续的,对于这种『每个维度长度都不同』的该怎么办呢?
方法就是类似上面的计算。
C 的数组给人不符合直觉的感觉,和指针、const modifier 什么的一样,很不对称...
我真的不知道这些和 typenames 有啥不一样的地方,为什么他们就是用一种不同的方式来描述
char * 这个类型是 char 的指针
char 这个类型是 char * 的指针
const char[] 是 const char 的数组
(C++) char &a[] 是 char 引用... 的数组
char (&a)[] 是引用数组 char[]
最后,
char* 是 char 的指针可是 char[n][m] 是代表一个多维数组,可是这个数组呢?
如果看作是数组的数组,实际上它是 长度 n 关于 char[m] 的数组
听起来很正常,问题是 (char[n])[m] 看起来怎么都类似长度 m 元素 char[n] 的数组... 就很奇怪
我...
其实这么倒着放还可能是有原因的,因为怎么看好像区分一维数组和多维数组是一个蛮正常的思路,数组的数组才不应该存在
可是对编译器就有这么一个问题:怎么分配它、怎么拿到元素的指针
分配数组的数组很简单,看看这个 Haskell 程序:
当然,
那么因为乘法是有交换律的,所以在两种数组上分配大小计算方式都有效。
再来看看索引的计算
对于递归的数组,还是比较简单的
思量一下,算 [1][3],首先我们有一个 [1] 的大小,然后乘索引 [3] 即可
其实本身没有错(迫真),我的例子错了...
其实这个的确写对了,就是递归求基索引(idx*dim),再加上自己的索引而已,问题在于 size 没有得到显式地体现(迫真
比如有 (a[2])[10],(a[0])[1] 就是 1、(a[1])[0] 就是 10
这算是递归入门... 至于那个 C 的多 dimen 数组,倒过来算就可以了,做出来就行...
y-first 的意思就是说,当我扫描二维矩阵的时候,我会用
matr[y][x] 这种索引方式因为一般数据都是从左到右扫描输入的,这样的话,按折行(下一个 y)切分会好写一些,不需要去每个去专门索引 matr[x][(0..len]]
前者的图示看起来像是这样:
int matr[y=6][x=4]
x当我们需要
3 0 0 0 0 0 0
2 0 0 0 0 0 0
1 0 0 0 0 0 0
0 0 0 0 0 0 0
+ 0 1 2 3 4 5 y
((int[6][4]) matr)[1] 的时候,得到 (matr + 4*1) 的位置得到了
2: 0 0 0 0 0int matr[x=4][y=6]
y它看起来像是这个样子
5 0 0 0 0
4 0 0 0 0
3 0 0 0 0
2 0 0 0 0
1 0 0 0 0
0 0 0 0 0
+ 0 1 2 3 x
不过这很 naive:因为它只是幼稚的数据描述策略问题而已,还有一个不那么 naive 的:映射到一个一维数组,怎么递归去计算这个
a[n][m] 的索引呢?你以为这是一个『n 维数组』,实际上它是一种对存储空间的描述,实际上内存是连续的,对于这种『每个维度长度都不同』的该怎么办呢?
方法就是类似上面的计算。
C 的数组给人不符合直觉的感觉,和指针、const modifier 什么的一样,很不对称...
我真的不知道这些和 typenames 有啥不一样的地方,为什么他们就是用一种不同的方式来描述
char * 这个类型是 char 的指针
char 这个类型是 char * 的指针
const char[] 是 const char 的数组
(C++) char &a[] 是 char 引用... 的数组
char (&a)[] 是引用数组 char[]
最后,
char* 是 char 的指针可是 char[n][m] 是代表一个多维数组,可是这个数组呢?
如果看作是数组的数组,实际上它是 长度 n 关于 char[m] 的数组
听起来很正常,问题是 (char[n])[m] 看起来怎么都类似长度 m 元素 char[n] 的数组... 就很奇怪
我...
其实这么倒着放还可能是有原因的,因为怎么看好像区分一维数组和多维数组是一个蛮正常的思路,数组的数组才不应该存在
可是对编译器就有这么一个问题:怎么分配它、怎么拿到元素的指针
分配数组的数组很简单,看看这个 Haskell 程序:
module Dim where这个『神奇』的递归程序是做什么?就是 items * size 而已,而 item 的 size 就是下一层的大小,如果没有了实际上还得在叠加一层,这时候用 (*) 乘法的透明操作数 1 即可
type Size = Word
type Dims = [Size]
allocSize :: Dims -> Size
allocSize [] = 1
allocSize (l:ss) = l * allocSize ss
当然,
allocSize <=> foldl (*) 1 <=> product ...allocSize [1,2,3] = 1 * 2 * 3 *1 = 6,所以说 array 是 homogenus product type。那么因为乘法是有交换律的,所以在两种数组上分配大小计算方式都有效。
再来看看索引的计算
getElemPtr :: Dims -> Dims -> Size现在你有维度们的长度,给你索引们,请问:这个元素存在哪个位置?
对于递归的数组,还是比较简单的
思量一下,算 [1][3],首先我们有一个 [1] 的大小,然后乘索引 [3] 即可
getElemPtr [] [] = 0这样就好了,欸,好像是错的吧... 总之就是和 C 的弄混了... 算
getElemPtr (d:ds) (i:is) = (getElemPtr ds is) + (d*i)
getElemPtr [1,3] [0,1] = 6
getElemPtr [1,3] [0,2] = 9
其实本身没有错(迫真),我的例子错了...
其实这个的确写对了,就是递归求基索引(idx*dim),再加上自己的索引而已,问题在于 size 没有得到显式地体现(迫真
比如有 (a[2])[10],(a[0])[1] 就是 1、(a[1])[0] 就是 10
这算是递归入门... 至于那个 C 的多 dimen 数组,倒过来算就可以了,做出来就行...
/tmp/duangsuse.sock
啊,那个我没有考虑到,其实... 写的插件还可以讲一下,所以前端给 #HTML #JavaScript 之前因为 Fx 阅读模式里面 link anchor 有 underline(decoration) 所以想加去这个的 CSS,后来才知道本来就没有... 如果有的话,可以 a { text-decoration: none; } 接下来简要说说几个小辅助插件了 首先是 NSFW Template,这使用到了 HTML5 的新 <template> tag bound 本来确实可以利用 prope…
那我也就只好快速地讲一下这七个插件了,发了文我还有很多事...
首先是
== NSFW template,暴露主要函数
== Abbr view
这个逻辑比较简单,类似 NSFW template。因为在一些设备上不能使用 "hover" 查看 abbrev... 只好在点击时在后面插入内 abbr 的实际容了。
写入的时候先新建一个 attribute,用于记录 abbr 已经被展开,每次 switch 的时候判断一下 shown => hide、hidden => show
暴露主要函数
首先是
== NSFW template,暴露主要函数
showTemplate(attr, finit)、辅助函数 selectDelete(cs), addCSSClass(name) 就 OK 了function showTemplate(attr, finit = doNothing) {
let templates = cssSelect(templateHasAtt(attr));
foreach(templates) (function(it) {
let into = merge(it.content);
finitize(into, finit);
prepend(finit, into);
});
}
selectDelete = cs => cs.lets(foreach) ( _.delete );这个插件就是去添加一些可选显示的内容,包裹在 <template attr> 标签里
addCSSClass = name => nd => nd.classList.add(name);
== Abbr view
这个逻辑比较简单,类似 NSFW template。因为在一些设备上不能使用 "hover" 查看 abbrev... 只好在点击时在后面插入内 abbr 的实际容了。
写入的时候先新建一个 attribute,用于记录 abbr 已经被展开,每次 switch 的时候判断一下 shown => hide、hidden => show
暴露主要函数
hookAbbr(nd) 就可以了cssSelect('abbr').lets(foreach).lets(hookAbbr);
逻辑也很简单,就是设置 onclick,二元状态机,在自己之后展开function _hookAbbr(nd) {
return () => { if (!getAttr(nd, 'shown')) {
insertAfter(nd, makeTextTag(nd.title)); setAttr(nd, 'shown');
} else {
nd.nextSibling.delete();
} };
}
function hookAbbr(nd) { nd.onclick = _hookAbbr(nd); }
什么的...我多么希望快速的讲完啊,可是又讲的很细,现在很晚了...
说功能和要点算了。
Night 的要点就是:提供文档阅读视图的用户风格选项
首先它自动根据当前时间,切换默认 Night/Day,其次,它支持:
+ 配色风格:Day/Night/Old
+ 字体:有无衬线
+ 字号:大小调整
+ 容器宽度:大小调整
实现:提供一个 autoDayNight() 导出逻辑来实现自动配色,没有其他要点。
Reflink preview 的要点
按照 invisible dt 提供的元数据,给指定的 anchor 标记(需要使用 id 来指定)挂上钩子,在 iframe float 里弄出来个(可以 close 的)内容,并且提供原本内容的链接
Music player 的要点:对 WebAudio 的一个简单前端封装,不支持播放队列什么的,只能全局放一个(动态 WebAudio)
可以调整音量、pos 和播放/暂停,支持画 WebAudio 的 Spectrum Canvas 图
本身暴露一个 playAudio(url) 的 API,使用 XHR 流即可
Footnote Xref 的要点
在某个 section 下面(扫描直到下一个 h*)
扫描所有的 subscript 区段起始的 footnote 元素,
接下来利用 class .fn 查找内容的 footnotes(foreach),
按照 subscript 对应到实际的 footnotes (自己动态建立 id,a href 到对应 footnotes,同时 footnotes 也建立 a href 到自己的动态 id)
最后 Contents Tree 的要点是 DOM Tree recursive pattern destruct
从 root 开始枚举它的 nextSibling,
如果不是 header tag 则跳过
如果是同级别 header,加入
如果是低级别 header,递归扫描,加入
如果是高级别 header,结束扫描
阅读时间的要点
就是提供字数统计(只需要算 length 即可,大概的)、行数统计、引用 链接 和代码统计、header 统计
本身虽然可以做比较好的预估(比如说,pattern matching)
可是不大算这一点,只需要算好后写 min 、字数行数拿 , 3 位隔一位就可以了,点击以显示详情
说功能和要点算了。
Night 的要点就是:提供文档阅读视图的用户风格选项
首先它自动根据当前时间,切换默认 Night/Day,其次,它支持:
+ 配色风格:Day/Night/Old
+ 字体:有无衬线
+ 字号:大小调整
+ 容器宽度:大小调整
实现:提供一个 autoDayNight() 导出逻辑来实现自动配色,没有其他要点。
Reflink preview 的要点
按照 invisible dt 提供的元数据,给指定的 anchor 标记(需要使用 id 来指定)挂上钩子,在 iframe float 里弄出来个(可以 close 的)内容,并且提供原本内容的链接
Music player 的要点:对 WebAudio 的一个简单前端封装,不支持播放队列什么的,只能全局放一个(动态 WebAudio)
可以调整音量、pos 和播放/暂停,支持画 WebAudio 的 Spectrum Canvas 图
本身暴露一个 playAudio(url) 的 API,使用 XHR 流即可
Footnote Xref 的要点
在某个 section 下面(扫描直到下一个 h*)
扫描所有的 subscript 区段起始的 footnote 元素,
接下来利用 class .fn 查找内容的 footnotes(foreach),
按照 subscript 对应到实际的 footnotes (自己动态建立 id,a href 到对应 footnotes,同时 footnotes 也建立 a href 到自己的动态 id)
foreach cssSelect('.fn') {
let footnote = footnotes[fnid(it)]
let [fid, rid] = makeId.times(2);
let fa = makeAnchor(footnote, fid);
let ma = makeAnchor(it, rid);
drawTo(fa, rid);
drawTo(ma, fid);
}
重要的是生成双向引用需要同时拿到两个引用最后 Contents Tree 的要点是 DOM Tree recursive pattern destruct
subsec(root)这个函数构造 <h1> - <h5> 的列表,
从 root 开始枚举它的 nextSibling,
如果不是 header tag 则跳过
如果是同级别 header,加入
如果是低级别 header,递归扫描,加入
如果是高级别 header,结束扫描
阅读时间的要点
就是提供字数统计(只需要算 length 即可,大概的)、行数统计、引用 链接 和代码统计、header 统计
本身虽然可以做比较好的预估(比如说,pattern matching)
可是不大算这一点,只需要算好后写 min 、字数行数拿 , 3 位隔一位就可以了,点击以显示详情
关于 Curry 函数
Curry 是什么呢?本来 curry 的意思是 Lambda composition (
于是 Lambda calculus 有个 currying:
这样就有一个好,因为 lambda 抽象(abstraction) 的 variable substraction 可以给一些项目提供参数,而未必要立刻『实际执行』这个函数:
可是很多函数式编程语言,比如 Haskell 是这个样子,JavaScript 就不是这个样子。
不过有 Function.prototype(参见我之前写的 LuaOOP 原型面向对象继承实现).bind
可以给指定默认参数
不过,指定就最好得一次指定完,不然很麻烦(因为 this 要传来传去的... 而且你还得手写 curry 参数的调用)
我希望这样的 curry:
开始我很 naive 地想到,好像这是在针对 accumlator(计数器一样的东西,总之就是不断被『从自己构造』)
去操作,于是非常自然地想到了 foldl, foldr (其实 foldr 的确是可以的,而且 compose = foldr (.) id,不过这里不提右递归的方法)
可是我又想到,这显然是不行的。curry1 不管怎么样至少是接受一个参数返回接剩下参数的... 这样的话毫无意义,
因为我实际上一直在提供第一个参数。
然后我就想到了,既然是要构造这么一个递归的情况(第一次填 0、每次填第 n+1 个参数)
为什么不先构造 curry 最后一个参数的情况,然后串起来呢?这样不就可以了?
不过这当然是没有那么简单的,因为 bind 是 left-to-right,然后手动调用也得拿到每一个 curry 的参数
不过我们可以用 effect. 创建的时候弄一个 array 每层去 push 一下就好了
算了还是右递归 bind 吧(当然自己写也可以,就是给左边填一个参数返回右边剩下的)... 用 effect 没必要
#JavaScript #FP #Haskell
Curry 是什么呢?本来 curry 的意思是 Lambda composition (
f.g = \args -> f (g args) ) 很难去接受一些『多参数函数』(要不然处理起来就很迷人...)于是 Lambda calculus 有个 currying:
\x y. x = \x. \y. x (原本一个多参数的 lambda 现在变成了多个单参数 lambda 的组合)这样就有一个好,因为 lambda 抽象(abstraction) 的 variable substraction 可以给一些项目提供参数,而未必要立刻『实际执行』这个函数:
add = \a. \b. (a + b)它可以提供『不能重写』的参数默认值(因为那里 2 就是立即值或者 UpValue 了,递归的时候这个东西不是参数的)
add2 = add 2 = \b. (2 + b)
add2 1 = 3
可是很多函数式编程语言,比如 Haskell 是这个样子,JavaScript 就不是这个样子。
不过有 Function.prototype(参见我之前写的 LuaOOP 原型面向对象继承实现).bind
可以给指定默认参数
不过,指定就最好得一次指定完,不然很麻烦(因为 this 要传来传去的... 而且你还得手写 curry 参数的调用)
我希望这样的 curry:
var puts = bound(matrix, 'putXY').curry()然后我早上赖床(逃跑)的时候就在想,该怎么实现这个多参数 curry 呢?
var puts00 = puts(0)(0)
puts00('0,0')
开始我很 naive 地想到,好像这是在针对 accumlator(计数器一样的东西,总之就是不断被『从自己构造』)
去操作,于是非常自然地想到了 foldl, foldr (其实 foldr 的确是可以的,而且 compose = foldr (.) id,不过这里不提右递归的方法)
可是我又想到,这显然是不行的。curry1 不管怎么样至少是接受一个参数返回接剩下参数的... 这样的话毫无意义,
因为我实际上一直在提供第一个参数。
然后我就想到了,既然是要构造这么一个递归的情况(第一次填 0、每次填第 n+1 个参数)
为什么不先构造 curry 最后一个参数的情况,然后串起来呢?这样不就可以了?
不过这当然是没有那么简单的,因为 bind 是 left-to-right,然后手动调用也得拿到每一个 curry 的参数
不过我们可以用 effect. 创建的时候弄一个 array 每层去 push 一下就好了
算了还是右递归 bind 吧(当然自己写也可以,就是给左边填一个参数返回右边剩下的)... 用 effect 没必要
function _curryN(f, ff, n) {
if (n == 0) return ff;
return function nextDefault(x_)
{ return _curryN(f, ff.bind(f, x_), n-1); };
}
Function.prototype.curryN(n) { return _curryN(this, this, n); }
总之递归构造数据还是... 应该是符合直觉好 吧...#JavaScript #FP #Haskell