[obsidian] vault backup: 2023-11-25 02:30:30[
This commit is contained in:
parent
e0132e6b68
commit
55c96ad6f2
@ -8,23 +8,9 @@
|
|||||||
(let double (lambda (x) (* x x)) (double 6))
|
(let double (lambda (x) (* x x)) (double 6))
|
||||||
```
|
```
|
||||||
|
|
||||||
まあプリミティブ演算は四則演算だけで再帰関数は自力で定義
|
ただ再帰は今のところ難しい。多分ListとAtomの区別がきちんとできてないせいで不動点コンビネータがきちんと動かない。
|
||||||
```lisp
|
|
||||||
(let fix
|
あくまで雰囲気重視で、ということなのだが、結果的にコードが短いため初学者にわかりやすいかと言われると、かなりコメントを足していかないと読めなさそう。
|
||||||
(lambda (f)
|
|
||||||
(
|
|
||||||
(lambda (x) (f (lambda(y) (x x y))))
|
|
||||||
(lambda (x) (f (lambda(y) (x x y))))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(let fact
|
|
||||||
(fix (lambda (f) (lambda (n) (if n (* n (f (- n 1))) 1) ) ))
|
|
||||||
(fact 10)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
%% 一行に直す %%
|
|
||||||
(let fix (lambda (f) ( (lambda (x) (f (lambda(y) (x x y)))) (lambda (x) (f (lambda(y) (x x y))))))(let fact (fix (lambda (f) (lambda (n) (if n (* n (f (- n 1))) 1) ) ))(fact 10)))
|
|
||||||
```
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const reader = require("readline").createInterface({
|
const reader = require("readline").createInterface({
|
||||||
@ -65,11 +51,7 @@ const parse = (tokens) => {
|
|||||||
}
|
}
|
||||||
return next_res
|
return next_res
|
||||||
}
|
}
|
||||||
|
const read = (str) => parse(tokenize(str));
|
||||||
const read = (str) => {
|
|
||||||
const res = parse(tokenize(str));
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
const binop = (args, fn) => fn(args[0], args[1]);
|
const binop = (args, fn) => fn(args[0], args[1]);
|
||||||
|
|
||||||
@ -78,7 +60,8 @@ const env = {
|
|||||||
"+": args => binop(args, (a, b) => a + b),
|
"+": args => binop(args, (a, b) => a + b),
|
||||||
"-": args => binop(args, (a, b) => a - b),
|
"-": args => binop(args, (a, b) => a - b),
|
||||||
"*": args => binop(args, (a, b) => a * b),
|
"*": args => binop(args, (a, b) => a * b),
|
||||||
"/": args => binop(args, (a, b) => a / b)
|
"/": args => binop(args, (a, b) => a / b),
|
||||||
|
"if": args => args[0] ? args[1] : args[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
const try_find = (name, env) => {
|
const try_find = (name, env) => {
|
||||||
@ -92,30 +75,34 @@ const try_find = (name, env) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const eval = (expr, env) => {
|
const eval = (expr, env) => {
|
||||||
|
if (expr ==null){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
if (!Array.isArray(expr)) {
|
if (!Array.isArray(expr)) {
|
||||||
return !isNaN(parseFloat(expr)) ? parseFloat(expr) : try_find(expr, env)
|
return !isNaN(parseFloat(expr)) ? parseFloat(expr) : try_find(expr, env)
|
||||||
} else {
|
} else {
|
||||||
const op = expr.shift();
|
const op = expr.shift();
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case 'let': {
|
case 'let': {
|
||||||
|
let res = eval(expr[1], env);
|
||||||
let newenv = { "parent": env };
|
let newenv = { "parent": env };
|
||||||
env[expr[0]] = eval(expr[1], newenv);
|
newenv[expr[0]] = res;
|
||||||
return eval(expr[2], env)
|
return eval(expr[2], newenv)
|
||||||
}
|
}
|
||||||
case 'lambda': return ['closure', expr[0], expr[1], env]//ids,body,env
|
case 'lambda': return ['closure', expr[0], expr[1], env]//ids,body,env
|
||||||
default: {
|
default: {
|
||||||
let fn = try_find(op, env);
|
let fn = eval(op, env);
|
||||||
if (fn) {
|
if (fn) {
|
||||||
if (Array.isArray(fn) && fn[0] === "closure") {
|
if (Array.isArray(fn) && fn[0] === "closure") {//closure
|
||||||
for (let i = 0; i < fn[1].length; i++) {
|
for (let i = 0; i < fn[1].length; i++) {
|
||||||
fn[3][fn[1][i]] = expr[i]
|
fn[3][fn[1][i]] = eval(expr[i],env)
|
||||||
}
|
}
|
||||||
return eval(fn[2], fn[3])
|
return eval(fn[2], fn[3])
|
||||||
} else {
|
} else {//extern function
|
||||||
return fn(expr.map(e => eval(e, env)))
|
return fn(expr.map(e => eval(e, env)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error(`symbol ${op} not found`)
|
return fn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
#programming-language #compiler-design
|
#programming-language #compiler-design
|
||||||
|
|
||||||
[[Node.jsで100行で書くLISP風ラムダ計算]]
|
[[Node.jsで約100行で書くLISP風ラムダ計算]]
|
||||||
|
|
||||||
|
|
||||||
[Write a JavaScript Parser in Rust](https://oxc-project.github.io/javascript-parser-in-rust/ja/docs/intro/)
|
[Write a JavaScript Parser in Rust](https://oxc-project.github.io/javascript-parser-in-rust/ja/docs/intro/)
|
||||||
|
Loading…
Reference in New Issue
Block a user