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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
duangsuse::Echo
好了,闲杂事物已经处理完毕,现在来干 ♂ 正事 ❤️ #weekly #tech 这星期(虽然就一天)的事情,将会包含: + 两个到三个 Excited 的项目(BinaryStreamIO 1.0、SimpleCat)(Android 的 Perferences 封装) + 两个小型 PoC 项目(PartitionSortableList、Delete/Insert/Modify sorted Lists Android 应用、TextTag)(吐槽:其实 duangsuse 也不会多少排序算法呢,他连…
#dev #life 那么,如今令人心碎的是,有些任务不得不因为时效问题不能做了... 💔😿

真的很令人沮丧,虽然他们都很『幼稚』都『什么都没有』但是对我来说,都那么有魅力,有自己独特的价值
希望 duangsuse 有一天从高中毕业后,能有足够的时间做所有自己想做的事情吧,一定要更好呢。

== 工程性(想做的事)

+ Kotlin Android UI DSL
+ Kotlin 实现 Gauss-Jourdan 消元算法解线性方程组
+ Android 单独重写 Unicode UCD Viewer 应用
+ DropScript(现在看来这个还算简单的了)
+ DeepTransform Android 应用
+ 默写:sm.ms JavaScript、CSharp Parallel DIP 反色、Java8 BshServer、Android BluetoothServer、Zygote service(虽然我其实完全已经记下来了,也算是完成任务)、OpenGL GLUT 体验、人工神经网络机器学习体验
+ 关于 PartitionSortedList 和『不可解决问题』的 List Delete-Insert-Modify Android 应用 PoC
+ 进一步细化 GeekApk 的设计

== 理论性(想说的知识点)

+ Visitor Pattern, Object Algebra, Finally Tagless 解决 Expression Problem 详细讲解
+ iptables
+ 线性代数:Gauss-Jourdan 消元算法解线性方程组,理解
+ ES6 的新特性(比如 Reflect 方面、并发方面、Generator 和 async 函数、let 和 pattern matching、二进制处理方面、各种基本操作和类型的扩展等等),简介
+ 讲解:基于递归下降法的 Parser 们
+ 常见 Functor, Operator(Function) 和 Monad
+ HTML、URL、URI,尝试讲解视图布局的直觉(比如兼容盒模型的思维方式、快速抽象自己的 View)

== 感慨性(学习中想噫吁嚱的东西,比方说突然的顿悟、对新领域魅力的感叹)

+ 上上上周学到的很多东西,比如说人工神经网络(诸如前馈全连接、卷积神经网络,非监管学习)方面的知识、RankNTypes、依赖类型和形式化验证、Rust 的 Vec 实现、CSharp 里 Parallel.ForEach DIP 反色、流式 Binary Processor 等等
+ 上上周学到的东西,比如 Internet 方面的一些东西(协议们,包括传输层的一些东西)、JavaEE 的 CDI/JNDI/Message Queue/JPA/JTA/JAX-RS&Reflect/(UI)Tests、CLR 的一些同步机制 — SpinLock 自旋锁、Monitor、Mutex、Semphore,和一些乐观并发控制机制,比如 Compare-And-Swap, Compare-And-Set
+ 上周学到的东西,比如一大群关于 JVM 执行子系统、类文件结构、类加载器架构、线程同步、内存模型、即时编译优化、面向对象编程的知识点,还有一小块 LLVM 的几个小知识点的观望


还有本周(其实有三天)的一个理论讲解性的科普,很难给大家阐述了(考虑到要给工程留足时间的原因)

+

那么还有这些,依然是在可以做的范围内:

+ 讲解关于二分查找和滚动歌词实现优化的内容
+ GeekSpec 1.0

它对 Session, State(Transaction), MVC, Dataverify, REST, Middleware(WebFilter), Test, Authentication, UI 打稿, WebSocket 有内部支持

+ AOP Proxy Preferences 封装
+ BinaryStreamIO 和 Binary AXML ARSC 处理器

如果有可能(子类实现方式足够优雅),BinaryStreamIO 将被 port 到 C++ 和 .NET 平台

+ Cat 程序设计语言的一个子集 — SimpleCat
+ (有可能的)Cat 程序设计语言的一个子集 — NaiveCat (这个包含 KotlinCommon 的 Reflect 内容,也会做自动的装箱/拆箱、接口实现转型、值类型自动提升操作)


PreferenceProxy,面向接口编程!涉及到 Java Reflect Proxy 和动态 Annotation 的内容,属于面向对象软件架构。

+ 重写 Android Spannable 库 TextTag


== 还有这些,是下次想做的

+ 利用这周写好的 GeekApk v1 (新) 接口方案解决代码繁复的问题,编写 GeekApk 的 Vert.x + JPA 后端
+ 编写 LayoutFormatter 和 LayoutFormatter IDEA / Gradle 插件
Forwarded from Rachel 碎碎念 (IFTTT)
https://t.co/ZJYeY2CmpT
这也太触了吧
澳大利亚国立大学提供的真随机数接口,利用量子随机发生器,在线生成指定长度和规格的随机数数组.https://t.co/AAFw7jOHTv— 智智乃🇹🇼 (@chychino) March 31, 2019
#Android #Low #Haha #life #tech #tencent #WeChat #weibo 真心佩服文案大佬。可是,可是,这能成为你无视界面风格个性化的理由吗?微信...
Forwarded from 永久封存 | Yuuta 台 | 😷 #Pray4Wuhan (YuutaW 鱼塔)
https://t.me/oasisfeng_apps/286103 然后国内的各种团队就开始清一色拒绝黑暗模式了么((
duangsuse::Echo
#dev #life 那么,如今令人心碎的是,有些任务不得不因为时效问题不能做了... 💔😿 真的很令人沮丧,虽然他们都很『幼稚』都『什么都没有』但是对我来说,都那么有魅力,有自己独特的价值 希望 duangsuse 有一天从高中毕业后,能有足够的时间做所有自己想做的事情吧,一定要更好呢。 — == 工程性(想做的事) + Kotlin Android UI DSL + Kotlin 实现 Gauss-Jourdan 消元算法解线性方程组 + Android 单独重写 Unicode UCD Viewer…
以后 GeekApk 就有两门『自己的语言』撑着了!

GeekApk 的后端,需要 REST, RDBMS, WebSocket,可以由 GeekSpec 1.0 提供高可重用性,具有灵活、可读性,严重减少余赘代码的开发工具
GeekApk 的多平台客户端(主要是 Web 和 Android,以及 Gtk#),由 Kotlin Common 和 CSharp 的 NaiveCat 程序设计语言支持,一次开发插件,多个平台运行

并且,虽然只是弱类型的 NaiveCat 还支持很多流行的操作:模式匹配、尾递归优化、Fibers、基于 first-class fiber 的事件驱动、扩展的类生成器 DSL、构造 Proxy 实现实例对象、无符号数值、Tuple、运算符重载、自动类型转换、正则扩展、类型安全、反射字段方法引用、扩展方法、给 Lambda bind 一个 self、静态代码检查...


虽然目前一些东西好像还在脱离设计阶段之中,期待未来的表现 🤔
这周的安排:

1. 讲解关于二分查找和滚动歌词实现优化的内容
2. AOP Proxy Preferences 封装
3. 重写 Android Spannable 库 TextTag

== 明天

1. BinaryStreamIO 和 Binary AXML ARSC 处理器
2. Cat 程序设计语言的一个子集 — SimpleCat,这也是 BinaryStreamIO-ReadStruct Annotation 定义式扩展的依赖关系
3. GeekSpec 1.0

== 后天(如果有可能)

1. NaiveCat 的 AST 和解析器
考虑一下用熟悉的 Ruby 简单行扫描算法写个 Parser,然后再来用 Pry 执行 Ruby 代码去统计...
duangsuse::Echo
考虑一下用熟悉的 Ruby 简单行扫描算法写个 Parser,然后再来用 Pry 执行 Ruby 代码去统计...
解析器(其实就是扫描器)处理这种文法:

以行("\n")为单位进行逐行处理,因为 Telegram 客户端使用这种方式输出


状态 DEFAULT:
如果匹配 /^(.+), \[(\d{2})\.(\d{2})\.(\d{2}) (\d{2}):(\d{2})\]$/ 说明是一个新消息
进入状态 NEW_MESSAGE
否则,扫描此行,进入状态 SCAN_PUSH_LINE

状态 NEW_MESSAGE
假若此行以 "[" 开头
匹配 /^\[In reply to (.+)\]$/ 说明新消息是 RepliedMessage,再次进入状态 NEW_MESSAGE
匹配 /^\[Forwarded from (.+)\]$/ 说明新消息是 ForwardedMessage,再次进入状态 NEW_MESSAGE

匹配 /^\[ File : (.*) \]$/ 说明新消息是 FileMessage
匹配 /^\[ (.) Sticker \]$/ 说明新消息是 StickerMessage
匹配 /^\[ Album \]$/ 说明新消息是 AlbumMessage
匹配 /^\[ Photo \]$/ 说明新消息是 PhotoMessage
否则,扫描这一行,进入状态 SCAN_PUSH_LINE

状态 SCAN_PUSH_LINE
假若此行以 "]" 结尾并且匹配新消息 Regex:进入状态 NEW_MESSAGE,扫描这一行
否则:
匹配 /\((\w+)://(\S*)\)/, 结果存入消息文本链接中
匹配 /(?![\(\)]).((http|https):(\S+))/, 结果存入内联文本链接中
匹配 /^(http|https):(\S+)/ 结果存入文本链接中
匹配 /(^|\s)#(?!#)((\S(?<![\(\)]))+)/ 结果存入消息标签中(为了写出这个正则表达式,我足足看了别人一个小时的博客...)
count.rb
4.5 KB
#Ruby #code #share 果然开始考虑的就不周全,差了,下次用别的重写算了...
duangsuse::Echo
致命: 每次工程都会花很多时间,每次时间都不够
其实是思路不清晰.... 熟练度不够

首先我的方式就不对,Ruby 里面没有 inline def,这种『递归下降』是错误的

好的程序会反映出它所处理数据的结构

想想看是真理啊,为什么这种简单的数据结构,会需要递归呢?

考虑一下 《深入理解 Java 虚拟机》 里的一个例子,使用了二进制处理、字节码处理、类加载器技术

包含下面五个类


1. public final class CodeRunner
2. class HotSwapClassLoader extends ClassLoader
3. static class ByteUtils
4. class ClassModifier
5. public static final HackSystem

它要加载一个类文件的字节数组,修改替换其中常量池里的 UTF String 内容,涉及读取/存储截断指定字节长度 int32、读取字符串、序列化字符串等操作,可是却不清楚到底该怎么写?


... 需要多加练习。
duangsuse::Echo
解析器(其实就是扫描器)处理这种文法: 以行("\n")为单位进行逐行处理,因为 Telegram 客户端使用这种方式输出 — 状态 DEFAULT: 如果匹配 /^(.+), \[(\d{2})\.(\d{2})\.(\d{2}) (\d{2}):(\d{2})\]$/ 说明是一个新消息 进入状态 NEW_MESSAGE 否则,扫描此行,进入状态 SCAN_PUSH_LINE 状态 NEW_MESSAGE 假若此行以 "[" 开头 匹配 /^\[In reply to (.+)\]$/…
我们看看真正应该有几个状态:

首先是进入文件的状态:就是 EXPECT_MESSAGE

这时,如果不匹配 REGEX_NEW 则直接忽略该行

如果匹配,则记录下当前 Message 的创建时间和频道,进入状态 SCAN_MESSAGE_HEADER
直到行不以 "[" 开头,检查特殊匹配,记录下当前消息类型和特殊内容
到上个流程结束,应该已经创建了一个消息的『基础信息』
进入状态 SCAN_MESSAGE_BODY

直到行以 "]" 结束,检查新消息匹配,否则:
匹配消息文本连接、内联文本链接、文本链接、Hashtags

为了调试方便,还必须保存当前行、当前位置、当前消息编号信息

总之,扫描器要保存这些状态:

var feeder
var state, line, offset, message_no

var tg_current_message

var tg_name, tg_date // new message
var tg_type, tg_ext_ref, tg_body_type

var tg_body

伪代码:

<EXPECT_MESSAGE> {
until ((ln = feeder.next_line).match?(REGEX_NEW)) scan_warn "Ignore line #{ln}"
// 或者说 dropWhile(readline.not_match?(REGEX_NEW)) { |ln| scan_warn "Expecting new message , ignoring line #{ln}" }

name, d0,d1,d2, hh, mm = _ln.match(Message::REGEX_NEW).captures
tg_name = name; tg_date = Time.new(d2, d1, d0, hh, mm, 0)

begin SCAN_MESSAGE_HEADER
}

<SCAN_MESSAGE_HEADER> {
takeWhile(readline.start_with("[")) {
// check special matches, set tg_type, tg_ext_ref, tg_body_type
}
begin SCAN_MESSAGE_BODY
}

<SCAN_MESSAGE_BODY> {
takeUntil(readline.end_with("]")) {
// check label links, inline links, plain links, hashtags
// and read body text
// return created message
}
begin EXPECT_MESSAGE
}
duangsuse::Echo
我们看看真正应该有几个状态: 首先是进入文件的状态:就是 EXPECT_MESSAGE 这时,如果不匹配 REGEX_NEW 则直接忽略该行 如果匹配,则记录下当前 Message 的创建时间和频道,进入状态 SCAN_MESSAGE_HEADER 直到行不以 "[" 开头,检查特殊匹配,记录下当前消息类型和特殊内容 到上个流程结束,应该已经创建了一个消息的『基础信息』 进入状态 SCAN_MESSAGE_BODY 直到行以 "]" 结束,检查新消息匹配,否则: 匹配消息文本连接、内联文本链接、文本链接、Hashtags…
那么,完成这程序需要的一些信息: #Kotlin #tools #project

— Regex 正则表达式匹配 group
新消息的 Regex
/^(.+), \[(\d{2})\.(\d{2})\.(\d{2}) (\d{2}):(\d{2})\]$/
对应数据:data class MessageHead(val channel: DisplayName, val date: Date)

新消息,reply to
/^\[In reply to (.+)\]$/
数据:data class RepliedMessageHead(val replies: DisplayName): MessageHead

新消息,forwarded
/^\[Forwarded from (.+)\]$/
数据:data class ForwardedMessageHead(val origin: DisplayName): MessageHead

data class Message<T>(val messageType: MessageType, val messageExtRef: T, val messageBodyType: MessageBodyType, val messageBody: MessageBody, val links: MessageLinks, val hashTags: MessageHashTags)
typealias FileMessage = Message<String>
typealias StickerMessage = Message<Character>
typealias NothingMessage = Message<Nothing>

消息体,file
/^\[ File : (.*) \]$/
消息体,sticker
/^\[ (.) Sticker \]$/
消息体,photo
/^\[ Photo \]$/
消息体,album
/^\[ Album \]$/

文本消息体,label links
/\((\w+)://(\S*)\)/
文本消息体,plain links
/^(http|https):(\S+)/
文本消息体,inline links
/(?![\(\)]).((http|https):(\S+))/

文本消息体,hashtags
/(^|\s)#(?!#)((\S(?<![\(\)]))+)/


要保存的状态

val feed: InputStream
var state: ScannerState
var line: Int, offset: Int, messageNo: Int, localLine: Int

var tgCurrentMessage

var tgName, tgDate
var tgType, tgExtRef, tgBodyType, tgBody

扫描算法:

fun nextMessage(): Message<*> {
while (!feed.eof) {
try {
when (state) {
EXPECT_MESSAGE -> scanMessage()
SCAN_HEADER -> scanHeader()
SCAN_BODY -> scanBody()
}
} catch (r: MessageResult) { return r.result }
}
}

inline fun scanMessage() {
feeder.lineDropUntil(REGEX_NEW_MESSAGE::matches) { scanWarn("Ignoring line $it") }
// set tgName and tgDate
begin(SCAN_HEADER)
}
inline fun scanHeader() {
feeder.lineTakeWhile("["::startWith) {
// check special matches, set tgType, tgExtRef, tgBodyType
}
begin(SCAN_BODY)
}
inline fun scanBody() {
feeder.lineTakeUntil({it.endWith("]") && it.match(REGEX_NEW_MESSAGE)}) {
// check label links, inline links, plain links, hashtags
// and read body text
}
throw MessageResult(tgCurrentMessage)
}
count.rb
4.4 KB
#Ruby 版的最后没有完成(
Forwarded from 永久封存 | Yuuta 台 | 😷 #Pray4Wuhan (YuutaW 鱼塔)
为什么我认为 工欲善其事,必先利其器 是不完全正确的

工欲善其事,必先利其器 这句话大家耳熟能详,尤其是在各大社交软件(如某乎)的教程上,总有 【大神】 上来就给你塞上这句话,说先做好准备工作 balabalabala。我从一个业余开发者的 situation 出发,分享一下自身感受,以及为什么说 工欲善其事,必先利其器 是不完全正确的,而且会耽误时间。

比如,我最近在研究 Android 源代码的学习方案,如何开始学习 Android 源码,知乎一些大神给出了方案。某个回答的第一段就是讲某源码阅读软件比某 IDE 高到哪里去了 balabala,然后我查了一下这个被推荐的软件,价格 200+ USD / user。在这里,我又想到了另一个 situation。为了 P 图,不惜花钱去买某砖块公司的 XXShop 软体,时间和金钱都 “浪费” 在了这些被推荐的软体上。

这些软体之所以会被大神们推荐,肯定由于它们的确好用,大神也都是有经验的过来人,指导新手(写教程)的时候也一定不希望其他人由于软体不好用而走自己走过的弯路。这些我们都能理解,但是真的很必要在自己还没有着手学习核心内容的时候花大价钱,或者费劲地去 “利其器” 吗?

我这里不是讽刺那些付费软体,这不是本文的重点,因为付费只是 “利其器” 的一个门槛。我还回到学习 AOSP 这件事情上来说。在学习 AOSP 之前,真的要去花时间来准备学习的工具吗?这就像一个人,为了好好读书而花了几天时间来挑选中意的阅读器一样。

“利其器” 必然有用,但是如果把太多的金钱和时间都浪费在这些准备工作上,那么就是一种浪费。为何不先拿起记事本(极端地说),买本书,把这些准备的时间用在真正的学习上呢?等学好了,再准备,也不迟。

#观点
永久封存 | Yuuta 台 | 😷 #Pray4Wuhan
为什么我认为 工欲善其事,必先利其器 是不完全正确的 工欲善其事,必先利其器 这句话大家耳熟能详,尤其是在各大社交软件(如某乎)的教程上,总有 【大神】 上来就给你塞上这句话,说先做好准备工作 balabalabala。我从一个业余开发者的 situation 出发,分享一下自身感受,以及为什么说 工欲善其事,必先利其器 是不完全正确的,而且会耽误时间。 比如,我最近在研究 Android 源代码的学习方案,如何开始学习 Android 源码,知乎一些大神给出了方案。某个回答的第一段就是讲某源码阅读软件比某…
我觉得,就为 #GeekApk#GeekSpec 这个例子来说,是正确的,至少我不用去做一些完全体力的工作了... 虽然 GeekApk 还有部分 JavaEE / Spring 的模型接口/子类实现什么的必须手写,逻辑也必须用 Kotlin,但自动化无必要的、模板化的部分重要性不言而喻。

后面同样基于 GeekSpec 的 Spectrum 自动化 HTTP API 客户端程序,更是肯定了这么做的价值 — 写出接口定义本来的样子,最大可能去压榨它潜藏的用途

#UNIX 哲学里也提到一句:程序员的时间比计算机的时间宝贵,所以如果可能,就要写会写程序的程序,让它替代程序员工作。

优先使用工具而不是拙劣的帮助来减轻编程任务的负担。工欲善其事,必先利其器。