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
#recommend #tools 合并翻译软件吗
Forwarded from 螺莉莉的黑板报
感觉 OmegaT 挺好用的……
https://github.com/CASC-Lang/CASC
我会一如往常在频道里进行项目结构分析,然后用与 C# 相对的 Java (竟然不是 Kotlin... )进行一些并行的重写工作。
之所以用 #Java 写这样富于技巧的 #CE 编译器 程序,是因为我想常常新口味了…… 一些原来 Kotlin 里有的我也用 TypeScript 重写过

原项目是一个“能编译繁简体中文、甚至英语”的编译器,目标是对简体程序员可用。
ChAoS_UnItY (Chaos Unity) 开发,由 C# minisk-compiler.net 起意,后者是一个通俗的基础教程示范,也囊括对 IDE 等语言工具 暴露 parser 、 type checker 等“更远的”工作的示范。 #recommended

程式碼範例
一加二十一是二十二 == True
(1 + 9 - 7) 是 (一 加 九 減 七)
1 + 九 減 7

这个没啥,相关知识: 算符链 InfixPattern/«Lua设计与实现» 相关章节; 中文数值 NumUnit/han() #learn

https://github.com/CASC-Lang/CASC/releases/tag/v0.0.1 看了以后我 🤔了很久,发现连 () 都是“运算符”而且还是 "TP"(tech. preview) 后我头疼了(显然我必须改掉这些设计)
而且它的文档表达的 OUA(Operator Unacceptable, 不接受数学形式) 让我也晕了一下

build 没什么好说的, azure CI + dotnet SDK .NET 5.0, publish build artifacts, NUnit tests
其 build.cmd 就是 dotnet build src/+test-proj/

那么看下关键点——词法、语法、计算与类型转换、作用域和函数调用。

Lexer.cs: Whitespace char.IsWhiteSpace (为 " \t\n\r" 优化), Identifier/Keyword char.IsLetter,
整体是 _position, _kind:SyntaxKind 实现的,有趣的是 identifier text 是靠算 span 再 slice 取的,本身倾向流式 Peek(offset), Current, LookAhead=Peek(1), '\u0000' EOF 但不完全
第一个 readonly List<char> 无使用
写的是: 加 減 乘 除 點 開 閉 正 負 且 或 反(非,!) 是 不(是,!=) 赋(=)
开闭括号的我感觉有点奇怪。

加正+減負-
乘*除/
(){}
且 &&
或 ||
反!
!= 不是
是==
賦=
命名都像 SyntaxKind.BangEqualsToken(!=) .StarToken(*) .SlashToken(/) 这样
其中 ==, &&, ||, != 的需消歧义,但没有 lookahead 而是以状态机区分、「不是」「反」「赋」 都是别名

0123456789零一二三四五六七八九
壹貳參肆伍陆柒捌玖拾十百千萬億

靠外置 ReadNumberToken(); 读数
另外都做了 ReportBadCharacter 的错误记录工作
以上皆返回 SyntaxToken ,试用 SyntaxFacts.GetText 拿内文,如果则用当前 span 取 substring 。

Parser.cs:
CompilationUnit, Stmt, BlockStmt, VariableDeclaration, ExprStmt, VariableDeclaration, Expr, BlockStmt, Stmt, ExprStmt, Expr, Expr, AssignmentExpr, AssignmentExpr, AssignmentExpr, BinaryExpr, BinaryExpr, BinaryExpr, PrimaryExpr, BinaryExpr, PrimaryExpr, ParenthesizedExpr, BooleanExpr, NumberExpr, NameExpr, NumberExpr, ParenthesizedExpr, Expr, BooleanExpr, NameExpr

其中带 Binding(他没解释但估计是作用域上下文,但我很好奇为什么要给每个 Node 键一个 BoundedXXX) 支持的:
BlockStatement, ExpressionStatement, VariableDeclaration
LiteralExpression, VariableExpression, AssignmentExpression, UnaryExpression, BinaryExpression

感觉挺无聊的,还是开始重写吧 🤐
不对,把 Text/Stream, Binding, ChineseParser.cs 上的痛点先说下才能继续
架构的问题太大了,尤其是 Original/WithBinding AST, 这个绝对要想办法削掉

其实 Java 的基础面向对象结构绝对不比 C#,我不用 Lombok 但会争取 Kotlin 移植可能,作为休闲弄几天吧。
...我觉得作者是真的没有这种 Do not Repeat Yourself 的意识,老实说, getZHText(TokenKind) 就得 Iterable<String> 的用处我觉得蛮奇怪的——这不是 parser 需要识别,基本只 toString() 用,那么为什么需要“全部”可能的设计关键字呢?目前我只在 Unit Test 里找到了用例,看来作者是不重视程序简洁性的,比较严重(之前协作 Mivik/kamet 的时候怎么可能看到这种大 switch-case 代码,何况是在 parse 完的后期处理里)。
Forwarded from 可爱 鸭鸭
Qv2ray 主项目 Archive 一小时

以纪念所有参与开源项目开发但未获尊重的开发者
This media is not supported in your browser
VIEW IN TELEGRAM
老实说这个代码吧,作者甚至可以说是在故意往冗长含糊去写…… tmp,tmpNum,result ,+= *= if (>=) 真的是把我绕晕了,明明那么简单的思想

仿佛在看一大堆 ret, obj, obj1, i, j, k 命名的这种代码,真的是相当「符合规范」呢,阅读起来真的过于草生,分不清是这个tmp还是那个tmp....
https://github.com/CASC-Lang?type=source
总之,这个还是比较搞大的。感觉作者是一个相当实践派的程序员,甚至有精力维护一个 Rust 版(C++ 版目前只有 CMakeLists) 以及一个(貌似是自动翻译的)TypeScript 版,生产能力很强,但代码质量和抽象/模拟能力必须学习一个,也该注意下不要把 build/ .vscode/ 提交上 VCS 什么的……
#v2ex #dev #net #tech “先理解字节流..... 比如 Java 的各种 Stream , 然后类比就懂了” “关键是理解 TCP 的流的概念吧~ 这个流是一个没头没尾的东西, 所以需要长度, 标记符之类的来定义数据的边界
个人的理解大致是这样吧.” “由于通信应用的复杂性,以及用户需求进一步提出更高的要求,当他们尝试多条数据放在一个 UDP 数据包里进行发送时,就会出现所谓的 [黏包] 问题。” 妈耶,整这么多术语,直接用 API 定义不好吗 😵
羽毛的小白板
https://www.v2ex.com/t/747735#reply28
“TCP 本来是一个流传输协议(数据不分块,保证有序,也就是只保证多次 recv 的数据依顺序拼起来保持原样),偏要把它当成一个消息传输协议(数据分块,保证有序,保证一次 send 对应一次 recv )来用。
不巧的是在环回网络以及短途网络里调试时,这种误用并不会出问题。”

这个回答挺好的,我目前的理解就是,他们要做 WebSocket 这样的 event listen 式协议,但却手动维护了一个 buffer ,要“粘起来”发 TCP ,然后收方再拆了去 dispatch 。
嗯... 说到 socket ,数据的确没 chunked 而只是 bytestream ,这点我对 C API 引入的 buffers 理解错了,我之前隐隐觉得对方肯定收完 buffer 的内容…… 今后就有经验了
This media is not supported in your browser
VIEW IN TELEGRAM
看完感觉懵懵的,动苏是 Kotlin 原住民,写过二进制字节流、字符流的框架,习惯 yield generator 和 java.util.Stream 的封装模式及利用,我明白,但根本就不看 static size 的那些东西和 buffers
表示很困惑什么叫「粘包」「拆包」,难道这两个词可以越过 Protobuf, BSON 这样的 data model 来谈吗?数据和其 representation, serialization 本身关系就不大的,为什么要专门写程序去拼包啊
#Python #code 妈耶,看来还是 lambda op_append: 的方法好,虽然带副作用。 总结:新写法省了 gavSplitfrom itertools import chain ,多了 3*lambda ,优雅性持平。
#Java #Learn #typing 还是写了……
Forwarded from dnaugsuz
型变是 <T> 参数上面的一种性质,其定义为:
协变, P<T1>: P<T>
逆变, P<T>: P<T1>
不变, P<T>, P<T1> 无子类型关系。
(其中 T1: Tclass P<T> )

子类型即若有 T1: T ,或言 (T)(T1)obj 有效(checks),则 op((T)x)op((T1)x) 照样可用。
型变性的意义主要是,定义出符合子类型限制的类型约束,比如 PECS(producer-extends; consumer-super) 原则。
interface Producer<R> { R get(); }
interface Consumer<T> { void accept(T value); }

假设你的函数需要接受上一为参数 er,它必须这样定义才能尽可能兼容「真正能兼容的所有」 er
void <R> R recv(Producer<? extends R> er);
void <T> void send(Consumer<? super T> er, T value);

参数列表多几项、少几项都是一样的,只是要满足必须的类型约束而已。

实践上,就是每个 Producer/Consumer/Function<T, R> 的是用处都必须以 Function<?super T, ?extends R> 这样的方法去定义参数的类型约束,不然它会破坏子类型的类型安全、或使本该有效的程序报类型检查错误,但让程序员去写这些 extends/super 的,实际上这是在暴露与业务逻辑不相干的细节。
Kotlin 有 in/out 的声明处型变,也就是不用 Java 的 "Type wildcard" 了,是符合理论优雅性和实践便利性的:
interface Function<in T, out R> { fun apply(value: T): R }
在类型约束(如函参)处, Function<Int, Any> 自动兼容其 Function<Number, Unit/*或 Nothing? = java.lang.Void, 仅 null*/>

类型(限)/下界即是指 Void...Object (子类型的)extends/super 的约束,Void 是底,没有实例的类型;Object 是顶,所有类型的父类型,这个东西没有区间只能加限制条件。
🖕这个玩意非常易混,涉及一些中英文的文化差异和数学抽象概念的移植,建议不要使用
另外,泛型(generics, aka. parameterized polymorphism 参数化多态) 不是范型、上下界(U/Low bound) 不是上下届 ,千万别拼错
Forwarded from dnaugsuz
我字多是因为我明白,想的多一点可以让代码简洁好看点
拿一小篇文字换所有项目里几十文件的质量,值。
Forwarded from dnaugsuz
有的代码写一行省十行,有的代码所遵循的模式,写了第一行后维护和重读重理解的麻烦不断;即便功能相同,不同的人写出来质量是完全不一样的。
所以我一贯很乐意学习编程之道,可能你觉得我字多些,对真的要学这些内容的人来说,这是我第五次讲相同话题,已经很省字数了。

便宜的就是最贵的,不想付出但想多得回报,很难不为这种心态再付出更大的代价。浪费与节省,大概是这个道理。