-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path03-list-util.lsp
77 lines (72 loc) · 2.3 KB
/
03-list-util.lsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
; (let-recursive <var> <value> <expression>)
; HACK: modifies the definition after the evaluation of value so that late
; self-references can be accommodated, allowing for example tail-recursive
; procs
(define let-recursive (proc args scope
(let1 scope'
(cons (cons (car args) ()) scope) ; prepend (<var> . ())
(let1 value
(eval scope' (cadr args))
(seq1
(let1 pair-ref (ref (car scope'))
; modify the tail of the cons in-place
; usually you should not do this
(seq1
(poke.d (car (call-native +$ 1 pair-ref 0x10)) (ref value))
(deref pair-ref)))
(eval scope' (cadr (cdr args))))))))
; evaluate all elements of a list
(define eval-list
(let-recursive map
(proc args scope
(if (nil? args) ()
(cons (eval scope (car args)) (eval scope (cons map (cdr args))))))
; pass evaluated list to `map`, running it in the provided scope
(proc args scope
(eval (eval scope (car args)) (cons map (eval scope (cadr args)))))))
; make a list from args
(define list
(proc args scope (eval-list scope args)))
; associate two lists into pairs
; if the second list is shorter than the first, remaining pairs will be associated to nil
(define assoc
(let-recursive map
(proc args ()
(if (nil? (car args))
()
(cons
(cons
(car (car args))
(car (cadr args)))
(unquote (list map
(cdr (car args))
(cdr (cadr args)))))))
; pass evaluated first and second arg to `map`
(proc args scope
(unquote (list map
(eval scope (car args))
(eval scope (cadr args)))))))
; concat two lists
(define concat
(let-recursive rec
(proc args scope
(if (nil? (car args))
(cadr args)
(cons (car (car args))
(unquote (list rec
(cdr (car args))
(cadr args))))))
(proc args scope
(unquote (list rec
(eval scope (car args))
(eval scope (cadr args)))))))
; (range 0 5) => (0 1 2 3 4)
(define range
(proc args scope
(let1 start (eval scope (car args))
(let1 end (eval scope (cadr args))
(if (zero? (car (call-native -$ 1 end start)))
()
(cons start (range
(car (call-native +$ 1 start 1))
end)))))))