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

技术相干订阅~
另外有 throws 闲杂频道 @dsuset
转载频道 @dsusep
极小可能会有批评zf的消息 如有不适可退出
suse小站(面向运气编程): https://WOJS.org/#/
Download Telegram
先试用 lex / re2c 和 Yacc
https://github.com/kztao/yscheme/blob/master/compiler.ss

这个从 Chez Scheme 作者 Kent Dybvig 的课堂上带来开源的 Scheme 编译器,可以把 R6RS 的子集的代码转换为 AT Syntax X86(_64) 汇编代码,不过需要一个额外的运行环境才能执行

Only the main compiler code is here. I don't have copyright of the rest of the code (test framework, runtime system etc)

直到现在都没有人公开编写此编译器输出需要的链接库,这也就是个废物了?因为可能大家都看不懂递归、CPS、Combinator... (反正还有一大堆真·函数式的理论没几个人看的)

在他删除这个 repo 之后,只有寥寥两个 fork 继续存在,而且没有人动过那些代码,真是应了某些科幻小说里“他们无法解开我加密的代码”这句话了,Scheme 是多像数学,看起来多么美观自然但是多么难理解,不熟悉者对着一大堆括号一头雾水,满眼 define lambda match 不知何意,大概 Haskell 都比这更像过程式语言不是吗...

最多的分析大概就是他吹出去的那 40 行代码了,一个 CPS 编译器

A notable thing of this compiler is its use of high-order evaluation contexts, an advanced technique used in CPS transformers, which resulted sometimes in much simpler and shorter code.


那么多人崇拜王垠,觉得他很酷,很厉害,可惜这些觉得他很厉害的程序员里,有几个知道他到底是做什么的呢?

所谓编译原理、编译器技术,可能以他为榜样的那部分人里,并没有人真正对这些感兴趣,只是作为一个遥不可及的偶像罢了。

可是,现在的计算机工程需要一种像神一样的存在吗?


如果你希望你的DSL跑的像射命丸文一样快,你可以把这些特性去掉,然后你就能在你自己的编译器里做优化(inline,JIT,fusion,tco,lazy,unwrap lambda)了。

然后你又会发现,这些其实很简单的东西知乎上的程序员似乎觉得这很高大上诶!那些脑子转不过来的程序员连 Parser Combinator 都搞不懂,用 JS 写出 JS 的 Parser、写出 C 语言的 Tokenizer 和 Grammar Analyzer 就能称霸一方,你一去他们岂不是集体跪拜?


真香... 🙈
duangsuse::Echo
https://github.com/kztao/yscheme/blob/master/compiler.ss 这个从 Chez Scheme 作者 Kent Dybvig 的课堂上带来开源的 Scheme 编译器,可以把 R6RS 的子集的代码转换为 AT Syntax X86(_64) 汇编代码,不过需要一个额外的运行环境才能执行 Only the main compiler code is here. I don't have copyright of the rest of the code…
现在咱正在测试 play compiler.ss 🐱
终于知道 define-syntax 是什么意思了...

注释掉没有的代码后,

;(load "match.ss")
;(load "helpers.ss")
;(load "driver.ss")
;(load "fmts.pretty")
;(load "wrapper.ss")

Chez Scheme 说

[DuangSUSE@duangsuse]~/Projects% scheme compiler.ss
Chez Scheme Version 9.5
Copyright 1984-2017 Cisco Systems, Inc.

Exception: misplaced aux keyword (unquote x) at line 234, char 8 of compiler.ss

发现有这些代码

(define mref?
(lambda (x)
(match x
[(mref ,base ,off) #t]
[,x #f]))) ; misplaced aux keyword (unquote x) at line 234

然后,参照手册 https://www.scheme.com/tspl4/examples.html

(display ,x) ; misplaced aux keyword (unquote x)

(define-syntax unquote
(lambda (x) 1)

(display ,s) ; => 1

(define-syntax unquote
(syntax-rules ()
[(_ e) (display e)]))

,display
#<procedure display>

好玩,可惜 ApkBundler Scheme 不打算使用这样的宏系统

因为 compiler.ss 使用了太多自定义语法 想白白测试来很困难,所以暂时不继续测试了
#learn #functional #scheme #cs #pl

https://www.cnblogs.com/JacZhu/p/9729587.html 阅读者 duangsuse 做的总结 以下

-Infinity: 以下可能不是标准的 C# 代码,如果不容易理解全换乘伪代码
0. 笔者一直以为 LINQ 是专门用来对不同数据源进行查询的工具
1. C# 3.0 的 LINQ 可以做 Parser Combinator
2. 我也好需要 Parser Combinator 编写技能啊

3. 任何实现了 SelectSelectMany 等方法的类型,都是支持类似于 from x in y select x.z 这样的 LINQ 语法的
4. 如果我们为 Task 类型实现了上面提到的两个方法,那么我们就可以不借助 async/await 来对 Task 进行操作

taskA = Task.FromResult(12)
taskB = Task.FromResult(12)

resultA = await taskA
resultB = await taskB

result = resultA + resultB // 12 + 12

resultLINQ =
from a in taskA // a = await taskA
from b in taskB // b = await taskB
select a + b // 简不简洁?

5. 我们来为 Task 类型添加 LINQ 语法

首先我们要定义一个 Select 拓展方法,用来实现通过一个 Func<TValue, TResult> Task<TValue> 转换成 Task<TResult> 的功能。

static async Task<TR>
Select<TV,TR>
(this Task<TV> task, Func<TV, TR> selector)
{
var value = await task; // 取出 task 中的值
return selector(value); // 使用 selector 对取出的值进行变换
}

static async Task<TaskResultType>
Select<TaskSelf, TaskResultType>
(Task<TaskSelf> self, Function<TaskSelf, TaskResultType> selector)
{ return selector(await self) }

taskA = Task.FromResult(12)
result = from a in taskA select a * a;
// taskA.Select(a => (a * a))
// `a => a * a' 就是 Select 中 selector /* (a => a * a) */ (await self) 被调用的那个 selector

6. 然后是 SelectMany 函数

class Task
async SelectMany<ThisType, SelectorType, ResultType>
(self, selector: Function<ThisType, Task<SelectorType>>,
projector: Function<ThisType, SelectorType, ResultType>): Task<ResultType>

{
var value = await self;
return projector(value, await selector(value));
}

7. 这个 SelectMany 实现的功能就是,通过一个 Func<TValue, Task<TResult>>Task<TValue> 转换成 Task<TResult>
8. 如果看不懂上面的解释的话,不要灰心,因为我也看不懂

9. taskA.SelectMany(a => taskB, (a, b) => (a * b))
10. from a in taskA from b in taskB select a * b
11. 后面还有一点我也看不懂,只看懂了一句话,就是 "SelectMany 可以被看作为把两层 Task 转换成单层 Task"

12. 可以看到,当出现了两个 Task 之后,LINQ 就会使用 SelectMany 来代替 Select
13. 想为什么 LINQ 不像之前那样,用两个 Select 分别处理两个 Task
14. 因为我们所写的第二个 Select 其实就是 SelectMany,结果比 LINQ 还多调用了两次 Select

15. 后面的看不懂

细心的你可能已经发现了,不管是 LINQ to Task 还是 LINQ to Result,我们都使用了某种特殊的类型(如:Task,Result)对值进行了包装,然后编写了特定的拓展方法 —— SelectMany,为这种类型定义了一个重要的基本操作。在函数式编程的里面,我们把这种特殊的类型统称为“Monad”,所谓“Monad”,不过是自函子范畴上的半幺群而已
int 类型的全部实例构成了一个集合(范畴),如果我们为其定义了一些函数,而且它们之间的复合运算满足结合律的话,我们就可以把这种函数叫做 int 类型范畴上的“态射”,态射讲的是范畴内部元素间的映射关系

// 将函数 g 与 f 复合,(g ∘ f)(x) = g(f(x))
Func<X, Z> Compose<X, Y, Z>(Func<Y, Z> g, Func<X, Y> f) => (X x) => g(f(x));

Func<int, int> f = (int x) => x * 2;

最后:学不下去了... 停车... 我要停车...
This media is not supported in your browser
VIEW IN TELEGRAM
#PL #dev #tech https://www.gnu.org/software/guile/

真是大开眼界 http://www.r6rs.org/implementations.html

1. GDB 好看的交互是基于 R6RS 实现 Guile
2. GNU 家的项目居然能把前端做得这麽好,而且在国内还是不知名语言

;;; Hello HTTP server
(use-modules (web server))

(define (my-handler request request-body)
(values '((content-type . (text/plain)))
"Hello World!"))

(run-server my-handler)

Guile 在国内可真是可谓无人知晓... RubyGems 根本没有 果然凉啊
GitHub 上语言实现绑定只有一两个,倒是库和使用它的应用有一些
推荐几个 R6RS 实现

https://www.biwascheme.org/ 基于 JavaScript 的字节码解释器
http://ikarus-scheme.org/ 原生代码编译
http://www.larcenists.org/download.html 同,区别在于只面向(x86, x64)/ARMv7l
(一件好玩的事情是, Chez Scheme 都不支持 R7RS 特性, Larceny 则支持, 所以我这里 Chez 的环境还居然无法编译 Larceny...
刚才编译了 Larceny(特地首先准备的实现)
感觉编译速度果然还是不如 Chez 快, 但其实已经很快了, GCC 和 Clang(只是前端) 都要花多多少倍的时间
可能 Chez 编译时不是直接生成机器码或者汇编的吧,可以看到 Larceny 的确慢了不少, 至于是不是都是 pass 架构的不清楚

Larceny 至少是 Linux 上不支持 X86_64,所以还得特地去装个 32 位兼容 libc 和头文件才能用... 还依赖 NASM

../larceny-1.3-bin-native-ia32-linux86/larceny

Larceny v1.3 "Grain Alcohol and Rainwater" (Aug 6 2017 01:16:30, precise:Linux:unified)
larceny.heap, built on Sun Aug 6 01:16:56 EDT 2017

(load "setup.sch")
(setup 'scheme: 'larceny 'host: 'linux86 'sassy 'string-rep: 'flat4)

(build-config-files)
(load-compiler)
(build-heap)
(build-runtime)
(build-executable)

; complete Larceny user system including the Twobit compiler
(build-larceny-files)


之后,不知道具体流程上有何差距,Chez 当时自己带了 boot 文件,Larceny 需要用现有的解释器编译自己,不懂这些...
http://sassy.sourceforge.net/

可以作为 Kasm 的参考... 不过看到说是占 Larceny 代码大部分我知道大概... 很难
This media is not supported in your browser
VIEW IN TELEGRAM
其实是我弄错了... 我想要类似 Petit Larceny 这样编译到 C 的,或者说可以脱离专门的运行时的实现
( 但我没有注意到这实际上是不可能的,除非是用 C, D, Fortran, no_std 的 Rust 之类

但挂上运行时其实也可以,因为运行时有 400k 大小

不过还是失望...