/tmp/duangsuse.sock
23 subscribers
303 photos
3 videos
92 files
337 links
从 duangsuse::Echo (@dsuse) 跟进出来的分支,将在作者恢复原帐号访问的时候合并删除。
Download Telegram
果然还是看的人(*96)多,看完的人少,只有 18 个... 算算只有大概 19% 的人读完了,碎片化阅读,这就是一个实例吧。
Forwarded from Telegraph
Total views for telegra.ph/对-drakeet-的一些话内联-07-03: 18

To get stats for a particular day, month or year, send me a message in the format HH,MM/DD/YYYY, MM/DD/YYYY, MM/YYYY or YYYY.
Forwarded from Deleted Account
看来 Telegram 上的读书人综合出现概率还是小啊(怎么有 90 次阅读,可是读到我因为文章太长不得不另建的内联的人却只有 19% 左右...
都是连看书 看文章都嫌浪费时间 了 么 🙈

看了上面这篇文章,我觉得作者陈皓的格局果然还是很大啊,怎么都是赶不上的呢。
Forwarded from Deleted Account
首先,在完成我打算的一门以小体积和 REPL 为特色的 JVM 脚本语言之前,我得先给自己入下门
(一般来说,脚本语言都是由一条一条作为基本执行单元的『语句』构成的,他们总是描述动作而非数据、存储、操作什么的,而不是可能不能执行的定义,比如『函数定义、变量定义』)

之前的入门也有,可是不顶用。(知识理解发生了变化)
我也想写一个 LLVM 的 native 编译器练手,可是应该是之后的事情(先做简单一点的)

当然,理论基础也是得有的,我最近会讲 infix 操作符的递归下降(recursive descent)解析、左递归和右递归、二元优先级

我现在打算设计的这门语言叫做 ec, 名字是从 GNU bc 和 GNU dc 抄来的,它的目标是成为一个(不要求性能)的可编程计算器
以后我也可能添加 JIT 支持,不过不是现在的事情(我要先准备一个 JVM binary stream 框架才可以写类代码的读写器)

首先它继承我 BinOps 计算器的所有操作,不过有一些额外的特性:

0. 它使用基于隐式状态机的解析组合子编写,代码很优雅
1. 它支持二元操作符优先级 infixl 和 infixr
2. 它支持函数定义,并且(可能)支持 pattern matching 和 tail recursion
3. Unicode 语法,可以写的很像数学
5. 支持和 Java 一定程度的互操作(interop),它支持调用静态方法

EC 的全名是 Electronic Calculator,它是一门多范式(multi-paradigm) 编程语言,主打函数式编程和过程式编程
它是基于 lambda calculus 的,所以非常简单,只有
x y z w a b c n 变量(只有两种变量,就是函数的参数和局部变量,函数参数是不可重新赋值的,全局作用域就是『全局函数』的作用域),这些名字默认是数值变量,ec 支持数值类型自动转换提升(和转换)

它有五种基本类型:Any, Num, Bool, Str, List<A>,只能在函数参数和返回值里指定,并且支持这样的自动推导
函数类型是 (T, T1, T2, ...) -> R, 当然函数类型也是类型,所以可以写接受函数或者返回函数的函数

类型参数支持子类型的形变性((in T) -> out R
不过还不开放用户数据的定义,所以也没有手动的类型参数型变

其中 Any 是 Num / Bool / Str 的父类型,其他类型不存在子类型(subtyping)关系

+ x* y* z* w* k*; a b c; n 默认为 Num 变量;这里 * 必须是一个或多个数字 0-9
+ p.{1} q.{1} 默认为 Bool 变量,这里 .{1} 照样得是数字 [0-9]
如果一个函数的名字类似 is* has*, 返回值默认为 Bool(当然变量也是一样...
+ name / str* 默认为 Str 变量
+ *s 的默认为 List<* 的自动推导>
+ 其他情况默认为 Any
+ List<A> 的 A 是一种类型,List 的 headtail 是惰性计算的

可以用 let ... in ...variable 控制局部变量的作用域

并且支持自定义转换器 implicit LongToInteger() = ...explicit, as operator
(\x -> x) 匿名函数(abstraction)
f(x) = x 具名函数(function operator)
(f 1) 函数应用(application)

它的流程控制分支使用分支函数实现,也可以 if elsematch,循环可以使用
尾递归(自动优化)和 for x in iterwhile p

没有惰性求值特性,因为底层操作使用 JVM 的 Object 引用实现,所有操作都是传值(pass-by-value & copy)调用

EC 使用 Lexical scoping,这意味着它存在闭包,EC 的闭包使用了类似 Lua 的 FuncState / UpValue 模型(不要时 close,每个函数一个 state),而不是 Ruby 1.9 的 Clone-stack 和简易 Scheme 实现的 dup-environment

Java interop 的支持使用 import 语句

import org.duangsuse.ec.Plugin.func
import org.duangsuse.ec.Plugin (@EcExports 标记的类型)

import org.duangsuse.ec
import Plugin

import Plugin hiding (func)
import Plugin.func as fun

关于 pattern matching 的函数定义,我想过了
不过尾递归优化的分析还得做

目前还在设计,举一点例子:

let
id x = x
in id 1


put "Hello, world"

assert 1+1 == 2
assert 1+1 /= 3

id = \x -> x

abs(n >0) = n
abs(n <=0) = neg n

fib : (Num) -> Num
fib(n) = fib(n-1) + fib(n-2)
fib(1) = 1
fib(2) = 2

fold(f, v, []) = v
fold(f, v, [x :: xs]) = fold(f, f(v, x), xs)
product(xs) = fold: <*> 1 xs
factorial(n) = product: [1..n]

count [_ :: xs] = 1 + count: xs
Deleted Account
首先,在完成我打算的一门以小体积和 REPL 为特色的 JVM 脚本语言之前,我得先给自己入下门 (一般来说,脚本语言都是由一条一条作为基本执行单元的『语句』构成的,他们总是描述动作而非数据、存储、操作什么的,而不是可能不能执行的定义,比如『函数定义、变量定义』) 之前的入门也有,可是不顶用。(知识理解发生了变化) 我也想写一个 LLVM 的 native 编译器练手,可是应该是之后的事情(先做简单一点的) 当然,理论基础也是得有的,我最近会讲 infix 操作符的递归下降(recursive des…
这里先提一下 infix operator 扫描的一些事情:

1. Infix chain 是什么?

1 + 1 * 9 这种代码写多了
可是不知道怎么解析

a.toString().hashCode() 也写过
可是也不知道怎么解析

Int -> String -> Int 实际上是 Int -> (String -> Int)
不知道如何解析成 data Type = ... | Fn Type Type 的形式
(Fn Type "Int" (Fn (Type "String") (Type "Int")))

Infix 是什么呢?
你看上面的东西,是不是都遵循这种模式:

chainr = item sep chainr

(啊盲目 right recursive

chainl = chainl sep item

(胡乱 left recursive

其实我是想说,,,,
chain = item (sep item)+

但是,以上两者确实是不错的思路,我们考虑两种递归解析子程序

Expr scanChain(Item left, int precedence_l);
它解析一个 (a ·) a · 的模式
Expr scanChain(Item left);
它解析一个 a [(·) a ·] 的模式(好像没有区别啊... 写错了

考虑到为了决定操作符的优先级(可以分左右,这样就同时实现了 left 递归结合和 right 递归结合),
前者需要 lookahead 一个 *(rhs) 一个 rhs op,第一层递归需要给出最小的优先级(实现一定 right assoc)
后者则为了理论上的好看得 lookahead 三次,然后还不能直接归纳到 binary operation 的模式,必须得遗忘一个用于决策递归的 item...

啊总之 ::Echo 频道之前讲过(搜索 chainl),也不是非常困难的问题,就是递归下去、判断 item 子解析器是否成功,一直 解析失败,回溯回来就可以了。目标就是关于二元运算建立递归的数据结构

infixl 和 infixr 属于结合性,Int -> (String -> Int) 是 right(infixr)
1 + 2 + 3 (+) 是 left, (a.toString()).hashCode() 也是 Left.

然后上面的的确是搞错了,只能
(lhs lop) op rhs
然后做决定,如果是 left-to-right 扫描 a · b · c
不能直接在第一个 · 决定(是这决定一层返回最终结果还是把 lhs 规约了传下去)

这一层返回就是(read a, judge · < ·1 , chainr)
a · (b ·1 c)
lhs 规约再递归下去就是(read a, judge · > ·1, chainl)
(a · b) ·1 c

的话只能子解析器再去返回某种容器来决定是 C a 还是 a 类型了
是不好的,只能在当前的层决定
https://coolshell.cn/articles/17524.html
#FP 考虑一下 Lambda 演算的 Y Combinator:

λf. (λx. f (x x)) (λx. f (x x)

也有人说:
λf. (λx. f (x x))^2

可是我觉得也可以命这样的名字(alpha-conversation 项变换)

λf. (λc. f (c c)) (λc. f (c c))

其实,乍一看 Y 组合子很难理解,实际上它的确是很烧脑,尤其是从『f 的结果是怎么传递回去的?』这里分析
不过本身从一个程序推进,也不是那么变态难了:

(λc. (c c)) (λc. (c c)) 大家都可以试着推导一下,这个程序会”孜孜不倦“地运行(致敬 The Little Schemer

不过它不是很好理解(虽然大家都能通过对递归程序只考虑本层的基本直觉感知到它的确是无限地”展开“自己,无法正常回溯)

(λf. (f f)) 这个例子蛮好理解的,它利用 variable binding 把一个匿名函数传递给它本身,但是这个匿名函数却不能保证像 Y 组合子一样持续展开下去。
于是我们就想,能不能做到『无尽展开』呢?
其实这不难做到,回顾刚才我们举的 (λf. (f f)), 它是什么?它接受一个 f,结果为 (f f) 也即 『f 应用(apply) 给自己』这个 application 的结果

注意一点:如果把它自己传递给自己会怎么样呢?
(define never-returned
(λc. (c c)) (λc. (c c)))
你永远别想拿到 never-returned 的值,因为那个傻函数子程序会不断把自己传给自己... 不要忘了它的任务实际上就是把某个函数 f 传递给它自己而已
这样可以做到蛮正常的匿名函数递归,也可以做到 Y combinator
(
(lambda (f) (f f))

(lambda (c a b)
(if (= a 0) (b)
(c (sub1 a) (add1 b))
)

当然,这个是理论上的,我没有考虑 arity mismatch 的问题...

(define sum
((lambda (f) (f (f f)))
(lambda (c) (lambda(a b)
(if (= a 0) b
(c (sub1 a) (add1 b)))))))))
骗你们的,只能 apply-with-args,curry 是无效的,因为 curry 是确定一个参数,不能重写的参数,何况上值(upvalue) c 根本不是『自己』
不过好像还是无解... 虽然我之前确定过的,不能只指定一个 c,然后后面的让 (c x y) 定...
不过还是可以用 Y 组合子:
> (define Y (lambda (f)
((lambda (c) f (c c))
(lambda (c) f (c c)))))

答案是它会不断地继续把 f 传递给自己,然后妄图返回那个永远不可能存在的结果...
这就是 Y combinator .

Y combinator 是组合子逻辑(combinatory logics)不动点组合子里最著名的一个,由它也可以得出 lambda 演算支持循环的推论,从而可以证明 Lambda calculus 通用图灵机(universal turing machine)模型等价

然后 就 跑路了(因为我也不会...
#acg #life #japan 🏕愿伤者平安...
Forwarded from AIM扩散力场 (零件 #PrayForKyoani)
在当地时间本日的10时35分,京都动画(本社宇治市)的第1工作室发生火灾,据消防局称,建筑物因火灾受损较为严重,并有多人受伤。
当地居民在发现1楼传来爆炸声、而后有烟雾蔓延出来便报了警。
京都府警察本部在现场发现了有一名男性向现场泼下类似汽油一样的液体,据京都府警察搜查科1课的调查,该男性嫌疑人40多岁,同时也负伤被送往了医院,在调查中对警方表示是他本人放了火。
这次火灾可能导致京都动画大量纸质原稿损毁,排期制作的动画也可能受到影响。
京都动画曾制作过很多知名作品:《凉宫春日的忧郁》、《CLANNAD》、《轻音少女》、《冰菓》、《中二病也要谈恋爱》、《境界的彼方》、《 吹响!上低音号》、《紫罗兰永恒花园》等。
/tmp/duangsuse.sock
https://coolshell.cn/articles/17524.html #FP 考虑一下 Lambda 演算的 Y Combinator: λf. (λx. f (x x)) (λx. f (x x) 也有人说: λf. (λx. f (x x))^2 可是我觉得也可以命这样的名字(alpha-conversation 项变换) λf. (λc. f (c c)) (λc. f (c c)) 其实,乍一看 Y 组合子很难理解,实际上它的确是很烧脑,尤其是从『f 的结果是怎么传递回去的?』这里分析…
关于昨天两个不会的问题,其实还是会的...

(define Y (lambda (f)
(let {[k (lambda [c] (f (c c)) )]} (k k))))

呃... 虽然是不会返回,但是 f 的确是可以被执行

不过我要说的不是这个问题,而是上面的 sum 函数该如何定义
上面的 sum,有一个问题: (lambda [f] (f f)) 很好,它的目标只是把匿名函数的引用递给它自己,但是为了兼容有多参数可重写的递归匿名函数,必须弄很多个

(lambda [f] (f f ()))
(lambda [f] (f f () ()))

... 只是为了给多余的参数提供默认值,这个函数本身它只运行一次而已。
柯里化也是没有办法的,其实我们需要的就是拿到一个『函数本身』的引用 c
可是直接以参数的形式提供 c,它就要求你的函数只能有一个参数(不然 arity mismatch)

于是可以考虑一下使用高阶函数和上值(upvalue),但是那个辅助函数偏偏又只传最外层的引用

于是有了这种办法

[define call-with-self
[lambda (f) (f f)]]
[define sum
(call-with-self
[lambda (self)
[lambda (a b) (if (= a 0) b ((self self) (sub1 a) (add1 b)))]])]

其实这样就是利用高阶函数拿到参数长度安全的自己的引用,不过还不如不用...
等于这个版本的 sum
[
[lambda {f} (f f)]
[lambda {c}
[let {[next [lambda {} (c c)]]}
[lambda (a b) [if (= a 0) b ((next) (sub1 a) (add1 b)) ]]]
]
]

这个 next 必须是惰性求值的,不然也不会停机... 和 Y 组合子还有点关系
之所以会停机,之所以需要惰性求值,就是因为 (next) 代表的 (c c) 就是『递归下去 1 层;回溯本层的结果』这个行为本身,此函数是 Y 组合子的一个应用(虽然我太菜所以不知道怎么重写了

自然,也可以试着让这个函数直接提供 recursive 函数的引用

(lambda {} (lambda (a b) ...))

可是外层函数必然要依赖它的参数提供一个(continuation 的)变量引用,所以不得不使用(递归的)参数了...

之前我晚上想了一会就是想到了这个方法(

Scheme 系的程序员都是在支持程序分析变换、程序综合的情况下还会各种封装逻辑的,可惜我不是(...

不过一般还是元编程 call-with-values(查文档 请
盲目地批判,那些消息我们都没有听到呢,何况这次是比较意外的情况 #life #statement
按照贵频道的说法,圣母院起火那段时间我们没有首先去考虑国内的可怜儿童和破事情,跑去顺带表示一下同情,也是对祖国不肖了。

这种话,不可能和受害的是『日本』的『动漫』工作室这两个关键词无关吧,如果是印度的、英国的、被袭击的是真理部、普通的公园广场什么的,又会如何作想呢?
到底还是和萌豚们过不去吧... 可是我们除了持瓜围观还能做什么,不就是没人听得见的批判,
还不如乖乖做好自己的事情然后静观其变算了....
Forwarded from 人海拾贝FlipRadio
观京都动画事件有感,这当然是件坏事,也是社会变糟的表征。不过,新疆的事情大家不太关心,香港的事情大家不太关心,京都动画出这个事情,大家受不了了,纷纷如丧考妣,这我不太能接受。我不是强迫所有人都必须关心我关心的事情,只是不管从哪个角度来看,新疆和香港的事情,都离大家的真实生活近得多得多,严重的多得多,邪恶的多得多。大家的注意力和关注点真是......唉,明天又有大批公众号出来吃这个人血馒头。真是坏事一出,坏事就一件接一件。这真是个大问题,大家对一个动画工作室的关心和心疼远大过几百万和自己关系更近的人,这是一种自由,还是一种什么呢?
除了泄愤就是做好自己的事情,可以表达一下自己的观点,但知道自己现在这方面也很废做不了什么
所以就做好该做的事情,少去管一些闲事,如果找得到事情做的话
Forwarded from 人海拾贝FlipRadio
我现在很想知道,除了打字泄愤,我们能做些什么?已经有很多年轻人做了那么多那么多,我们能做的还是打字泄愤。我想该怪我们自己
人海拾贝FlipRadio
观京都动画事件有感,这当然是件坏事,也是社会变糟的表征。不过,新疆的事情大家不太关心,香港的事情大家不太关心,京都动画出这个事情,大家受不了了,纷纷如丧考妣,这我不太能接受。我不是强迫所有人都必须关心我关心的事情,只是不管从哪个角度来看,新疆和香港的事情,都离大家的真实生活近得多得多,严重的多得多,邪恶的多得多。大家的注意力和关注点真是......唉,明天又有大批公众号出来吃这个人血馒头。真是坏事一出,坏事就一件接一件。这真是个大问题,大家对一个动画工作室的关心和心疼远大过几百万和自己关系更近的人,这是一种自由,还是一种什么呢?
让大家热爱八卦,八卦并不一定是明星的八卦,还可以是你身边的人,
比如,公司的同事,自己的同学,职场见闻,社会热点,争议话题,……

这些东西总有一些东西会让人心态有很多微妙的变化,
甚至花大量的时间去搜索和阅读大量的观点,以及花大量时间与人辩论争论,这个过程会让人上瘾,让人欲罢不能,

然而这些事却和自己没有半毛钱关系。
你要做的事就是转发其中一些SB或是很极端的观点,造成大家的一睦讨论后,就早早离场……
[origin:coolshell::如何超过大多数人]
#task 马上要做的事情:

0. 用 6 种平台编写排序的 PoC (C++, C++/Qt, Java/Android, JavaScript/Web, Java/Servlet/MongoDB, Kotlin/SpringBoot)
1. Java 8 的 @in @out type parameter annotation processor
2. 编写 XML 解析器,讲解基于状态机模型的分词/解析-style parser 结构
太棒了,总算可以听坤坤的《鸡 🐔 你太美》了!大爱坤坤!