-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathstdlib.slisp
More file actions
278 lines (224 loc) · 6.69 KB
/
Copy pathstdlib.slisp
File metadata and controls
278 lines (224 loc) · 6.69 KB
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
;;; stdlib.lisp - Lisp standard library, prepended to user programs.
;;
;; We're consistent with argument usage so:
;;
;; n is an integer.
;; x is anything (cons, list, int, character, string, lambda, whatever).
;; xs is a list.
;; fn is a callable function, which in practice means a lambda.
;;
;; Some functions might have different arguments, but if they are anything listed
;; above then their value will always be as expected.
;;
;;; printing functions
(defun print (x)
"Print the given item intelligently."
(cond
((char? x) (putc x))
((float? x) (printfloat x))
((int? x) (printint x))
((lambda? x) (printstr "<lambda>"))
((nil? x) (printstr "<nil>"))
((str? x) (printstr x))
((cons? x) (do
(putc #\()
(print-cons x) ; List items, separated by spaces
(putc #\))))
(t (printstr "uknown type"))))
(defun print-cons (x)
"Print the contents of the cons X, recursively."
(print (car x))
(if (nil? (cdr x))
nil
(if (cons? (cdr x))
(do
(putc 32)
(print-cons (cdr x)))
(do
(printstr " . ")
(print (cdr x))))))
;; exactly like print, but with a newline on the end.
(defun println (x)
"Print everything as 'print' would, but append a newline afterwards."
(print x)
(newline))
;;; logical functions
(defun and (xs)
"Return true if every item in the specified list is true.
NOTE: This is not a macro, so all arguments are evaluated."
(let ((res (filter xs (lambda (x) x))))
(= (length xs) (length res))))
(defun or (xs)
"Return true if any value in the specified list contains a true value.
NOTE: This is not a macro, so all arguments are evaluated."
(let ((res (filter xs (lambda (x) x))))
(> (length res) 0)))
;;; Maths functions
(defun abs (n)
"Return the absolute value of N, as a positive number"
(if (< n 0) (- 0 n) n))
(defun even? (n)
"Return 1 if the number is even, nil otherwise."
(= (% n 2 ) 0))
(defun odd? (n)
"Return 1 if the number is odd, nil otherwise."
(= (% n 2 ) 1))
(defun zero? (n)
"Return 1 if the number is zero, nil otherwise."
(= n 0))
(defun one? (n)
"Return 1 if the number is one, nil otherwise."
(= n 1))
(defun neg? (n)
"Return 1 if the number is negative, nil otherwise."
(< n 0))
(defun pos? (n)
"Return 1 if the number is positive, nil otherwise."
(> n 0))
(defun sum (xs)
"sum all the numbers in the list"
(if xs
(+ (car xs)
(sum (cdr xs)))
0))
(defun max (xs)
"Return the maximum integer from the list of numbers supplied."
(if (nil? xs)
xs
(reduce xs
(lambda (a b)
(if (< a b) b a))
(car xs))))
(defun min (xs)
"Return the smallest integer from the list of numbers supplied."
(if (nil? xs)
xs
(reduce xs
(lambda (a b)
(if (< a b) a b))
(car xs))))
;;; List-creation methods
(defun range (start end step)
"Create a list of numbers between the start and end bounds, inclusive.
Incrementing by the given step each time."
(if (<= start end)
(cons start (range (+ start step) end step))
nil))
(defun seq (n)
"Create a list of number ranging from 0-N, inclusive."
(range 0 n 1))
(defun nat (n)
"Create a list of numbers ranging from 1-N, inclusive."
(range 1 n 1))
(defun repeated (n x)
"Return a list of length n whose elements are all x."
(if (pos? n)
(cons x (repeated (- n 1) x))))
;;; list utility functions
(defun append (xs item)
"Append the given value to the specified list. If the list is empty just return the specified item."
(if (nil? xs)
item
(cons (car xs) (append (cdr xs) item))))
(defun filter (xs fn)
"Return a list consisting of all members of the given list for which the given predicate returns non-nil."
(if (nil? xs)
nil
(if (fn (car xs))
(cons (car xs) (filter (cdr xs) fn))
(filter (cdr xs) fn))))
(defun join (xs)
"Join an arbitrary list of strings together into a single string."
(if xs
(join-helper (cdr xs) (car xs))
""))
(defun join-helper (xs acc)
(if xs
(join-helper
(cdr xs)
(strcat acc (car xs)))
acc))
(defun join-by (xs sep)
"Join string list-items by the given separator"
(if xs
(join-rest (cdr xs) (car xs) sep)
""))
(defun join-rest (xs acc sep)
(if xs
(join-rest
(cdr xs)
(strcat (strcat acc sep)
(car xs))
sep)
acc))
(defun find-helper (xs item index)
(if xs
(if (= (car xs) item)
(cons index
(find-helper (cdr xs) item (+ index 1)))
(find-helper (cdr xs) item (+ index 1)))
nil))
(defun find (xs item)
"Return the offsets of any occurrence of the item in the given list, nil on failure."
(find-helper xs item 0))
(defun flatten (xs)
"Converts a list of nested lists to a single list, flattening it."
(if (nil? xs)
nil
(if (! (cons? (car xs)))
(cons (car xs) (flatten (cdr xs)))
(append (flatten (car xs)) (flatten (cdr xs))))))
(defun length (xs)
"Return the length of the given list or string."
(if (str? xs)
(strlen xs)
(if xs
(+ 1 (length (cdr xs)))
0)))
(defun repeat (n fn)
"Execute the supplied body of code N times."
(if (> n 0)
(do
(fn n)
(repeat (- n 1) fn))))
(defun nth (xs n)
"Return the Nth item from the specified list"
(if (= n 0)
(car xs)
(nth (cdr xs) (- n 1))))
(defun map (fn xs)
"Create a new list by calling the given function for every list element."
(if (nil? xs)
nil
(cons (fn (car xs)) (map fn (cdr xs)))))
(defun member? (xs item)
"Return true if the specified item is found within the given list."
(cond
( (nil? xs) nil)
( (= item (car xs)) 1)
( 1 (member? (cdr xs) item))))
(defun reduce (xs fn acc)
"This is our reduce function, which uses a list, a function, and the accumulator."
(if (nil? xs)
acc
(reduce (cdr xs) fn (fn acc (car xs)))))
(defun reverse-inner (xs acc)
"Helper to use an accumulator to reverse a list. Used by 'reverse'"
(if (nil? xs)
acc
(reverse-inner (cdr xs) (cons (car xs) acc))))
(defun reverse (xs)
"Reverse the contents of the specified list."
(reverse-inner xs nil))
;;; system functions
(defun getenv (name)
(getenv-loop name (environment)))
(defun getenv-loop (name xs)
(if xs
(let ((parts (split (car xs) #\=)))
(if parts
(if (= (car parts) name)
(car (cdr parts))
(getenv-loop name (cdr xs)))
(getenv-loop name (cdr xs))))
nil))