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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
dnaugsuz
所以Python害得定位差不多的Ruby受到迫害用户量减少,真是劣币驱逐良币。 还好在更规范的JVM平台上这是不可能的,虽然很多开发者依然按照习惯继续使用辣鸡到10才有 local variable inference 的Jawa,Kotlin依然已经(虽然是借助Google之手)在许多开发圈里火了起来,是Kotlin驱逐屑Jawa,至少比Python应用的情况好。
Java 1.3 是 Plain Old Java,那时候整个语言面向对象结构基本已经确立了。Java很早都有APT(Annotation Processing Tool)了。
1.4 加入了 assert,当然Kotlin里就是 assert 函数,当然Java里可没这么方便(Kotlin语言内部函数),真是的。
Java 5 是引入了 Generics, Autoboxing, enum 等,虽然 stdlib 的很多集合类依然是非泛型版本的,反观Kotlin现在全都是泛型版本的(而且还有 in/out 生产消费默写的安全泛型型变),辣鸡Jawa!
Java 6 是 @Override 注解支持在 interface 里用
Java 7 加入了 Diamond 语法糖项目、ARM、multi catch,这个改动也引入了 Union type,并集类型,虽然我很奇怪为什么不是 Intersection type,交集类型。难道 catch(A|B x) { x.methodOnA(); x.methodOnB(); } 能够编译?
Java 8 加入了 lambda 和 Type annotation
Java 9 支持语言内建 Modules、private methods in interface
Java 10 才支持 local variable type inference
Java 11 居然又新增 local variable syntax for lambda parameters (JEP 323),原因是语言一致性(uniformity)和支持对 lambda parameter 使用 local variable 的 annotation,难道不应该是一个大版本里面的吗?
Java 12 了才有 switch expression,估计是抄Kotlin的,谁叫它更新慢。(当然这也不能全怪 Oracle 和 Java 开发团队,毕竟他们有很多基于 Java 程序设计语言的框架比如 Swing, AWT, JavaEE 基础要维护,还要维护 HotSpot VM,但是从语言上来看,Kotlin绝对完爆Jawa。Kotlin是专心做语言)
#Java #PL
#Qzone #Java #Server
https://user.qzone.qq.com/3323659619/mood/63051bc6f8f3055e05da0300.1

iseki:
Spring …它真的不香… Vert.x 香(x

duangsuse:
同意,Sp 有点冗了,虽然我也没拿它写过什么(但是就框架上感觉过大)

Vertx 对异步任务和 events 抽象还不赖,我记得它的 CompositeFuture.all,记得它的 core, ext, web 子模块和 Router, HttpServer, Router#route 以及 Verticle, MainVerticle 的扩展。

但是 Spring 相比 Vertx 的确是有点令人费解了,甚至还默认上什么『诊断』组件,代码质量下去了,什么自动化其实都是废的。

Kotlin 的 Ktor 不知道 iseki 君有木有玩过,估计也不赖,何况还有 Kotlin HTML Builder DSL 加持,我估计都这样了也写不出烂项目来,不愧是 Kotlin 呢。Write once in one language, run anywhere on all platform.

iseki:
其实我觉得Vert.x搭配上Kotlin的coroutine就非常的舒服了,前提是别不小心把context搞乱就好…
#Kotlin Write once in one language, run anywhere on all platform.
编程就应该是这样,语言表达无关、平台无关,什么『专有』…… 都弱暴了! M$ 之前那么宠 C# 和 .NET,最后还是只能给它官方开源跨平台了呵,不是想弄成Windows专有的技术么。
#dev #PL #statement 今天好不容易天晴了,那就随便谈谈程序设计上的一些知识吧。

说的是『表述式(imperative)编程』和『定义式(declarative)编程』,它们是编程范式(programming paradigm)中区别最明显的两种。
偶尔,表述式也被称为『命令式』,定义式也被称为『声明式』。

如果让表述式的程序员写一段『把大象塞进冰箱』的代码,其中利用外部抽象『打开、塞进、关上』,他们会这么写:

事 入口() 为
打开(冰箱的门)
塞进(冰箱的里面、大象)
关闭(冰箱的门)

当然 *程序=数据结构+算法* ,我这里没有提到关于冰箱、大象的数据结构抽象建模方式,不过我也没有(为了简化讲解目的)过分实际到连 打开(物体) 都没提出来,只有 打开冰箱门() 的程度。

如果让定义式的程序员写呢?

事 入口() 为
塞进里面(冰箱、大象)
事 塞进里面(容器:物体、此物:物体) 为
打开(容器);塞进(容器的里面、此物);关闭(容器)

想想看,如果我们又要求在塞完大象后,放一首歌 比如,《亲爱的大象》 会如何?
如果我们的 塞进(物体、物体) 编程接口,可能(基于异常系统或是分情况的数据结构地)失败会怎么样?失败了第一是不能放那首歌,第二是不能异常退出整个程序。

(这里假设我们使用的是有自动内存管理,而无须指针弱引用啥子的语言)

量 歌者:播放器 = 播放器()
歌者去加载(文件("大象大象.wav"))
歌者的位置 = 0
歌者去歌唱()

我们讨论的问题比较抽象,但利用编程语言提供的表达式、程序和数据对象定义、基本控制结构组织这样的程序,就是我们的日常工作。

那么具体修改完的代码我就不贴了,因为实在有点长,但是我们肯定能预见到,表述式的程序员直接复制粘贴以上代码,而定义式的程序员又会定义出新的子程序(subroutine, sub-procedure) 事 播放音乐文件(路径:文)

其实一句话可以总结这两种编程风格(我本周的文章也会说到)
*『表述式越写越复杂,定义式越写越简单。』*

这里我们能够看出他们最大的区别,就是表述式的程序员喜欢「直白地」表达程序,而定义式的程序员喜欢抽提(抽象、提取)重复的程序逻辑,所以哪怕是我们要求再加音乐播放的功能、再要求塞大象进冰箱的子程序可能失败,都不会使得代码冗杂难看,不会进入所谓的『嵌套地狱』。

同样地,他们会努力地提升代码的可读性,也只有用定义式的思路编程,你才能设计出解决回调(callback)嵌套地狱的Promise异步任务抽象,而表述式的程序员则只会抱怨它难看,而不知道或者懒得去想到,其实有改进方法的。

你是表述式的程序员还是定义式的程序员呢?相信许多人会觉得表述式和定义式不分高低。(其实我上面说的『表述式』『定义式』也不是准确定义,而是说它们的使用者经常的编程风格,从某种意义上就是它们的『编程风格』)
不过,我个人觉得,不管是C、VisualBasic这样的『表述式编程语言』还是Scheme、Haskell这样的『定义式编程语言』,都不要忘记经常重新检查自己的代码,尽可能自然,而不是「简单」地描述你的程序。

要记得,真正的少写代码是使得它更好看、更少冗余,而不是在起名字上花费心思,最后弄得大家都看不懂,这也是Kotlin实际上的编程风格。

这不是智商低的表现,相反它是清清楚楚地认识到了自己和别人的智商、精力有限,抱持对软件和其他有兴趣查看源代码的人的善意,而对代码的质量格外地珍惜。
虽然『代码』实现只是软件里很小的一部分,在信息技术里也不是最关键的问题,我真心希望大家以后编程的时候,都要注意呦。

其实这里我也可以再顺便扩展地说到面向对象范式的内容的,也可以关于『编程是什么』这个问题说点观点,可是好像属于跑题内容……


浩哥也说过这个话题
#project Binarie 的(字节序上)『莫名其妙的问题』已经被确认为泛抽象数据结构(机器数的 shl shr and)编程失误,顺序没搞明白,pop_right 了 byte 导致 integralToBytes 的输出顺序是反的 0123 -> 3210。
E2im-2 基于标准输入输出流协议的一个细节(准确的说,是我『面向调试编程』导致的…… 很羞愧),多输出了换行符的问题将在明天修正。
Forwarded from dnaugsuz
lazy 到不会,其实是 lazy 里面所依赖的那些值偶尔还没初始化,我以为可以的。
比如:

val a: Int by lazy { b + depA }
val depA get() = a + 1
val b = 0

此时 depA 依赖还没初始化的 a,就是 null 了,我没想到 lazy initializer 里不能递归的……
Forwarded from dnaugsuz
Kotlin 的代码质量不是盖的,怎么可能在 Lazy delegate 的实现上出现低级错误。
Forwarded from dnaugsuz
那不是文言啊,那是现代文。每次我去学校的时候偶尔会有机会设计一下,目前也就完善了两次(第二次还没发上网)

最近我有 Kotlin Multiplatform 二进制序列化组合子库 Binarie 和解析组合子库 ParserKt 要写,暂时没时间实现它

因为绝句程序设计语言依赖很多上下文相关的语法(主要是实现『布局』语义特性的,比如逗号表示法、「为」文法,那是必须的。)
所以我绝对不能使用一些比较老式的解析器实现方式,比如ANTLR来实现它。

也只能慢慢看喽,何时有了 ParserKt,我打算先弄个 prototype(原型) 翻译到Kotlin。至于 1.0 的语言特性我得先实现另外一门「脚本语言」再考虑。

如果你感兴趣可以来看看之前的一些设计笔记,不算太严谨。
Forwarded from dnaugsuz
好像不会的样子,估计它Lazy递归就会null,而不至于死递归
Forwarded from dnaugsuz
没办法啊,可能有些语言的确是可以的吧(比如Scala)
可是过于高级的特性是没人用的 😂

Scala是没人用的(悲)
Forwarded from dnaugsuz
其实我主要是看不惯 ANTLR 大写式 terminal 小写 non terminal 的命名风格,而且对 Kotlin 来说,难道最好的 DSL 不是集成到它本身的 EDSL(Embedded Domain Specific Language) 吗?

ANTLR 也是蛮强大,比如有 Syntax tree listener、case non-senstive 兼容的输入 filter,而且也可以解析二进制流(当然,泛型解析是 ParserKt 的强项),虽然官方说是不能进行上下文敏感的解析。
但我觉得它真是有点太大了,虽然很易用,但不是很合适。
Forwarded from dnaugsuz
没办法,看看 Java 内置 compiler 有人用么
Forwarded from dnaugsuz
唉,我还记得 Java APT 那个 rootElements: Set<? extends Element> 还是 Set<? extends Annotation> 什么的,我真是看这一条都眼花了。
#PL 绝句考虑了一下是不是要区分“”双引单引‘’的注释/文档,后来我觉得,单引号是文档更好。
因为它显得更有『语言结构表达特质』一些。
Forwarded from dnaugsuz
文言文的『中文编程语言』有人写过了(还有两种),但是没人用:
https://new.qq.com/omn/20191218/20191218A0DVG600.html (这个是有很多star的,但只能用于计算机科学研究之用)
(好像是今年12月发布的啊!这么说中国的计算机科学教育还是有点效果。)

还有一个更早的大家忘了:Perl YuYan

其实高级语言直接的翻译,甚至是到基于图灵机顺序控制流的低级化翻译,就程序表示和转化领域而言这个项目算不上是高精尖,但着实是很有创意。

其实绝句最开始只是我瞎想要有一种以中文语言风格和语序表达程序逻辑的编程工具的,要我说绝句目前设计的方向是基本扩展自 Kotlin。

另外,其实想想我对绝句语言工具的一些细节设计也和这个同学不谋而和,比如标识符都可以让编译器直接机器分词(额外建立翻译过程)转化过去(到其他编程语言)(而这个是直接处理到拼pin1音yin1)来兼容国际化维护的。

举个例子吧,就我刚才了解的 WenYanLang,

吾有一数「x」 // 量 x:数 = 一百一十一
吾有一爻「p」 // 量 p:真假 = 真
吾有一言「s」 // 量 s:文 = "你好世界"
吾有一术「f」 // 量 f:()效果 = 函数,说("你好")。 “『函数』是一个全局多态重载函数,也有一同名类型『函数<入T1、入T2、…、出R>』”
吾有一列「xs」 // 量 xs:行<项> = 行一(1、2、3)



引记法 绝句.记号 「~次」
”吾有一数。曰三。名之曰「甲」。“
量 甲 = 三 ”‘绝句当然也支持汉字数值表示,代价是所有标识符不能以 零,...,九 开头……“
对 三次 里的_,
说("你好,世界!")
”吾有一言。曰「「问天地好在。」」。書之。“

怎么感觉那语言是面向栈的,但绝句是完全面向对象的,它的结构是 属别名(typealias)/常参(const val)、类(interface)、物(class)、例(object)、事(fun)、量(val)、变参(var)。

太晚了,其实绝句目前还只是个雏形,而且我上高三真心没时间继续怎么地啊,这就显示出大学生欺负人了啊!!!😂 说实话他们能够设计出这种真正意义上的『中文编程语言』我还是蛮惊喜的,其实也有点酸(。
duangsuse::Echo
至于一维列表是称为行还是列,最开始我确定的是列,可又总感觉理论上不是很统一(因为绝句里还有『行列』),我得到时候好好思考斟酌一下。
介于行一般是横着的,代表x轴,一般位图下标是 bitmap[y][x] 的形式出现(我觉得很好看,我只要我以为,不要你以为……)
而列一般是竖着的,代表y轴

这样看就是『列行』了…… 那就列行吧

……我还是觉得,不要用『列』好,免得分不清。
duangsuse::Echo
运算符: 前、后 (dec/inc) +(加)、-(减)、*(乘)、/(除)、%(取余) -~(取负) 大(>)、小(<) 不大(<=)、不小(>=) — 这一行括号里的表示法仅参考用 汉语里就不要用小于号、小于等于了。 取负的 -~ 只是注释,绝句不存在前缀记法,只有前缀算符 &(且) |(或) !~(取非) (异) — 只有真假类型有 绝句的且或非逻辑都是短路计算的,也就是说 假 & 不可能, 真 | 不可能 我相信,既然绝句已经改了这么多了,不会有人觉得让 (&) 官复原职很奇怪 第一眼看了…
昨天晚上睡不着(一想到有大学生弄了算是同类的东西,而且是大学生有一整周的时间光明正大弄而我每周只有不到三天,实在是有点莫名难受)

然后我又考虑了一下之前这么写的 lambda parameter:
https://t.me/dsuse/11778

宫水家.找,她:她的名字是"三叶"。手机上的最近聊天记录.数,它的发送者是泷。有若「大五十」 空则,抛下沃日

现在因为「:」的语义改成和 「:」 一样了(准确的说,我已经决定不允许使用半角的 ':',实际上这周我在学校里还好好考虑了一下全角/半角的可置换性,我的结果是:完全不允许,但解析器得查出这种错误)
(而现在唯一可以同时用在程序表达式和构造定义里的符号,就是小写括号了)

所以我不得不换个方法,于是我翻了翻常用中文符号,

宫水家去找,【她】她的名字是"三叶"。手机上的最近聊天记录去数,它的发送者是泷。有若「大五十」 空则,抛下沃日。


这么写还怪好看的。
之前就确定的是 Annotation 咱就用 【】 来。

语言上的标签我觉得其实也是可以用中文括号的(而且中文括号真TM多啊)
开始考虑的是〔〕。其实也没啥问题。

对[楼] 此楼里的家,对家里的这人,
若这人的包里有枪,去报告(警察、这人)、略过[楼]。


对〔楼〕此楼里的家,对家里的这人,
若这人的包里有枪,去报告(警察、这人)、略过〔楼〕。


可我觉得蛮没有必要,绝句里有「」表示中缀、『』表示名字、{} 是可选的逗号表示法替换(为了语言一致性,我也不想让那些程序员写东西有时「为」有时 「{}」……)、…… 等等

https://github.com/LingDong-/wenyan-lang#syntax-cheatsheet
如果你去看「文言」程序设计语言的reference,你会发现他们一个语法有很多表现形式,比如

批曰。「「注释」」。
注曰。「「注释」」。


关于绝句是否也要加入同含义多表现形式这点,我持否定态度。
绝句的语言一致性是很重要的,即便只是注释这点我也不会同时允许“” ‘’ /**/ {--} 作为注释起止存在。

然后我还考虑了一下之前的「变长」修饰符,我觉得它应该被改成「多个」

对何<项>皆有
【只可内联】的事 行一(变长的 项目:项):行<项> 为 “Kotlin listOf(…)”
量 此行:行<项> = 行()
对项目里的,此行去加(它)。回此行

【只可内联】的事 行一(许多的项目:项):行<项>……

新风格。
顺便说一句,发现「文言」语没有布局文法(就是绝句的「为」「」)以后我忍不住欣喜了一番。你怎么那么欠打

吾有一術。名之曰「吸星大法」。是術曰。⋯⋯是謂「吸星大法」之術也。

这实际上就是比较普通,而且在解析器设计上和 () 这种括号没本质上的区别的 {} 花括号,主要区别在于 () 用于 group 表达式、{} 用于 group 语句。

吾有一術。名之曰「翻倍」。欲行是術。必先得一數。曰「甲」。乃行是術曰。乘「甲」以二。名之曰「乙」。乃得「乙」。是謂「翻倍」之術也。

事『翻倍』(甲:数):数 = 甲*2 “跟括号式的名字后不用加空格”
“或者,”
事 翻倍(甲:数):数 为
量乙 = 甲*2;回乙 “知道我为什么用「量」而且区分了「量」和变参吧?存储和「临时值」实际上有不同的”
“或者,”
事『翻倍』(甲:数):数 = 甲去乘(二)令为,〖乙〗回[令为]乙。

文言的创意虽然很好,但我发现他的作者貌似是 JavaScript/Ruby/Python 系的程序员,而且会基本2D绘图编程。

我是函数式的程序员,所以有机会设计出基于布局的文法,以及中缀链「」来使文法更方便阅读,但 JavaScript 系的程序员是想不到的,哪怕他们也会写许多算法。因为无论 JavaScript(ES6)/Ruby/Perl/C/C++/Java/C#…… 等语言都没有支持布局,虽然Python支持了但…… 不是很好看,想直接移植到中文也总感觉缺了什么。自以为设计的逗号表示法是相当好看而且有用的,尽管其实是扩展自Kotlin对「代码块」和「闭包块」的相同表现形式。
duangsuse::Echo
#PL #PLT 为了方便大家了解一下,我在正式开始编写设计文档前会简单谈一下『绝句』程序设计语言的表达方式。 我不会提及任何设计逻辑、推导的东西,这对绝句来说应该是实现细则,只需要说「必须写明类型」、「能够智能转型」即可。 — 例子: 分二查找.jue — “之所以叫『分二』,是因为绝句里以『二』开头也是表示数字的方法……” “在上升序列 [自己] 中二分查找一个 [目标] 项目” 对何<项: 可比<项>>皆有 私下、尾递归的事 分二查找(自己: 行<项>、目标: 项、范围: 数域): 引数? 为 …
吾有一術。名之曰「埃氏篩」。欲行是術。必先得一數。曰「甲」。乃行是術曰。
吾有一列。名之曰「掩」。為是「甲」遍。充「掩」以陽也。
除「甲」以二。名之曰「甲半」。

有數二。名之曰「戊」。恆為是。若「戊」等於「甲半」者乃止也。
有數二。名之曰「戌」。恆為是。若「戌」等於「甲半」者乃止也。

乘「戊」以「戌」。名之曰「合」
若「合」不大於「甲」者。
昔之「掩」之「合」者。今陰是矣。
若非乃止也。
加一以「戌」。昔之「戌」者。今其是矣云云。
加一以「戊」。昔之「戊」者。今其是矣云云。

吾有一列。名之曰「諸素」。
有數二。名之曰「戊」。恆為是。若「戊」等於「掩」之長者乃止也。
夫「掩」之「戊」。名之曰「素耶」。
若「素耶」者充「諸素」以「戊」也。
加一以「戊」。昔之「戊」者。今其是矣云云。
乃得「諸素」。
是謂「埃氏篩」之術也。

施「埃氏篩」於一百。書之。


这个素数filter,用绝句一般的写法(也基本算是Kotlin一般的写法)
表述式该这么写(绝句的『存储』抽象在原型阶段是还没设计好的,另,我刻意对照了上贴代码的结构):

事 埃氏篩(x:数) 为
量 掩:行<真假> = 行(x),假。;对掩的索引里的针,掩[针]=真。
量『x半』 = x / 2
变数 i = 2;重复, “如果不想写类型也可以 变参i=2”
若i是『x半』,停下。
变数 j=2;重复,
若j是『x半』,停下。
量 此积 = i*j
若此积不大x,掩[x] = 假。否则,停下。
继续。j=j后
继续。i=i后“若真。”
量 诸素:动行<数> = 动行(x),零。
量 诸素子:变迭子<数> = 诸素去变迭代()
变数i=2;重复,
若i是掩的末引,停下。
量 此为素 = 掩[i]
若此为素,诸素子去加入(i)。
继续。i=i后
回诸素

事 入口() 为
  去::埃氏篩.用 “也可以说「去::埃氏篩去用」” (100) 令为(去::说) 

也可以按照绝句一般的(表述式)编程风格:

事 埃氏篩(x:数) 为
量 非掩:动组<真假> = 组(x),真。
量『x半』 = x / 2;量『二启数』 = (2..数的无穷大)
对二启数里的 i,
若i是『x半』,停下。
对二启数里的 j,
若j是『x半』,停下。
量 此积 = i*j
若此积不大x,非掩[x] = 假。否则,停下。
量 诸素:变行<数> = 行一()
对二启数里的i,
若i是掩的末引,停下。
量 此为素 = 非掩[i]
若此为素,诸素去加入(i)。
回诸素


也可以这么写,我数学不好就不继续转化成定义式风格了。

引记法 绝句.符号 「止」

“始末是 right-inclusive、起止是 right-exclusive,注意『起止』不能在不加方括的情况下作为名字”
事 埃氏篩(末:数):行<数> 为
量 此为素 = 动组(长=末),真。
量『末半』= 末 / 2
量『二止末半』 = (2止末半)
对『二止末半』里的 i,
对[试j]『二止末半』里的 j,
量 此积 = i*j
“若此积不大x,此为素[x] = 假。”
变参 可止 = 假 “瞎写的”
此为素[此积] = 此积大x 顺便,
若它,可止 = 真。
若可止,停下。
“否则,停下。”
“若此为素[此积],停下[试j]。”
量 诸素:变行<数> = 行一()
对『二止末半』里的,
若它是『此为素』的末引,不可能。 “断言了。”
若此为素[它],诸素去加入(它)。
回诸素


当然可能有写错的…… 特别是集合可变性……

文言的恆為是。…… 在绝句里就是 重复若条件…… 这里条件=
上面的重复……继续。 权当我没写过。
你们也看到了,其实很多循环就不该写成无限+控制流break的形式,此外『重复若真』也的确是有那么一点感觉。
绝句永远是为 90% 的情况优化,不可能为了一个极端情况加特定语法,我们不想变成C++或者Python。
此外,绝句的 do while重复…… 若…
「重复」跟的就是「若」(而不是「当」,因为那么做不好区分 whiledo while

变数 i=0;重复若i小10,i = i后。“i=10”

变数 i=0;重复,i = i后。若假 “i=1”
变数 i=0;重复若假,i = i后。 “i=0” 

while 就是 if (p) 版本的 do while,当然控制流上是类似这样:
do_while:
operation
br.not :out
jmp do_while
out:
// merge

while:
br.not :out //notice this
operation
jmp while
out:
// merge


对应到控制流上「重复」「若」也是相当好看的,「重复」就是上面的 :while, :do_while 指令偏离量标签和后面的 jmp、「若」就是 br.not :out 判断。
http://wenyan-lang.lingdong.works/ide.html?example=factorial

看了许多example,算法欧几里德服气。