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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
#Android 第一次听到辅助服务(无障碍服务, Accessiblity service)会导致手机变卡... 不过想想也是有道理的,那么多数据要跨 ring 级别传输呢


Ring 级别:计算机系统底层分级权限控制
类似的就是操作系统内核支持的进程访问权限控制呢。
duangsuse::Echo
Photo
#Kotlin 咳咳,其实如果 @UseExperimental 支持的话,大家可以用 @file:UseExperimental 哦。
这也是 Kotlin 的一个改进(不是语法糖^1),Java 里 Annotation 是不能加在 File 上的,File 本身不是可见的语法元素。

^1 语法糖:对某种语法表述的惯用性简写,e.g. C++ 的 std::string abcs("abcdefg..."); 就是 std::string abcs = std::string("abcdefg..."); 的惯用法
#Java #Android 现在来告诉你们(虽然一直以来都对我自己来说不好...)
所谓『越复杂越容易堆砌,越简单越难于设计』究竟是什么。

我本身没有多少工程经验,记忆力也比较差,但是不知道为什么,就是看不得重复冗余的代码... 真的,哪怕有一点正常的重复我都不能忍... 😵
我本身不擅长重构和程序变换,程序分析也够呛,但总是喜欢尽一切可能地抽提程序逻辑,甚至到了使用面向对象多态和继承特性的地步(当然我一般更喜欢函数式的说...)。

文章(我知道一些工程派可能非常不屑,因为我实际上没有几个拿得出手的应用、理论上也没有太大收获,我还没有造出自己的解析器框架却好像说了很多自己『自以为高大上其实是欺负人骗人』的话。这也是我自己一直的感觉)
里,提到了一些 #Haskell 代码,不过虽然 Haskell 的链表是惰性求值的(对于工程派来说,它就可以实现 Stream)我依然不怎么理解那种代码呢

-- zipWith 从来没有完全停机过,它只是挂起,因为 Haskell 的 [a] 关于它的 head/tail 惰性求值
fibs' :: [Int]
fibs' = 0 : 1 : zipWith (+) fibs' (drop 1 fibs')

相信看到它的你们也一样,我是完全蒙蔽的,我看过 zipWith 的定义,也在纸上模拟过,只是没有完全拿到『那个』直觉而已。

quickSort :: Ord a => [a] -> [a]
quickSort xs
|length xs <2 = xs
|otherwise = quickSort lts ++ eqs ++ quickSort gts
where
x = let mid' = (length xs `div` 2) in (xs !! mid')
lts = [ l | l <- xs, l < x ]
eqs = [ x'| x'<- xs, x' ==x]
gts = [ r | r <- xs, x < r ]

-- forall i. list[i] <= list[i+1]
-- forall x r in join2(list). x <= r
ordered xs
|length xs <2 = True
|otherwise = forall (zipWith (<=) xs (tail xs))
where forall = foldl (&&) True

prop_qsortOrdered inxs = ordered (quickSort inxs)
where _ = inxs :: [Int]

import Test.QuickCheck (quickCheck)
quickCheck prop_qsortOrdered -- OK, passed 100 tests.

这就是所谓『简单』的设计。看起来就是很简洁没几行字而且没有符合某种刻板的缩进格式,其实没有一定的积累,你写不出这种代码。
程序设计和抄改代码是有区别的。

哪怕是对于 Android Build 的 Buildscript 都去记住其中的名字和属性。到了什么都靠背、默写的阶段,才有能够写出无余赘代码程度的能力呢。
对于简单的顺序编程、单次异步回调、事件监听、流/协程、多线程处理、多任务,靠的都只有一个 — 对『程序本来应该做什么』的直觉

这也正是我在文章里说的,当然,写完我发现也是王垠说的。虽然我觉得提到他也没太大意义^1... 🙈
— 刚入门的程序员扣老师枚举出的语法,战战兢兢地拿那一堆惯用法组织自己的逻辑、加入实际项目的工程师扣刻板复制的项目管理、设计模式、代码风格,可是真正的程序设计大师只扣对编程的直觉和程序本身的灵魂,对他们来说已经没有入门者的条条框框、刻板的约束了,回归初心,他们看到的是程序所做的事情本身,是程序的灵魂;换十种兼容的语言和底层抽象去描述也不是问题,因为他们已经站得足够高,无须顾虑脚下低处的迷雾笼罩而可以自由地放飞视线,不识庐山真面目,只缘身在此山中。

刚才看到某频道(这里不说)的 Rx 代码后又忍不住想重写一下... 那就这么干吧

首先,Rx 里要一个流的 handler 就是:onNext((Item) -> *) onComplete() onError((Error) -> *)
当然你可以不处理错误,会 ES6 Promise 的同学会觉得这是一种『持续性发射』的 Promise。
至于状态转换、信号.... 呃(这也是我最近在构筑的直觉模型,所谓直觉,这里就是类似在脑中对模型进行可视化的骚操作而已)

一个 Promise 有三个状态:
pending(0), resolved, rejected
pending -> resolved
pending -> rejected

pending 是初始状态、可以状态转移到 resolved 和 rejected 抽象状态。
要在状态变迁时收到通知添加处理逻辑,对于
pending -> resolved 使用 then(_: Function<R>), 它可以嵌套(回调链条),本身是 Promise<E, R>,说起来这又涉及函数式编程范畴论(关于 flatMap)的一些工程应用了...
pending -> rejected 使用 catch(_: Function<E>)

一个流大概是有三个状态,可以类比:active, failed, finished
active 状态有一个信号(signal) nextItem 使用它监听:
onNext(Function<T> consumer): Stream<T>;

然后,对于一个 Stream,就有了『订阅者』(信号 dispatcher)和『监听者』(信号 handler)的角色,订阅者负责把『流』的更新事件交给『监听者』处理。
(以上内容是我猜的... 可能不准确甚至谬误)

首先 dispatcher 我们基本认为是 application scopend 或者至少是 page scoped,那么就应该先弄一个设置好 dispatcher 的 stream。

val foundItems: Single<List<Found>> = if (currentChapterFilter.checked) doSearch(in = Chapter) else doSearch(in = Book)

那么为了创建查找结果,就应该使用 singleOnesingleAll 流方法,我猜他们是通过逐个 item 收集到 T(one) 和 Stream<T>(all) 的

articleDao.singleOne(selectedArticleId) 就创建了一个流... 不过我们得为流设置 scheduler 和 observer... 可能,而且流上还可以加处理高阶函数 xs.map(adds(1))
所以抽提一下 single* 选择方法,它设置好一个(此模块的)流,给它指定 scheduler 和 observer

fun <T> itemStream(stm: Stream<T>): Stream<T> = stm.scheduleOn(ioScheduler).observeOn(Schedulers.single())

还有 map(eta) & join(mu) 的 flatMap (一知半解中,因为范畴论很难懂)
接受一个返回 Fct<T> 的函数,然后把所有 map 完了 join() 起来成为 Fct<T> (rather than Fct<Fct<T>>)

这样。原来的查找代码可以这么写。

val firstone = itemStream(articleDao.singleOne(selectedArticleId)).map { it.first }
val allpassed = itemStream(articleDao.singleAll(selectedFolderId))
.toFlowable().flatMap(Flowable::fromIterable then articleToFoundsMapper)...

此刻还都是 folders -> articles 的形式(flatMap join 了所有文件夹子树)(关键在于这个『都』,一般都是这么干的,尽可能保证数据结构一致)
然后进行 Item -> Found 变换(then · 函数 compose)

然后 allpassedflatMap(Flowable::fromIterable) 的形式... 其实这个逻辑本身应该被抽提为 joinAll(), 欸算了
toList
, collect(Collectors.toList()) 我就不想说了
其实看你们工程的时候在用,我也觉得 java.util.stream.Collectors 只应该有 toList 静态字段,而不是方法,看起来怪怪的。本来只应该是一个处理过程却好像要什么专门的计算才能得到它...

...
最后,调用链写的老长,该不会是忘了类似 builder pattern 之类的东西出现到底是为了什么吧。是我看任何冗余都不顺眼么...

val add1 = SumBuilder(1)
println(add1.plus(2).plus(-1).sum())

关键在于 add1 这个『对象』(操作和数据共同的封装)的复用啊!!!

^1 这里不该和王垠的雷同观点扯上关系,这只是想要暗示什么。请参看原文章正文内容。
#reveng 啊,说起来 drakeet 又开始在纯纯写作的代码保护上下工夫了... 100% 胜率退役么...

不知道他有没有应对动态调试的情况... 机器代码也会被逆向分析的情况、月读运行时内存的情况、不过,显然我现在不能也没时间去看了。

我不是密码学爱好者,但我很清楚,程序映像是被动地『被』解释的、用户看到的是解释器依照它看得懂的程序做到的、解释器是你控制的。
程序是 Ring 3 的,它看不到很多东西。而你是 root,你操纵一切。

让代码完全被保护就像使水不湿、信息不被复制一样,是做不到的,只能尽可能提升成本。
『向左看的同时又像右看』么,可是现实世界里不存在影分身这种东西啊。

『破解』爱好者们啊,这一点狭隘的视角、孱弱的直觉模拟、程序设计都做不到的程度,也能自称『神』么。
连计算机科学的基础,PLT,程序设计语言理论、操作系统都不了解的话,又怎么能称得上是破解者。

说起来,其实集成电路 circuit 和嵌入式的设计反“破解”还更为令人骄傲一点,各种 MCU 的厂家都做了很好的代码保护,物理上反破解。

其实这又有什么的,不如自己好好继续看自己的程序分析... 可是我最近又咸鱼了... 自己开发反编译器么
LLVM 编译器也要来一个哦
本质上谁都能看,或者不登录也能看
黑名单此时更多的是表达一种态度
duangsuse::Echo
本质上谁都能看,或者不登录也能看
是的
duangsuse::Echo
是的
#math 函数曲线么... 好怀念啊

也是我最近在考虑的东西呢,说起来 cubic bezier 函数的求值器可不好学啊...
折线图那么好看那么方便,不如写一个来吧...

优化... 管他呢,反正以后会专门有学习的呢(计算机图形学)。其实 duangsuse 这段时间有考虑基于始末状态和函数曲线的动画帧插值。

所谓心型曲线是两条一次分数直线(分段函数),比较简单,我也不想多说... 我不擅长数值函数、斜率和等式推导什么的 没办法...


def y(x, threshold = (10/13)): return x*(13/10) if x < threshold else (1-x)*(13/3)


from numpy import arange
from pandas import DataFrame

xs = arange(0, 5, 0.1)
ys = [y(x) for x in xs]

curve = DataFrame()
curve['y'] = ys

curve.index.name = 'x'
curve.plot(title = 'Heart <3')

嘛,还蛮有爱的
duangsuse::Echo
#math 啊... 我居然花了很大精力变换等式才想起来,1-x 其实是 (-x) 和常数项 1 的叠加... 🙈 之前还误解为 -1+x 的说,,,, 果然还是不擅长等式变换,连这个都要靠字面表示的直觉,不能模拟... QAQ
duangsuse 对计算的厌恶是有目共睹的... 但是自从接触了函数式以来,也想办法去做一些基本无须计算的判断了,比如值域
duangsuse::Echo
duangsuse 对计算的厌恶是有目共睹的... 但是自从接触了函数式以来,也想办法去做一些基本无须计算的判断了,比如值域
嗚嗚 我數學只有代數領域還能理解 圖形領域幾乎是每看到一次想自殺一次的等級
duangsuse::Echo
嗚嗚 我數學只有代數領域還能理解 圖形領域幾乎是每看到一次想自殺一次的等級
其实这也算是代数啦,
我小时候是完全平方公式别人死教我都教不会

我根本不知道为啥 1+1 = (1+(-1))+2
我代数真的超菜的,连 n^2n*n2nn * 2 都不知道;辣鸡的要死 #math
但是 -1 + 5.... 是 4 呢
或許你可以想成 -(-1+x)