/tmp/duangsuse.sock
23 subscribers
303 photos
3 videos
92 files
337 links
从 duangsuse::Echo (@dsuse) 跟进出来的分支,将在作者恢复原帐号访问的时候合并删除。
Download Telegram
Forwarded from 永久封存 | Yuuta 台 | 😷 #Pray4Wuhan (玉米狐狸)
/tmp/duangsuse.sock
#China #Low
#PLT 咳咳,咱来谈谈这个东西的实践的问题。
既然咱说是实践,那干脆就引入一个编程语言吧,我们叫它 MiniScheme。

Scheme 呢…… 不错!我们使用满是括号的 s-expression,这种基础表达方式。
(+ 1 2) ; 3

那么这个语言呢,我们打算用 Kotlin Common 开发(因为也没必要特别地放 JVM 上)
Literate Programming…… 算了,LKT 还没完成,在那之前,还是保持老编程风格好了。

怎么计算?慢慢看,但我们认为,输入代码是 CharIterator,这样支持 REPL 会比较方便。
怎么实现那种按 Enter 就求值的 REPL 呢?我们仿冒一下 Firefox Developer Console 和 IRB 的设计:一个表达式可以写在多行,就是说换行时如果输入不完整可以继续读下去。
实现简单,将会使用到 Observer<Expr> 呢,这样我们可以同时支持按单个 Expr 求值的 REPL,以及按整个文件求值的直接执行。

我们的任务是什么呢?
+ 支持 (fun () (println 1))(fun (a0 a1) (+ a0 a1)) 这样的 Abstraction 和 (f x y) 这样的 Application
+ 支持 Lexical Scoping,当然也包括闭包这个东西
+ 支持 null Name 以及 Boolean Int Long 的字面表达,注意 Int Long 也包含二进制和十六进制表示法
稍后也会支持 Float Double Char String 的字面表达,以及 `() 这种 Scheme 式 symbol list。
+ 支持 () 括号,<> 括号稍后会被我们用于语言扩展,以下我们会把它作为分词过程的语言构词,保留词。
此外,为了语言的一致性,我们要禁止对 [] 和 {} 的使用。

大家觉得,(+ 1 (* 2 3)) 是怎么计算的?我们会把它折叠到 (+ 1 6) 然后继续算下去。
每一个 (+)、(*) 都代表一颗『语法树』的子树,它们都有值,比如 1(* 2 3) 这些都是子树啊。
(+ expr expr) 这是它的类型,而 (+ 1 (* 2 3)) 的第一个 expr,是一个 literal "1",是子树。第二个是表达式,另一个子树。

就是这样,那我们的语言怎么计算呢?或者说它怎么知道 (* 2 3)6 呢?
参考一下上面的全局作用域吧,我们在全局作用域提供 (* int int) 这个操作。
我们可以把全局作用域做成一个 class,包含 get, set 方法,为了语言的灵活性,还得有一个 getFunction 方法。 算喽,既然都是动态类型,动态在全局作用域取那些函数,就检查强转吧。
interface GlobalScope: BasicMap<Symbol, Value> {
// val functions: BasicMap<Symbol, Value>
}
class Prelude: GlobalScope by mutableMapOf(
"*" to { a, b -> (a as Int) * (b as Int) }
)
这个语言认为它的 function 是 interface Invocable { operator fun invoke(vararg args: Value): Value }
这样,我们就能够提供对 (*) 计算的定义了——定义在 Kotlin 里面,一个基本操作。

过会我们会通过简单的面向对象子类型多态 override 入门,认识 Visitor Pattern,写关于 evaluate, dump, check 这类操作的 AST Walker。

— 稍后的语言扩展 —
+ 支持 call-by-need,对参数进行惰性求值
现在我们是 call-by-value,在调用前对参数进行求值。
+ 可利用 (f x _) 进行的 Partial Application
+ <1 + 2> 这样的中缀链,和 (infix l 4 +) (infix r 2 ->) 这种东西,不必支持特殊的词法规则

待会我也会讲一下 Trie 树的实现,这样对可扩展关键字的实现,也可以自己思考下。
#life #statement 清朝翁方纲的女婿戈仙舟有一次对他的老师刘镛说:我岳父让我问问您,您的字哪一笔是古人的?刘镛说:回去问问你岳父,他的字哪一笔是自己的?
Forwarded from Deleted Account
请求数学支援!急!在线等!
Forwarded from Deleted Account
需要依据某一点 P 和一个 rotation、distance 求出 P' 的 (x, y) 轴距离,忘记三角函数怎么用了来着(绝望)
手头也么得纸
Forwarded from Pani Ram
Forwarded from Pani Ram
是要求Q点吗
Forwarded from Deleted Account
应该是的
不过所有那个 象限 都要正常
Forwarded from Pani Ram
Q(x0+d*cos(theta), y0+d*sin(theta))
Forwarded from Pani Ram
theta 是弧度值的
Forwarded from Pani Ram
deg2rad _deg = _deg / 180.0 * _PI
Forwarded from Deleted Account
艹好像失败了
Forwarded from Deleted Account
看起来好像还是不对……算了吧 90+30 度……
Forwarded from Deleted Account
修好 bug,75 行终于弄成了,感动 😥
Forwarded from Deleted Account
KochHill.kt
2.1 KB
@iseki 我的基础工作已经做完了,你可以继续下去,画那个分形了啊 🌝 (注:感谢 @DuckSoft 大佬提供的公式)
Turtle.kt
2.3 KB
#Kotlin #code 画画的程序 当然只是核心部分
import kotlin.math.sin
import kotlin.math.cos
import kotlin.math.PI

protected fun forward(distance: Double) {
val pA = position
val distanceAB = distance.distanceDegree(rotation)
val pB = pA + distanceAB
canvas.drawLine(pA.x, pA.y, pB.x, pB.y)
position.assign(pB)
}
private fun Double.distanceDegree(rotation: Deg): Point2 {
val d = this; val r = rotation.coerceRad()
return Point( (d*cos(r)).toInt(), (d*sin(r)).toInt() )
}

最核心的科技
protected var rotation: Deg get() = rawRotation*FULL_DEG
set(d) { rawRotation = d/FULL_DEG }
protected fun rotate(deg: Double) { rotation += deg }
protected fun forward(distance: Double) {
val pA = position
val distanceAB = distance.lineDegreed(rotation)
val pB = pA + distanceAB
canvas.drawLine(pA.x, pA.y, pB.x, pB.y)
position.assign(pB)
}
private fun Double.lineDegreed(rotation: Deg): Point2 {
val d = this; val r = rotation.coerceRad()
return Point( (d*cos(r)).toInt(), (d*sin(r)).toInt() )
}
/** Coerce to radix from degree */
fun Deg.coerceRad() = this / 180.0 * PI
Turtle.kt
2.6 KB
#Kotlin #code Turtle 最终版本。“我真的不更了”——duangsuse
“我们就是死,也不会再多编辑一次的。”——duangsuse