/tmp/duangsuse.sock
23 subscribers
303 photos
3 videos
92 files
337 links
从 duangsuse::Echo (@dsuse) 跟进出来的分支,将在作者恢复原帐号访问的时候合并删除。
Download Telegram
Forwarded from Deleted Account
唉,国内都这样的
Forwarded from Deleted Account
现在一个『优酷视频』,都弄什么『头条』啊,什么新闻,状态栏都是新闻,各种新闻。
Forwarded from Deleted Account
腾讯还有那种无法用语言吐槽的新闻,让人感觉很无力。
但它们说自己是『事实派』
QQ 也有新闻,但我在里面编辑一些文字准备发,偶尔都会莫名其妙因为不小心乱点一下就完全丢失了输入内容。
Dream It Possible
Delacey
华为手机自带的Dream It Possible
服了,服了,这都能预言到。
Forwarded from 永久封存 | Yuuta 台 | 😷 #Pray4Wuhan (wuhang2003)
Steam上的预言帝(
#life #CS @ice1000 冰封哥最近又换了几张貌似宠物鸡图片的 avatar。
原来显示屏还分 PWM(Pulse Width Moderation,脉冲宽度调制) 和 DC(Direct Current) 两种

还有 频闪、OLED、Amoled、拖影、偏色、(PWM)占空闭、刷新率、垂直更新、逐行刷新、隔行更新、果冻效应、运动模糊、灰阶、刷新频率矫正 什么的

显示相关的参数有对比度、亮度、色域、亮/暗处的显示效果、色准 等

https://t.me/c/1076357496/1734632 #hardware #CG
#life #statement莫言谈教养》(杂志上看到,没找到源头)
假如有人在谈论李白,
此时一个人出来问了一句,『李白是谁?』,这是最初级的没有教养,因为他不读书。
又有一个人出来哈哈大笑,『你连李白是谁都不知道啊!』,这是中级的没有教养,因为他不懂得尊重人。
另外一个人立刻开始就着李白的出生经历高谈阔论,这是最高级别的没有教养,因为他炫耀自己的知识。
Forwarded from Deleted Account
重要的不是学语言,是你先把 JavaScript 和 Java 里那一些基本的数据类型 primitives、控制结构给背下来,然后再去学「疯子」封装、抽象、继承、多态的面向对象,把这个抽象能力和编程经验给提上来,然后再怎么样自己想喽。

那个基本数据比如 boolean, byte, short, int, long, float, double, char, string 吧,加上 array, reference, function, error,基本数据结构比如 list, set, map 什么的,都记下来,以后整理认知用得到。

控制结构比如 seq, branch, repeat 吧,换成 Java 就是 {} 组合语句、if + if else + switch + ? : ternary、while, for, do while、break continue,然后再多看点高级语言虚拟机(HLLVM) 的指令流的学习一点编译原理的知识,认识一下老冯(Von Newmann) 那一套存储、运算、控制、输入输出的,自己写个解释器出来不就会好很多了么?多了解一下,学处理树形结构,写点子类型的 Evaluator 和 visitor pattern 的 tree walker 什么的。

对象和消息那个极其类似 UML(Unified Model Language) 术语的『给某 obj 发信号』就理解为『一群对象互相驱使』好了。
面向对象多态就是子类型、参数化类型,特殊多态函数 overload 和 C++ 那个类型转换貌似就是。

子程序的 vararg 了解和 C、C++ 用 stdarg.h 和 initializer_list、template 特化递归和 ... 展开的可以去学学,毕竟元编程。

算法就不用学太多了,先认识一下 BFS 广度优先搜索、常递归实现的 DFS 深度优先搜索就好了,当然狄克斯特拉算法、二分查找、并查集(UnionFind) 快速查找的传递关系优化、那个『树状数组』的权重优化也是可以参考一下的,关系式(relational programming) 的 unification 算法也可以学习一下,六个基本元素 variable, state, introduce(fresh), eq, both, either,不就是求解相等么,以后写点类型推导算法用得上,逆波兰记法 (1 2 +) 也必须了解下,数值化字符串再化回来的也可以写写啊。可以试试写字典树(trie tree) 和弄个二分查找的 RangeMap 什么的。

纯函数式编程完全可以不学,范畴论直接以你们家的族谱开始枚举可选的箭头就可以了,然后传统函数式数据 Maybe Either 相当常用,Haskell 写解释器学下 GADTs 和 TypeFamilies 小姐的博客是个不错的选择。

重要的是学模式,那个 x >= first && x <= lastx >= begin && x < stop 的左开右(闭/开) 式区间必须会用,状态机 列表处理 栈 队列什么的必须明白,然后是写点提供 callback 的程序 正确理解回调和异步、不用处理数据同步的那种多线程、SIMD 也可以考虑一下,
Forwarded from Deleted Account
计算机科学不能光嘴上说说,所以现在就去拿 Turtle 画画。
多整点应用啊,状态机、线形结构、树形结构、映射是相当重要的抽象模式,纸上编程用起来,当一个快乐的空想工程师。

关键是要买书看啊…… 还能怎么样,我说的又 要 素 过 多,没有结构。
大佬多的是,一年后你有没有长进看自己。
This media is not supported in your browser
VIEW IN TELEGRAM
/tmp/duangsuse.sock
😜 Sticker
好可爱的小海豹
大眼睛 那个像眉毛的部位和哈士奇、Doge 一样
本苏打算去看看盗版《天气之子》之类的动漫电影什么的,
在此之前,本苏不得不先谈谈解释器实现时的作用域实现 #CS #PLT

下文,我们涉及到主要术语:子程序(subroutine)、参数(argument)、局部变量(local variable)、上值(up-value)、闭包(closure)、词法作用域(lexical scoping)、动态作用域(dynamic scoping)

在编程中,我们经常……

算喽,简略点。
我们要处理的,就是实现局部变量,此外作为子程序参数的局部变量也包含在内。
此外,还有闭包——对闭包的创建有点像面向对象的架构器调用,我们需要包住 UpValue——也就是外部函数(outter function) 的局部变量,之后闭包被展开(调用,或者说求值)的时候可以用到包好的值。

function makeCounter() {
var count = 0;
return () => { count++; };
}

var counter = makeCounter()
counter() //: 0
counter() //: 1

假如你是李华,你的朋友 Ada 想要创建一门编程语言,但她不知道如何提供作用域,以使得程序表达更模块化。
你和 Ada 通过 SICP 和龙书了解了有这么两种作用域方案(划掉,怎么可能这么简单)
(-1). (大脑降级方案)使用全局作用域
0. (不全实现方案)使用 Map<String, Perfixed<String>>,给变量加函数名前缀。
1. 使用时序作用域,也即动态作用域。 你们用 Stack<Map<String, Object>> 存储变量,每一层都是 Map<String,Object>,然后每次取值时用名字往外找,第一个匹配的就是值,注意,如果你们用 String 作为名字(标识符),不同函数如果名字一样会导致产生可跨层引用,对返回函数指针的处理也可能遭致问题,因为子程序和变量值是完全分开的。
2. 使用 Map<String, StackOrSingle<Object>> 优化方案
3. 使用 pre-bind 预先指定使用到的变量,然后在进入可能修改变量的子程序前把老变量备份在系统栈的 Map 上,速度更快。

但是 Ada 同学很快否定了这些做法,理由是,那样容易造成混淆。

one = 1 # "one" in add1
def add1(n):
return one + 1

def each_people(people, fn):
for one in people: # most recent definition of "one"
return fn(one)

def print_grow1(person):
name, age = person
print(name + " aged " + add1(age)) # here

each_people([('Jack' 22), ('Rose', 19)], print_grow1)

那么咱来看 C++ 的 caputre: [some_upvalue](int arg1) { return arg1+some_upvalue; }
咱知道,子程序可以是递归的,也就是说,属从它的参数可能在同一时间有很多个,上面也说了。

但关于子程序 (x) => x + 1 最关键的其实是,我们知道 (x+1) 里的 x 是这个东西的第一个参数。
但除了参数,局部变量也是要有的,怎么办?
如果程序自己调用自己也是可能的,怎么办?

def just(n):
if n == 0: return 0
else return just(n-1)+1

just(2) //= just(1) +1 //= just(0) + 1 + 1


调用栈最深的时候,just 的参数是这样的:
[(2), (1), (0)] Top
所以,为了保证递归可能性,作用域的实现必须和栈有关。

那么局部变量怎么办呢?也在栈上分配嘛。
变量是什么?最关键却不太容易感知到的一点是,变量就是针对某个存储空间的,名字,或者标记符而已,它后面藏着『一个』——有且只有一个 存储空间。

就好像 f= (x, y) => x+y 里的 x, y 在生存周期上是『局部变量』,实际上是『参数』,再细化一点,x 代表第一个形式化参数、y 则是第二个。
f(1, 2) 最终就代表着 (1+2),这才是正常一点的世界观。

也就是 lambda 演算的世界观,不过这里才不会提太多术语呢!上面的 (x, y) 被称为 formals,形式参数、 (x+y) 被称为 body,体。

我们从 (x, y) => x+y 的『抽象 Abstraction』,给定两个实际参数 (1,2),填充到 (1+2) 的过程被称为『替换 Substitute』,这 x, y 就被叫做『代词 Substitution』(我自己翻译的……)
而从 (1+2) 算出最终的结果 3 的过程,被称为『收束 Reduce』(也是我自己翻译的…… 好像也叫『归约』)

这整个动作,则被称为『施用 Apply』,整个程序表达呢?就叫『应用Application』。

所以参数、局部变量、闭包该如何实现呢?(当然也有全局变量)

Lua呢,因为是手动递归下降解析器,所以直接在解析的时候,做好这个问题就完了。不就是一个名字对应一个存储空间,冲突按嵌套次序深者优先么。
这个问题怎么解决呢?每一层解析器,都得知道当前有什么参数,方便统一这个存储位置。
最根本的需要就是一个 Map<Symbol, Local> 符号表,代表本层的词法作用域信息(之前所有外层嵌套的参数和局部变量)

局部变量呢?当然,参数就是局部变量,不过是可以暴露出来给调用者提供的那种而已。
局部变量,定义的时候直接在栈帧上分配好了存储空间。至于都放在栈上如何不冲突呢?
这就涉及到调用约定的问题,调用者知道如何操纵咱共同的存储——系统栈,不会破坏要执行的子程序的取参行为。

function solve(a, b, c)
d = 233
return a, b, c, d -- (arg0, arg1, arg2, var0)
end

(注:Lua 包含常量折叠,也就是说 d 这个数值常量可能不会作为局部变量,这里忽略这种可能)
名字冲突呢?不存在的事情,字符串的名字可能冲突,存储空间是不可能冲突的。
名字如何在内部的闭包中共享呢?

让解析器知道,闭包里的 someVar 实际上代表着外部 someVar 的值,就对了。
不过这有点区别——其实也可以作为引用实现,假设某函数把一个包着自己变量的闭包递了出去,就有可能在变量还『活着』的时候,被自己调用的函数修改,我们这里不考虑这种情况。
Lua 的实现是,UpValue(也就是上面我们说的 someVar,某个闭包包住的外层函数变量)
有两个状态:open/close,我忘记它们代表什么了,好像和 GC 有关。

于是一个闭包长这样: [captures](formals) {body}
我们怎么创建它呢?考虑一下实现的细节——每个参数都是 Subst(val idx: FrameIdx, val name: String)、每个局部变量都是 Variable(同上),区别主要是参数不可被赋值,而这个存储(编号)分配的过程在解析阶段完成。

调用者知道的事情,就是按顺序把它们压到栈上,一般是后参先压(我是指传统 CDEF 的,Lua、JVM 里可能不是这样)。
然后子程序知道的事情,就是现在 (a,b) => a+b 里的 a,我们到栈的第一个位置取,这就保证了 a 指代同一个位置,并且符合参数传递的预期。

局部变量也是一样,都商议好分配位置,如知道 x 是在当前栈顶 -1,取/置都按照这个位置来即可。

于是,我们的参数可以传递,并且有名字、局部变量可以读写,并且也有名字。现在闭包对 UpValue 的引用怎么办?
我们觉得,既然闭包不可避免地是一种数据对象,那就给它安排一个数组,来存放其 capture 住的部分,其他的和普通函数无二,也有自己的代码、参数和局部变量。

UpValue(val idx: Idx, val name: String)

解析闭包时,记住外层函数的局部变量表,如果知道闭包引用了外层的东西,就把这个被引用的东西往 captures 列表一放,再对应地把对它的引用视为 UpValue(idx, name)
创建闭包时,检查闭包的 captures 列表,分配一个数组把 capture 住变量的实际值都存到里面去,合并入闭包对象的状态里,这样运行时就能拿到 UpValue 的信息了。


实现注记:
1. Subst 和 Variable 都是 Local,但 Subst 没有 setValueIn。
2. Upvalue 和 Local 都是 Resolvable,能够关于一个栈取到值
3. Function 和 Closure 都是 Subroutine,可以被提供参数调用也可以有局部变量
4. 在 Lua 里,函数是有 maxlocals 的,换句话说,Subroutine 就有使用的局部存储空间大小这一说,可以在运行前确定。
5. 解析器可以选择低内存优化和低计算优化
如果要为低内存优化,可以使用 ArrayMap,再加上 base map, shadowed map 先往局部遮盖的符号(可能没有)里找,再往上一层的遮盖找,这个数据和算法可以封装为一个 class,一般情况都不用。
6. 查找顺序:局部变量、参数、外部函数的 UpValue,否则就是全局变量。
Forwarded from Deleted Account
Wave.kt
728 B
#Kotlin 你说的好有道理啊,虽然花了很长时间我才知道 index/44100.0 再 %1.0 是什么意思,(time/ratio)*2*Pi*Short.MAX_VALUE 嘛,我之前也听说过 PWM,不过只知道能用来做 LED 的闪烁走马灯
Audio
然后像是这样
Forwarded from Deleted Account
有意思,我又可以把这个发上 GitHub 了(当然是到我那个文件分享里面)。