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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
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,算法欧几里德服气。
dnaugsuz
文言文的『中文编程语言』有人写过了(还有两种),但是没人用: https://new.qq.com/omn/20191218/20191218A0DVG600.html (这个是有很多star的,但只能用于计算机科学研究之用) (好像是今年12月发布的啊!这么说中国的计算机科学教育还是有点效果。) 还有一个更早的大家忘了:Perl YuYan 其实高级语言直接的翻译,甚至是到基于图灵机顺序控制流的低级化翻译,就程序表示和转化领域而言这个项目算不上是高精尖,但着实是很有创意。 其实绝句最开始只是我瞎想…
其实我真是蛮酸的,尤其是看到自己的无人问津(当然我不怪Telegram)和CMU高材生的后生可畏。

他们是大学生啊,我可是高中在读的很不称职的高中生啊,羡慕人家的光明正大。

现在还得弄Binarie和ParserKt,绝句虽然最近就可以设计,也只能暑假开始了,我完成至少是ParserKt才可以动工(还好,ParserKt的DSL,PKNF, ParserKt Normal Form暂时不需要动)

设计也算不上,其实就是归纳下之前的设计,不归纳的设计都是渣设计、不抽提的编程都是写屑代码。
https://github.com/swizl/tinycc_zh

虽然还有其他的事情,为了方便整理绝句的设计,我把一些类C的关键字枚举一下……

— 数据类型
void - 空 = 例 绝句.效果
bool - 布耳 = 真假
char - 字(8-bit unsigned) = 无符字节 “目前当然是Kotlin有所以我们才有”
signed char - 有符字(8-bit unsigned) = 字节
short int - 短 = 短数 “无符情况都是一样”
wchar_t = 字儿
int - 整 = 数
long int - 长 = 长数
float - 单精 = 浮数
double - 双精 = 实数
char * = 文

属别名 计数 = 数
属别名 引数 = 数

— 子程序局部语言结构



— 控制流

if = 若
else = 否则
switch = 判…,
case = ✖️ “这是绝句里的 when 文法,是C式switch的扩充。”
while = 重复若
do …… while (…) = 重复…… 若…
for = 对…里的〔名〕…… | 解对…里的(模式)……
break = 停下
continue = 略过
return = 回
goto = ✖️

— 小语言构件、修饰符等
extern = 待例
static = ✖️
signed = ✖️ unsigned = ✖️
short = ✖️ long = ✖️
const = 常
volatile = 【并行易变】
register = ✖️
auto = ✖️ “绝句和Kotlin一样是自动类型推导的强类型,而C99里auto只是storage classifier,一般认为完全没必要写,都是栈上分配存储空间”
inline = 内联
restrict = ✖️ “要限定直接用 组<T> 动组<T> 的分别就可以了,实在不行还可以 组<出T> 基于生产消费模型的型变性和集合可变性安全”

— 大语言构件
struct = ✖️ “绝句1.0 应该会弄出 存储<T> 和 分配 的抽象来,这样 struct 直接继承自 分配 而不是 值 就可以了”
union = ✖️ “绝句包含面向对象范式,应该使用子类型而不是不明确的并集类型实现union”
enum = 例物 “enum class”
typedef = 属别名 “绝句里,类型被称为「属」,和「类」「物」是有区别的”
default = ✖️ “在 when 里,fall thru 直接用「上皆……」实现,default 就直接是 else(否则)”
sizeof = ✖️ “除非绝句未来特别兼容Native,否则不会提供,况且提供也不会作为关键字,绝句语言设计上对添加语法糖是很克制的。”
attribute = ✖️ alignof = ✖️ typeof = ✖️
asm = ✖️ “attribute 就是Java的Annotation,绝句是支持【注解】语法的,其它的没有意义。”

预处理器:
define, undef, include, include_next (覆盖header定义)
ifdef, ifndef, elif, endif
defined,
error, warning, line, pragma,
VA_ARGS, COUNTER

以及文件、函数、函数名、行号、编译的日期和时间

通通都无效。不过绝句倒是有「包」「定记法」「引记法」「引(成)」「引全(除)」。
duangsuse::Echo
https://github.com/swizl/tinycc_zh 虽然还有其他的事情,为了方便整理绝句的设计,我把一些类C的关键字枚举一下…… — 数据类型 void - 空 = 例 绝句.效果 bool - 布耳 = 真假 char - 字(8-bit unsigned) = 无符字节 “目前当然是Kotlin有所以我们才有” signed char - 有符字(8-bit unsigned) = 字节 short int - 短 = 短数 “无符情况都是一样” wchar_t = 字儿 int…
刚才考虑了一下,发现『浮数』『实数』和『短数』『数』是不一致的
应该叫『短实数』『实数』才对,如果有人有好的命名建议call我。

代码直接表示的整数默认是『数』,也可是『长数』
代码直接表示的浮点数默认是『实数』,也可是『短实数』

Range仍叫『数域』(什么长数域、短数域…… 关键是,用区间会导致『字节区间』这种命名很长的情况,我不希望有这种物名)、Progression叫『步进』


决定了,「.」中缀语法只能拿来表达全称名(比如引用例物的一个 case variant),没有此人.为聪明人这种说法。

昨天晚上考虑出来的是:
〖〗的 lambda closure parameter list
『许多(vararg)』修饰符,这是重新定义,原名是『变长』。

Trie 树 walk的三种情况:刚刚好、过长、过短
以及 walking 的两种情况:过短、失败、成功。
https://zhuanlan.zhihu.com/p/40356993

我们再来看看绝句基于类似 Haskell 的自定义中后缀『记法』,能和这样DSL形式泛滥的『泛向编程语言』有多大的差别。

无需多说,进行计算机编程的第一步是掌握编程语言。
绝句的思想,进行计算机编程的第一步是掌握模式化解决问题的思路,比如顺序、判断、重复。

第一,当前主流的编程语言对于普通人还是太难了,即使是最简单的Javascript、Python、PHP等,也都有太多的知识点,比如闭包、作用域、位运算、迭代器、继承。为了让行业外人士能够容易掌握,中文编程一定不能照搬主流语言,而要对它们进行简化,去除复杂的知识点。
我很同意,但那些知识点举几个例子日常使用是不存在任何问题的,作用域以词法作用域照着语感实现不就好了吗,继承难道不是最自然的事情吗。

第二,要“信达雅”。好的外文的翻译要“信达雅”,好的中文编程也要“信达雅”,像一篇文章一样,少用符号,多用文字,要让人容易读,容易理解。
此外,还不能滥用创造者视角,不否定符号的价值、不能一切皆文字。好的创造者要从用户的角度考虑问题,而不为解决特定问题随意修改语法。

第三,不要有太多嵌套。
所以函数式编程和文法布局的设计都是很重要的。

C#语言中实现用控制台打印”你好”的程序是

控制台.打印(“你好”);

Z语言实现打印“你好”的程序是这样写的

控制台打印“你好”


绝句实现打印『你好』的程序是这样写的:
说("你好")

“标准库定义”
【只可内联】内联的事 说(话:文) 为
说(话);说完了()
也可以:
说点("你");说点("好");说完了()
(我是刻意为了和Kotlin对应的,好像没有刻意与Kt拉开距离的必要)
或者对应上面的代码,
控制台去说("你好")
不过用『记法』也可以这样,
引记法 绝句.符号 「写」
引 控制台.标准输出 “just a joke”
标准输出写"你好"

面向对象,就是一群对象互相发『消息』、互相驱使的过程,而这个『驱使』的动词为「去」。利用暴露的「取者」「置者」访问对象状态的动词为「的」,两者皆可的符号就是「.」了。
记法,是绝句的自定义中缀运算符。

Z语言程序没有点号,没有括号,末尾没有分号,看起来和一般的中文句子没有两样,中国人理解起来非常容易。
绝句为了一些迷之原因(可能是为了兼容不同的编程风格?)加上了「.」(我可能决定要去掉?)
末尾怎么不能有分号了,若此人之为男,说("👻")、说("👻")。 (记法「之」)还不行么

(哦,想起来了,此人.为男也不失为一种编程风格,但我现在对不使用引记法的绝句代码表示怀疑。)

C#取成员用‘.’号,比如
T.年龄
Z语言是这样
T的年龄

绝句也是一样,不过不存在所谓的静态字段,而是和Kotlin一样采用了 companion object(面向对象本来就不应该有所谓的静态成员的,只该有类、对象、架构器、方法、属性)

去除new
绝句也不要new就能调用架构器

var P=new点(0,0);
P=点(0,0)
量P=元二(0、0)

C#语言是 函数名称+参数列表
Z语言是 函数部分1+参数1+函数部分2+参数2+...

void 打开文件(文件,读写方式)
以(读写方式)打开(文件)
绝句可以选择基于记法的EDSL,上面的『多参并列』其实我以前连字典树都不会写的时候也想过,就是老绝句(「预处理器」版本的)
为了语言的明确性,我不能这样设计。

属别名 路径 = 文
事 打开文件(模式:打开模式、文件名:路径):文件……

这是一般方法,量 hello = 打开文件(打开模式.只读、"hello.txt")
定记法 「模式」
扩物 文 为
事「模式」(模式:打开模式):元二<路径、打开模式> = 元二(我、模式)
事 打开文件(目标:
元二<路径、打开模式>
):文件……
这是EDSL内部专用语言定义式,量 hello = 打开文件("hello.txt" 模式 打开模式.只读)


省略主语
枚举类可以省略主语
比如枚举enum读写方式{只读方式,只写方式,读写方式}


绝句的枚举不可能像C一样没有规范地随便给作用域做变通,一般来讲这是需要「引」引入的。

引全 打开模式 “import OpenMode.*”

例物 打开模式 为
只读、只写、读写

这样就可以了。之前有一次我想了想是否要花精力尝试支持自定义前缀如「以~」
可是后来我觉得,中文编程关键在于编程,而不是一切皆中文表述,与常见的表达顺序兼容是很重要的,Scala虽好但是很可怜。绝句完全可以在内部提供一个 以(T):以句法 函数,然后随便定义引用扩物来实现『全中文编程』,但那还有规范可言吗?所以我后来没加……(何况加上也很莫名其妙,严重加大了代码风格的不确定性)

打开文件(文件W,读写方式.只读方式);
以(只读方式)打开(文件W)
打开文件("hello.txt"模式只读)


稍微往远处走走,你会发现仅就以上例子而言,更『灵活』的语法反而不如更死板的Kotlin扩展式:

用户配置文件=以(只读方式)打开(文件W) 

量 用户配置文件 = 打开文件(只读、"hello.txt")

看不出区别。如果要加入异常处理呢?

尝试
用户配置文件=以(只读方式)打开(文件W)
捕获 打开失败
用户配置文件=空

量 用户配置文件 = 尝试,打开文件(只读、"hello.txt") 。
接迎 打开失败成误,误去输出()、回。


那么,如果有可选的参数(比如最经典的,Kotlin 的 Iterable<T>.joinToString(……))呢?直接的中文调用模式是难以利用默认参数的,尽管这样表达基本不需要显示写出参数名。
汉语、汉字是美的、富有信息量的,但只有你开始重视程序算法、程序表述方式的美,使得它在保持简单漂亮的同时也能尽可能干净利落,才有可能把两个美有机结合在一起,最终完美地实现一个编程语言、编译器需要解决最本分的工作——让人编程、让人又快又好地编程。
『玉有灵性,反之也有邪性。』,事物往往都有两面性。

汉语编程,做好了能够让刚入门的中国人像编程大师一样肆意实现出各种曾经复杂难懂的逻辑,做差了,以纯汉字表达的程序会不留情面地显现出汉字丑陋的一面,更难看、更难懂,令语文老师觉得满篇不合体、缺语素,也可能让刚想试水的工程师最终悻悻离开,不能实用。 #statement #PLT 🤔
🤔duangsuse 昨天晚上想到了一些话,愿意分享给大家。 #statement

duangsuse(虽然一点也不好)是如何编程的呢?
他编程,是一个从整到零,再从零到整的过程。

首先是把一个相对比较大的目标,拆分成许多能够比较简单实现的小目标
比如,把一个操作纷繁复杂的类(class),抽提出实现了很多接口的类。

接着是和自己争论实现的难点和复杂性,继续重新拆分和重新组织继承、数据依赖这样的关联,偶尔还会为一些经常联系在一起的东西(比如 Database, Controller) 起一些首字母简写,记住。
比如,它会把二进制流读取器弄成 class Reader: BaseDataReader, ByteReader, ReadControl 而不是把所有这些操作,放在一个类里面。

然后是实现这些小目标。

最后,他按照在实现小目标时早已预备好的思路,把许多子程序组装成整个程序。

如何做出好吃的糖炒板栗?大的小的分开炒。一起炒的话,小的糊了大的没熟,怎么也不好吃。

如何写出好看的程序?每个部分分开写。写成一坨的话,两个事情里类似的子过程,差异不大,却让人迷迷糊糊分不清,怎么也不好看。

fun <R> Producer<R>.retry(n: Cnt, terminate: PredicateOn<R>): R?
= sequence { invoke() }.take(n)
.dropWhile { it != null && !it.terminate() }
.firstOrNull()


fun <R> simplier_retry(n: Int, terminate: PredicateOn<T> = { true }, op: Producer<R?>): R? {
for (_i in 1..n) {
val res = op() ?: return null
if (terminate(res)) return res
}
return null //这是一个『线性查找』的控制流模式,可以用sequence抽提成定义式的形式。
}


堆砌从简单到复杂,再到写不下去、开始忌惮自己的维护;设计从复杂到简单,最终对代码的一切都了若指掌。

有人说『从不写bug所以不需要debug』,相信吧,他们是对的。其实本来就不应该有bug,最精炼的代码,基本上在纸面debug就够了。
有人觉得『A4纸编程』是很NB的大佬才能做的事情,为什么平常人不能做?难道他们真的连『广播体操』打着节拍都不会跳了么?要编程就得有能上A4纸写的勇气才行。

android { compileSdkVersion(26)
defaultConfig {
applicationId("org.sample")
minSdkVersion(6); targetSdkVersion(19)
versionCode(1); versionName("1.0")
}
buildTypes {
release { minifyEnabled(true); proguradFiles(defalutProguradFile, "progurad-rules.pro") }
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
compileOptions {
sourceCompatibility = Java8
targetCompatibility = Java8
}
kotlinOptions {
targetJvm = "1.8"
}
}

为了使得代码稍微好看、好记那么一点点,我甘愿打破一切所谓的『代码风格』,拒绝使用任何刻板的自动格式化器毁坏我对布局的整理,甚至哪怕设计一门新的编程语言来或多或少的修补Kotlin的华点也在所不辞。因为我明白,编程语言只是『做菜』的材料,厨师的刀功、能力,才是程序设计最重要的东西。

外表看起来漂亮、看起来不乏味单调或者不「多余」,很多时候才是最大的陷阱。我更在乎程序的灵魂,而不仅仅是它那任何一个解析器都能机械地识得的形式。

堆砌者开始不明白自己要写什么且只有编写简单程序的功底,所以开始是简单的,但也正因为不知道自己要做什么,所以越写越复杂。
随着他们从别处的模板复制来的逻辑越来越多,对代码整洁、布局顺序的着眼率越来越低,整个项目会走上重构越来越耗时、越来越难以扩充和测试的死胡同。

设计者一开始就明白自己要做什么样的东西,它的基础目的是什么、必须要什么算法、大概会有哪些逻辑重复、使用了什么外部API和抽象、未来可能有怎样的变化,所以随着逐步的细化程序越来越简单、代码复用程度越来越高、维护越来越轻松。

简单不是因为愚蠢,而恰恰是对自己和别人的精力限制有着清醒而深刻的认识。大智若愚,深深认识自己的「蠢」并且着实去解决它。
编程不是为了显得自己有多高明、多数学,而是想尽可能直白、尽可能好地定义完程序为解决问题所必须要做的事。

你是要「堆砌」出你的程序,还是要最终坚持着把它「设计」完?
你觉得你的程序只是给一个人、一个人的项目用,还是把它发布出去,让所有人都能少做本不愿下的苦功?

把世界视为过程,还是对象?是不是要有 closure(闭包)这种东西方便抽提执行逻辑?是不是要有 sequence 来表示一种…… 计算过程和结果的序列?
决定吧,以后不仅仅要学会利用别人的API编程,更要明白编程这件事,除了模式识别,在『修改别人的代码』『仿照有效代码的样子』外还剩下什么。

编程不再乎对一个项目「累积写了多少时间」,而在于你对你的目的和编程的「道」,有多大程度的了解。

因为「项目」只是某个时间的状态,它只能表示现在,而「方法」则是变化率,它代表着未来。
授人渔,而不只授人鱼。
争得渔,别老是争得鱼。
Forwarded from duangsuse Throws
啧啧啧,虽然易语言提供了语言运行环境、IDE和基础库,但它身为『面向对象编程语言』居然连基本的中文语序都做不到,还和洋文一样把操作放在前边。我深深感到这5kw纳税人的钱是用到刀背上
我们来对比一下迫真易语言的『容易度』和绝句的『容易度』

这里易语言的代码风格我参考了 Kotlin(1space) 的格式。
引入 apr;
公开 类 启动类 {
公开 静态 启动() {
整数 数量;
控制台.输出行("请输入将要生成的随机数个数:");
数量 = 控制台.输入整数();
随机数集合.显示(数量);
随机数集合.显示();
}
}
公开 类 随机数集合 {
公开 静态 显示(整数 生成个数=10) {
字节集 临时字节集;
整数 I,J;
内存池 局内存池 = 创建 内存池;
控制台.输出行("下面开始生成"+生成个数.到文本+"个随机数====>");
计次循环(生成个数,J) {
临时字节集 = 随机数.生成随机数(1,局内存池);
I = 字节集类.到整数(临时字节集);
控制台.输出行(整数类.到文本(I));
}
控制台.输出行("<========随机数已生成"); 控制台.输入文本();//暂停屏幕滚动用
}
}

我几乎忍不住要喷了。整数类.到文本(1),这也能够算是面向对象?它知道啥叫封装么?

引记法 绝句.符号 「~次」
引 Apache.PortableRuntime

例 随机生成: 应用程序 为
实现的事 入口() 为
说("请输入将要生成的随机数个数:")
量 数目 = 听去数一()
随机数集去说(计=数目)
随机数集去说()
例 随机数集 为
事 说(计:计数 = 10) 为
量 存池 = 内存池()
量 随机数组:组<数>
说("下面开始生成${计}个随机数====>")
对计次里的 j,
随机数组 = 随机数器去生成随机数(长=1、分配器=存池)
量 I = 随机数组去化数()
说(I去化文());
说("<========随机数已生成");听去行一() “暂停屏幕滚动用”

然鹅,我这还是给易语言留了面子的情况,要知道绝句完全可以把这段程序写得更好看:
引记法 绝句.额联 「令为」
引记法 绝句.符号 「以」
引记法 绝句.符号 「~个」
引记法 绝句.符号 「化」

引 Apache.PortableRuntime

例 随机生成: App 为“皮一下,标准库里不一定有这个别名,当然绝句也可以用上「类物别名」的”
实现的事 入口() 为
说("请输入将要生成的随机数个数:")
量 数目 = 听去数一()
说("下面开始生成${数目}个随机数====>")
随机数之集去取(数目个) 令为,它以(" ")去接并()。令为(::说)
说("<========随机数已生成")
听去行一() “暂停屏幕滚动用”

例 随机数之集:随机数集()
物 随机数集 为 “也可以是单例的”
私下、晚成的“lateinit”变参 存池:内存池
事 取(次:数目):行<数> 为
存池 = 内存池()
量 随机行:行<数> = 行一()
解对 次里的_,随机行去加入(随便一数())。
回随机行
私下的事 随便一数():数
= 随机数器去生成随机数(1、分配器=存池)
去化数()
duangsuse::Echo
https://www.yinwang.org/blog-cn/2019/12/26/success
淫王19年终于又出博文了啊,我待会看看,感谢推送。 #blog
duangsuse::Echo
我们来对比一下迫真易语言的『容易度』和绝句的『容易度』 这里易语言的代码风格我参考了 Kotlin(1space) 的格式。 引入 apr; 公开 类 启动类 { 公开 静态 启动() { 整数 数量; 控制台.输出行("请输入将要生成的随机数个数:"); 数量 = 控制台.输入整数(); 随机数集合.显示(数量); 随机数集合.显示(); } } 公开 类 随机数集合 { 公开 静态 显示(整数 生成个数=10) { 字节集 临时字节集; 整数 I,J; 内存池 局内存池…
我吃饭回家路上考虑了一下

首先为了能够实现
函数,〖x0〗x0。
函数,〖x0〗
x0
这种逗号表示法的形式,这个样子的逗号表示法类似:
逗号块(逗号修饰, 体)……

同时,我也终于决定抛弃了逗号表示法的 {} 替换:
若p { op0() } 否则 { op1() } “不允许。”
毕竟绝句不需要像 Haskell 那样 \case ox (Some x) -> 切换布局块和非布局块版本的语法,逗号表示法「,、。」是比较简单的。
现在这个开闭符号是『reserved』了。

然后,绝句也可以利用记法、扩物和内联的物兼容传统汉语的表示形式(比如『把(x)加进xs』)
这个扩展将在标准库的 绝句.严格中文 里实现。

然后,绝句的相对Kotlin的一些语法扩展:

「为」布局定义、「其中」布局定义、逗号表示法、第二|三人称的「你」「它」、「的」「去」、『记法』和「」中缀链、『』名字、【】注解、汉字数值常量表示。

""" 为 是对 raw string 的布局化扩展,之间区间 (0,1) 个空格,多了不算。
关于其中是否支持 $, ${} 一说,Kotlin 是支持的,不打算改变。

逗号当然也包括顿号的。比如:对用户里的,好人里去划掉(它)、坏人里去划掉(它)。

一些常见语法:

对…里的(名)……
对…里的你…… “第二人称”
对…里的…… “第三人称”
若你… …… “第二人称「若」” (删掉,这个语法其实是冲突的,而且在正常代码里也无必要。
【无参注解】
【带参注解 参0、参1、...】

判断……
判… ……
(「它」第三人称中缀简写)
判属… ……(于、它)
判存… ……(于、它)

所有判断都可以有语句形式和表达式形式,表达式形式的分支必须有穷举性。
「、」是逗号表示法里常见的语法,只不过不同结构有不同表现形式。
提供的「上皆……」都是副作用的形式,表达式里不允许。
「否则……」在表达式里也允许,这时预期的不是效果而是值。

一些规范化修订:

解量、解对、判属于、判存于、「空则」逗号表示法

重复若、重复……若。

绝句的面向文件定义结构:

包、记法(定、引) 、引(成)、引全(除)
属别名、类物别名、常参、类、物(造于、初)、例、事、量(取者、置者、代者)、变参。

突然想起来,:: 是引用文件级事和架构器?
架构器不是函数??? 🤪
那么就没必要区分属别名和类物别名了,都一样。

我决定了,第一设计稿应该把「变」初始化的 = Expr
改成 初 Expr,要不然显示不出参量变化的精髓。
变参现在是
变 属名 角括名字 初 Expr
变 属名 名字 ws1 初 Expr
变数 和 初0
的形式

还有,「包」在汉语里不应该还是原来的 package (qualified-name); 形式
包 (复名) 为
这样(其中,复名是复合名称的意思)

PKNF(ParserKt Normal Form) 是一种形式化文法描述语言,它可以为 ParserKt 生成有效化、优化的代码(比如合并前驱、分支遮盖式前驱重排序)
合并前驱的功能可以让
变 属名 角括名字 初 Expr
变 属名 名字 ws1 初 Expr
变成利用 ParserKt 递归下降上下文相关解析来判断翻译成类似这样:
变量 ('变' 属名)|变参 后继:(anychar) where
后继:(run c) caseA|caseB
caseA lookahead:('『' ) 角括名字 '初' Expr
caseB 名字 '初' Expr
它只需要能够对任意两个子结构取 succeeder union (交集)和 succeeder complement (补集)就可以启发式合并分支了
complement 角括名字 名字 = setOf('『')
complement 名字 角括名字 = setOf()

— 所以只要出现的字符是'『',就只可能是角括,否则只可能是普通名字。

但是PKNF开发比较复杂,而且理论上的很多东西暂时不完善(也别指望它们太完善)
所以一时间ParserKt是不可能用上PKNF来定义自己的上下文敏感语法的,尽管PKNF已经被我完全形式化定义好了(以它自己描述它自己……),要用可能是一年后了。

令做(run)、令为(let)、令置为、顺手(also, (T)效果)、交给(支持 (T)* 的 also)
有若(takeIf)
成文(toString) 成码(hashCode)

滤出(filter)、映至(map)

存一(find+不空)、存仅一(single)、皆是(all)、皆非(none)

后来我发现它们有点不规范。
令为(let)、令做(run)、令试(runCatching)、顺便(also)
有若(takeIf)、有非(takeUnless)
对(to)
化文(toString)、化记码(hashCode)
滤出(filter)、映至(map)
存一(find)、存仅一(single)、皆是(all)、皆非(none)

apply, use 比较让中国人不明所以、with 已该被换为let。

—取此即值(get)、置值于此()
……我突然觉得绝句的『直接值代理』有很大问题了,我不知道它是为了什么,根本不应该让程序员能够做出这种定义。
代为取值(getValue)、代为置值(setValue)

语言结构方面,术语统一为:
常量(literal)、言(expression)、句(statement)、体(block)、构(syntax structures)、书(file)

然后继承方面,顶部类型最好还是『分配』而不是值(即便这样有点『结构化编程』式了……)。

包『绝句』为
开放的物『分配』为
【内建】、待例、算符的事 问全等(另:分配)
类『可度』为
量 大小:计数
扩物『可度』为
记法「之为」的量 之为空 “……”
类『可度长』为
量 长度:计数

本来我打算让 none 变成「存零」的,可是那样 all 就不好命名了,只好引入记法「皆」。

未来绝句标准化到一定程度后我会开始考虑如何将他实现,以何种单位编译、要翻译到什么语言。

rust 在还没有编译器的时候,它的第一个编译器被起名为 rustboot
虽然绝句还不能怎么样呢(大概可能只暂时会做符号解析的工作)
我觉得,第一个只能输出Kotlin源代码的翻译器就叫『绝句 序』吧……
duangsuse::Echo
https://www.yinwang.org/blog-cn/2019/12/26/success
我从很早的时候就藐视所有试图给我打分的人。我从来没有觉得竞赛的主办者有任何资格来评价我,所以从大学开始我就没参加过任何竞赛:ACM,IOI…… 现在一看到这种东西,看看他们的主办者,出题人和裁判们是什么水平,都觉得可笑。当然我就更加不会在乎任何人说我是否“成功”。

不支持,人只有追求更好和自己不在乎的事情,有舍有得而已。这么说太绝对,何况你怎么能武断他们技术不怎么样。

淫王也是可怜,估计他经常被一些清华的校友嘲讽什么的,还好我估计本科都上不了,不担心被别人唾弃。
duangsuse::Echo pinned «🤔duangsuse 昨天晚上想到了一些话,愿意分享给大家。 #statement duangsuse(虽然一点也不好)是如何编程的呢? 他编程,是一个从整到零,再从零到整的过程。 首先是把一个相对比较大的目标,拆分成许多能够比较简单实现的小目标。 比如,把一个操作纷繁复杂的类(class),抽提出实现了很多接口的类。 接着是和自己争论实现的难点和复杂性,继续重新拆分和重新组织继承、数据依赖这样的关联,偶尔还会为一些经常联系在一起的东西(比如 Database, Controller) 起一些首字母简写,记住。…»
duangsuse::Echo
我吃饭回家路上考虑了一下 首先为了能够实现 函数,〖x0〗x0。 函数,〖x0〗 x0 这种逗号表示法的形式,这个样子的逗号表示法类似: 逗号块(逗号修饰, 体)…… 同时,我也终于决定抛弃了逗号表示法的 {} 替换: 若p { op0() } 否则 { op1() } “不允许。” 毕竟绝句不需要像 Haskell 那样 \case ox (Some x) -> 切换布局块和非布局块版本的语法,逗号表示法「,、。」是比较简单的。 现在这个开闭符号是『reserved』了。 然后,绝句也可以利…
本来不该就这么快结束的,可我觉得思路和细节已经基本在我上面写的例子里显示出来了(比如量『a』=1;变文『s』这种不带空格的类词法解析定义),所以我觉得还是继续写我的 e2im-2、Binarie、ParserKt 吧……


嗯……其实不对,我还有许多设计笔记没有发的,而且最重要的中缀操作符、优先级,我都没任何定义。
下次吧,毕竟一时半会也实现不了。