96 lines
1.4 KiB
Markdown
96 lines
1.4 KiB
Markdown
# puyo 3 (this time it's nameful)
|
|
|
|
## semantics
|
|
single-threaded, dynamically-typed (because lol), multiple named returns by default, pass-by-value
|
|
|
|
functions take and return a map ALWAYS
|
|
|
|
Values:
|
|
- function
|
|
- number (f64)
|
|
- map (HashMap<Symbol, >)
|
|
|
|
## examples
|
|
`double x = x * 2`
|
|
```rust
|
|
double = fn([x] [x]) (
|
|
^x := x * 2;
|
|
);
|
|
```
|
|
|
|
`apply f x = f x`
|
|
```rust
|
|
;; same as apply = fn([f x] [x]) ( ... )
|
|
fn apply([f x] [x]) (
|
|
^x := f x;
|
|
);
|
|
|
|
;; f would have to be like fn([a] [a]) ( ... )
|
|
```
|
|
|
|
```scheme
|
|
(define (make-counter)
|
|
(let ([i 0])
|
|
(lambda ()
|
|
(set! i (+ i 1))
|
|
i)))
|
|
```
|
|
```rust
|
|
fn make_counter([] [inc]) (
|
|
i := 0;
|
|
^inc := fn([] [i]) (
|
|
i := i + 1;
|
|
^i := i;
|
|
);
|
|
|
|
;; or fn ^inc(...)
|
|
)
|
|
```
|
|
|
|
`desat hsla = { hsla with s := hsla.s / 2 }`
|
|
```rust
|
|
;; omitting the return means it's the same
|
|
fn desat([h s l a]) (
|
|
^s := ^s / 2;
|
|
)
|
|
```
|
|
|
|
`compose f g x = f (g x)`
|
|
```rust
|
|
fn compose([f g x] [x]) (
|
|
^x := g x;
|
|
^x := f x;
|
|
)
|
|
|
|
f := fn([x]) (^x := x + 2;);
|
|
g := fn([x]) (^x := x * 3;);
|
|
f2 := f;
|
|
|
|
compose f g x == (((compose f) g) x) == compose {f: f2, g} x == compose {x} f g
|
|
```
|
|
|
|
`id x = x`
|
|
```rust
|
|
fn id([x]) ()
|
|
```
|
|
|
|
"Maps" should really just be blocks
|
|
```rust
|
|
foo := 3;
|
|
{
|
|
x := 42;
|
|
^twice_x := x * 2;
|
|
^thrice_x := x * 3;
|
|
^foo;
|
|
}
|
|
```
|
|
becomes
|
|
```json5
|
|
{
|
|
"twice_x": 84,
|
|
"thrice_x": 126,
|
|
// ^foo as a statement behaves like ^foo := foo, so we get that nice record field punning
|
|
"foo": 3,
|
|
}
|
|
```
|