duangsuse::Echo
719 subscribers
4.28K photos
130 videos
583 files
6.5K links
import this:
美而不丑、明而不暗、短而不凡、长而不乱,扁平不宽,读而后码,行之天下,勿托地上天国。
异常勿吞,难过勿过,叹一真理。效率是很重要,盲目最是低效。
简明是可靠的先验,不是可靠的祭品。
知其变,守其恒,为天下式;穷其变,知不穷,得地上势。知变守恒却穷变知新,我认真理,我不认真。

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
数位板压力感应 wroks on my machine(可见对 Wacom 数位板的支持还是很好的
Forwarded from duangsuse Throws
GIMP 的新 MyPaint 笔刷测试(不知道是不是基于 G'MIC 的,dalao,,,,
继续瞎眼抄画(直接把纸压在数位板上照着描...
Forwarded from duangsuse Throws
最后桌面布局(这次试用到此为止,非常成功,没有坑。可见各大 GNU/Linux 发行版对 Wacom 数位板的支持都很好,Krita 4.1.7.101 Qt 5 Core Tablet 在我这里有个 cache double-free 的问题,其他都好
Forwarded from duangsuse Throws
#sysadmin #KDE #Linux 如果大家配置中遇到了不能用的情况,ArchWiki
#PL #CSharp #PLT Generics.
Forwarded from 羽毛的小白板
A sorted set in Pg

#Pg好玩
羽毛的小白板
A sorted set in Pg #Pg好玩
暂时没有时间学这些东西,大佬能不能在频道上讲解一下是怎么做的(刚刚 SQL 入门
学习的话还得先在相对标准又简单的环境(如 SQLite)下熟悉 CRUD
顺路给大家科普一下 LWP 的问题(虽然现在对并发编程什么的我也不擅长,但如上所说我会学的,而且最终会变成我的技能 #parallelism

这个本来是我在某国产 JVM 书上并发实践上看到的,当然操作系统笔记上也有讲(肯定的,现在哪个操作系统不是多用户多任务... 况且,据说此书是他们应付考研用的,不过目前我不是很熟,其中很多问题 C++ 这样的并发编程程序员都能遇到,不只是操作系统层面的问题)

LWP 是 LightWeightProcess,轻量级进程的意思

对应的概念是 KLT(Kernel-Level Threads),系统级线程

In computer operating systems, a light-weight process (LWP) is a means of achieving multitasking. In the traditional meaning of the term, as used in Unix System V and Solaris, a LWP runs in user space on top of a single kernel thread and shares its address space and system resources with other LWPs within the same process. Multiple user level threads, managed by a thread library, can be placed on top of one or many LWPs - allowing multitasking to be done at the user level, which can have some performance benefits.

类似 pthread 这样的 1:1 (LWP:KLT)模式,一个 LWP 是由一个 KLT 直接映射上的,实际上现在很多内核都是这种模式,Windows NT、Linux 都是。当然 Solaris (好像曾经叫 SunOS?)这种还会提供 N:1 的混合线程(不过应该没有专门 1:N 的,N:N 的应该有,java.util.concurrent 的 FJP 应该就属于这类,对应 j.u.c 的 FixedThreadPool 固定线程到任务的),目前大家的很多 JRE 环境实例(当然包括 JDK)大概都是直接一个 Thread 映射到一个 KLT 的(比如 9012 年的 Windows

如果喜欢不妨多了解一下,我没啥本事只能说这点了(大佬们多多指教 QAQ

For applications that require separate or custom pools, a ForkJoinPool may be constructed with a given target parallelism level; by default, equal to the number of available processors. The pool attempts to maintain enough active (or available) threads by dynamically adding, suspending, or resuming internal worker threads

同时也有类似的概念 Green Threads,用户级的线程实现,它不依赖操作系统的支持(所以,DOS 上都能用,这就是说 MRI Ruby 的一些早期版本甚至可以在 MSDOS <=6.x 上用多线程的原因)开始一些 20 世纪 Sun 的 JVM 也是 Green Threads,可是这个东西就有很大弊端,比如系统资源分配、CPU 也就是执行资源分配上操作系统认不出你这个用户自己弄的线程实现,系统资源(比如文件、互斥体、Timer 们)上的东西就很难实现甚至不可能实现,所以也不是太好,当然背后由系统级线程 KLT 支持的也有自己的缺陷,就是 User-mode 和 Kernel-mode 互相切来切去更频繁,开销比较大,CLR via C# 上是有讲的

当然这些和什么用户模式、内核模式、系统资源、任务调度之间有很大关系... 所以我还是回去用 Java 抽象出来的 java.lang.Thread 好了(删除)
坏处就是 JVM 平台上同步的确是比较简单的,他们都用 Monitor 这种重量级的方法... 当然商用 JVM 实现的优化肯定要做... 早些时候(JDK 1.2 还是 1.3 之前) Java 的 volatile 语义都有问题,不能阻止指令重排序,『著名』的双检锁 Singleton 模式都会直接当场爆炸不可避(尤其是那些 Constructor 副作用很强大的类...)

JVM 平台上对开发者们素质的要求肯定是比 C#、C++ 这种低的(但是不希望大家都只会用个 synchronized,volatile 而且是滥用这种万能同步语义(那玩意,说实话,真的很 trivial,我开始完全不懂数据竞争同步问题的时候(就是完全没有任何分析能力)都会用它同步多线程的 Hashtable 了(synchronized 的 HashMap)可以说是相当简单相当 trivial(

这里我们不讨论 Coroutines(协程),也不讨论什么抢占式线程、非抢占式线程,也不讨论什么原子性操作... 可重入... 线程安全... 因为我不是太懂,当然我也不是完全不懂。差不多就行了


好了不说了(科普一下而已(
duangsuse::Echo
Yuuta 重写的代码我看了,都还好。略微使用了一些 Kotlin 额外的特性,但主要还是语法糖之类的 这里真的是服了国中生的精力,这么长的代码也写得。怀念初中的时候哈?( 推荐使用 辅助函数 来使诸如 if (startHour == 0 && startMinute == 0 && endHour == 0 && endMinute == 0) { …
另外 #fix 再说一个问题,就是我这里提的这一条其实是我的误解 #Android

至于这一条呢,是我在《Kotlin 极简教程》上注意到的,并不适合这种情况,是我误记了

它是说 Kotlin 的 Any(因为 Kotlin 开始就没有只考虑 JVM,后来还有 KJS、KN 呢,所以 Kotlin 自己语言层面的一些东西不单单在跟着 Java,如现在的一些 Kotlin JVM Developer 们的日常,Kotlin JVM 要 Kotlin 反射还得加依赖还是什么的)没有 Java (就是 Kotlin 的 Any?Any 映射到 java.lang.Object)的 Object#wait Object#notify 这种锁同步工具 Kotlin 里就不推荐了(因为 Any 类型里面没标这些方法虽然 JVM 运行时里是有的,Object 对象当然能响应这些调用),推荐使用专门的并发编程工具比如 java.util 里面那些

后面那句说的就是可以加 (o as Object) 强制转换到 java.lang.Object (原来的类型是 kotlin.Any)来使用这几个方法

而 Trumeet(Yuuta)写的

     private val lock = Any()

实际上他后来是要 synchronized (lock) { ... } 的(而不是 lock.wait(5.seconds()) 这种对 java.lang.Object#wait(long) 的调用),这当然没有问题,要不然 kotlinc 也不给过了。
duangsuse::Echo
学习的话还得先在相对标准又简单的环境(如 SQLite)下熟悉 CRUD
CRUD 语句比较简单,都学过了(那么我就再花点时间顺便学一下,感谢 dalao 的分享 #SQL #Postgres

现在也比较合适,因为我在学校的时候学着分析了一下实际的应用,理工两开花,结果非常成功。而且我发现 Kotlin + SpringBoot 开发起来非常模式化、MVC 模式非常简单(就是几个 Entity、后面那些东西都是自动生成的,写个 interface 和几个 Spring EL 一 瞬 解 决模型层查询问题,Controller 层都非常 trivial,@ResponseBody 可以直接组织起 JSON 来,不需要脑子),决定赶快做一个练手(别怪我写的东西太 trival... 或许还不如 OI 生一天的,当然现在 OI 生可能也有些不是多复杂的东西(甚至 dfs 深度优先搜索不会做都不是不可能),当然我觉得都差不多,没啥有意思的算法,就是拿那几个接口绑定一下完了,Xposed 插件什么的都一样,我觉得写这种东西应该比编写效率和建模分析能力,当然也可以当我智障好了。这就轻松多了)
所以还是比较适合学这类东西的(属于 JPA 层(当然实际上 Web 后端和前端都还有很多知识可以学,不过其实能借助文档比较不用脑子的学会了,不需要多少思考,代价就是不会有太大提升

顺推博文 SQL查询语句及关系代数复习题

这是代码 #code 据说实现的是一个 sorted set 的 table???

INSERT INTO array_test(id, items) VALUES (1, ARRAY[1])

比较简单不讲

ON CONFLICT (id) DO

下面的语句是插入 id 冲突的时候执行的

UPDATE SET items = ARRAY(SELECT DISTINCT item FROM unnest(array_test.items || excluded.items) item ORDER BY item)
WHERE NOT array_test.items && excluded.items

RETURNING items;

unnest(): This function is used to expand an array to a set of rows.
子句们(不是所有 #PL 爱好者都必须把 AST 之类的东西搞出来或者指出那个语句什么组成情况...)
UPDATE SET: UPDATE changes the values of the specified columns in all rows that satisfy the condition. Only the columns to be modified need be mentioned in the SET clause
SELECT DISTINCT: The SELECT DISTINCT statement is used to return only distinct (different) values.
RETURNING(of UPDATE): The optional RETURNING clause causes UPDATE to compute and return value(s) based on each row actually updated

简单到幼儿园级别的 SQL 子句就不说了(比如 ORDER BY

当然我只是顺手找了点文档而已... 具体实现逻辑自己分析吧(我看了个大概)(因为我准备发书单来着...)
duangsuse::Echo
学习的话还得先在相对标准又简单的环境(如 SQLite)下熟悉 CRUD
深入的话就是 data type 和相关的 operator 和 function,以及 pg 对 CRUD 扩展的专有写法
duangsuse::Echo
深入的话就是 data type 和相关的 operator 和 function,以及 pg 对 CRUD 扩展的专有写法
我目前还是想拿 Pg 做点实际的应用(
实在是没有那个力气开几个理论向学习,因为定理证明、PL 理论那些已经够累了... 代数程序逻辑依然在学,反正理论向都是均衡发展但都很薄弱就是了

现在具体来讲就是 The Little Schemer 终于熟悉了一点这个列表处理语言... 不过我觉得还是 Haskell 好,因为 Haskell 更符合直觉(看很多用 Haskell 讲程序分析的论文就知道),Scheme 一类的一大堆 car cdr 让不让人活了

具体就是(拿 foldr 和 foldl 举个例子)

Haskell 里(比较简单比较符合那些面向程序分析变换的方式,没有 Foldable、Functor 什么的 class,也是因为我没好好学过 Haskell,羞愧)

foldr :: (a -> r -> r) -> r -> ([a] -> r)
foldl :: (a -> r -> r) -> r -> ([a] -> r)

foldr f v [] = v
foldr f v (x : xs) = f x (foldr f v xs)

foldl f v [] = v
foldl f v (x : xs) = foldl f (f v x) xs

reverse :: [a] -> [a]
reverse = foldl (\xs x -> x : xs) []

map :: (a -> b) -> ([a] -> [b])
map f = foldr (\x xs -> f x : xs) []

length :: [a] -> Int
length = foldr (\_ n -> n + 1) 0

当然,上面的都是 point-free 风格(两边约掉一个参数)(现在你们知道啥叫程序变换了吧?),which 曾经被淫王喷的,因为不直观(实际上他也喷 fold 这种递归模板的,实在是不够直观),不过我是为了讲这个专门举的例子求不喷。

而我们用 Scheme 翻译一下原来简单直观的代码瞬间变成了乱码(这里就没加类型,因为我没试过有静态类型系统的 Scheme 实现):

(define fold-right
(lambda (f v l)
(cond
((null? l) v)
(else (f (car l) (foldr (cdr l)))))))

(define fold-left
(lambda (f v l)
(cond
((null? l) v)
(else (foldl f (f v (car l)) (cdr l))))))

(define foldr
(lambda (f v)
(lambda (l) (fold-right f v l))))

(define foldl
(lambda (f v)
(lambda (l) (fold-left f v l))))

(define reverse
(foldl
(lambda (xs x) (cons x xs)) '()))

(define map
(foldr (lambda (x xs)
(cons (f x) xs)) '()))

(define length
(foldr (lambda (_ n)
(add1 n)) 0))

一 瞬 混 乱
不要停下啊(指乱码)

而且像这种(universality property of fold operator)拿 Scheme 表示就彻底... 彻底(暴论
请善用模式识别。高中生数学科目必须要会的技能

g [] = v
g (x : xs) = f x (g xs)

g = fold f v

e.g. reverse 函数

reverse [] = [] (其实 reverse [_] 来匹配只有一项的列表也可以,我觉得是这样)
reverse (x : xs) = reverse xs ++ [x]

reverse = fold f v
where f = (\x xs -> xs ++ [x])
v = []

步骤(推算出 f)大概就是 (g xs) 换成 xs...
g (x : xs) = 
f x (g xs)
reverse (x : xs) = reverse xs ++ [x]
reverse
xs ++ [x] = ((++) (reverse xs) [x])
参数顺序不对,再加层 lambda 表示法就可以了(

定理证明现在勉强理解了一下 rev (rev v) = v 这种,所谓的『更小规模』的证明 forall a v. rev (v ::r a) = a :: rev v 也能勉强理解了,看了证明思路也有,但是还不会写,rewrite 归纳证明比较符合直觉(拿 xs 递归解决什么的...)然后 Agda 总算是看得懂了(我不知道写了多少遍那几个例子才,,,)