/tmp/duangsuse.sock
23 subscribers
303 photos
3 videos
92 files
337 links
从 duangsuse::Echo (@dsuse) 跟进出来的分支,将在作者恢复原帐号访问的时候合并删除。
Download Telegram
/tmp/duangsuse.sock
啊,那个我没有考虑到,其实... 写的插件还可以讲一下,所以前端给 #HTML #JavaScript 之前因为 Fx 阅读模式里面 link anchor 有 underline(decoration) 所以想加去这个的 CSS,后来才知道本来就没有... 如果有的话,可以 a { text-decoration: none; } 接下来简要说说几个小辅助插件了 首先是 NSFW Template,这使用到了 HTML5 的新 <template> tag bound 本来确实可以利用 prope…
那我也就只好快速地讲一下这七个插件了,发了文我还有很多事...

首先是
== 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 );
addCSSClass = name => nd => nd.classList.add(name);

这个插件就是去添加一些可选显示的内容,包裹在 <template attr> 标签里

== 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)

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 ( 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)
add2 = add 2 = \b. (2 + b)
add2 1 = 3

它可以提供『不能重写』的参数默认值(因为那里 2 就是立即值或者 UpValue 了,递归的时候这个东西不是参数的)

可是很多函数式编程语言,比如 Haskell 是这个样子,JavaScript 就不是这个样子。

不过有 Function.prototype(参见我之前写的 LuaOOP 原型面向对象继承实现).bind
可以给指定默认参数

不过,指定就最好得一次指定完,不然很麻烦(因为 this 要传来传去的... 而且你还得手写 curry 参数的调用)

我希望这样的 curry:

var puts = bound(matrix, 'putXY').curry()
var puts00 = puts(0)(0)
puts00('0,0')

然后我早上赖床(逃跑)的时候就在想,该怎么实现这个多参数 curry 呢?

开始我很 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
/tmp/duangsuse.sock
...我多么希望快速的讲完啊,可是又讲的很细,现在很晚了... 说功能和要点算了。 Night 的要点就是:提供文档阅读视图的用户风格选项 首先它自动根据当前时间,切换默认 Night/Day,其次,它支持: + 配色风格:Day/Night/Old + 字体:有无衬线 + 字号:大小调整 + 容器宽度:大小调整 实现:提供一个 autoDayNight() 导出逻辑来实现自动配色,没有其他要点。 Reflink preview 的要点 按照 invisible dt 提供的元数据,给指定的…
最后那个就是非常简单的递归数据构造逻辑,最后的结束扫描只是因为我们觉得『出现比它大的 heading 代表它结束了』而已,如果知道 ending 的话当然应该提早返回

构造出的数据非常简单,思考一下为什么递归扫描(此时把子树的 level 看作根文档)

相关知识,Python、Haskell 的缩进语义也是可以通过类似判断实现的,只不过使用 DOM Tree 接口去解析会方便很多
/tmp/duangsuse.sock
啊,那个我没有考虑到,其实... 写的插件还可以讲一下,所以前端给 #HTML #JavaScript 之前因为 Fx 阅读模式里面 link anchor 有 underline(decoration) 所以想加去这个的 CSS,后来才知道本来就没有... 如果有的话,可以 a { text-decoration: none; } 接下来简要说说几个小辅助插件了 首先是 NSFW Template,这使用到了 HTML5 的新 <template> tag bound 本来确实可以利用 prope…
以上的函数库还要加上一些方便的 operator:

forIter 要能够接受 InterruptedException 来支持内部函数去 breakIter() nextIter() 打断/

take / drop / collect = take.curry1(Infinity)
takeWhile / dropWhile
zipWith(f, xs, ys)
map(f, xs)
filter(p, xs)
iterBy(node, docall('get', 'nextSibling'))
ap(sub, [1,2]) 这种

因为是手写就不 AMD/CommonJS 了
还是支持 ES5 算了,眼花的特性,毕竟 ES5 也老高级了...
JavaScript 面向语言编程应该非常简单的说,使用 副作用的流完成 parser combinator...
这样就 好看 可是不... 总感觉有些东西
这个 dropWhile 本来可以讲一个问题的,可是觉得没有必要讲了(就是一个同时持有当前项和 lookAhead 项目的问题,对于 stream 式的差别只在时序、这里只在最后一次迭代)
一个时序问题,修改前的程序会多迭代一次、跳过流里的一项,现在的程序不会了(移动 n!=0 到前面,短路 &&...)
写各种 list operator 写到手软... 还没有开始写业务逻辑...
fp.js
9.3 KB
#FP #JavaScript #Haskell 🤔 绝对要开始写业务逻辑了...
Forwarded from Deleted Account
def makeCats(xs, t); t.times { xs = xs.map { |x| xs.map { |it| it+x }  }.flatten }; return xs; end
Forwarded from Deleted Account
Forwarded from Deleted Account
makeCats('a'..'z', 1)

=> ["aa", "ba", "ca", "da", "ea", "fa", "ga", "ha", "ia", "ja", "ka", "la", "ma", "na", "oa", "pa", "qa", "ra", "sa", "ta", "ua", "va", "wa", "xa", "ya", "za", "ab", "bb", "cb", "db", "eb", "fb", "gb", "hb", "ib", "jb", "kb", "lb", "mb", "nb", "ob", "pb", "qb", "rb", "sb", "tb", "ub", "vb", "wb", "xb", "yb", "zb", "ac", "bc", "cc", "dc", "ec", "fc", "gc", "hc", "ic", "jc", "kc", "lc", "mc", "nc", "oc", "pc", "qc", ...]
Forwarded from Deleted Account
递归下来懒得想了,跑路(不过就是每次往上面一层去 map (\x flatMap ([x] ++)) xs

就可以构造出 a (a) b (a) ... z(a), a(b)... a (aa), z(aa), a(ab)....
Forwarded from Deleted Account
可以(

#define GETC (ch = getchar())
static inline int readInt() {
signed int n = 0;
char ch = '\0';
while (isspace(GETC));
if (ch == '-') { n = ~n; GETC; }
//reads natural part
while (isdigit(GETC))
n = (n*10) + (ch-'0');
return n;
}

类似解析组合子的布局
Forwarded from Deleted Account
总之,现在看起来生成的程序是有差别,不过我觉得还是相信编译优化的好,毕竟这都几十年的积累了,若是真的快它要把普通 add sub mul 指令都优化成位运算的

知乎上之前有篇关于这类问题的描述,可以找找,总之就是这样...

我觉得,把程序写好看是最重要的,各种很 dirty 的 workaround 和手工的变形,能免则免,避免黑科技、避免魔数什么的

希望两位以后的程序,尽可能往简单易维护的方向写... 或许过几天你就会发现简单的价值所在

推荐文章:如何写出无法维护的代码

Have a nice night coding.
Forwarded from Deleted Account
的确有点,短谁都是的,不对称无规范是要命的
Forwarded from Deleted Account
dijkstra 图搜索也的确是每一步考虑到更多的条件,构造有更多的数据...
Forwarded from Deleted Account
我学过 dijkstra 算法(就是主要一个 map 记录某 node(edge) 的最小开销和一层路径,最后根据 end edge 的路径回溯一个一个地方的回来),不过我没写过,而且不是特别熟悉 C++
不过我觉得代码风格是很重要的

良好的代码风格可以证明你拥有清晰的逻辑,何况本来常量、函数、本地变量、全局变量、类型名称使用不同的命名风格本来就有益于使得编程更简单易读