-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest.lisp
193 lines (153 loc) · 5.65 KB
/
test.lisp
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
;;; test.lisp - Simple feature-tests/demonstrations of our system.
;;
;; This is a sample input file for our minimal lisp interpreter.
;;
;; We use it to demonstrates and test our the basic features.
;;
;; NOTE: A lot of the things called here are defined in the standard
;; library, which is pre-pended to all loaded-scripts.
;; Instead of just (+ 1 2) we allow multiple args
(print "Our mathematical functions allow 2+ arguments, e.g: %s = %s"
(quote (+ 1 2 3 4 5 6)) (+ 1 2 3 4 5 6))
;;
;; Use our "repeat" function, from the standard library, to run a block
;; N/10 times. The number of the attempt is given as a parameter.
;;
(repeat 10 (lambda (n) (print "I'm in a loop %s" n)))
;;
;; Use our "while" function, from the standard library, to run a block
;; of code N/5 times.
;;
(let ((a 5))
(while (> a 0)
(begin
(print "(while) loop - iteration %s" a)
(set! a (- a 1) true))))
;; Define a function, `fact`, to calculate factorials.
(define fact (lambda (n)
(if (<= n 1)
1
(* n (fact (- n 1))))))
;; Invoke the factorial function, using apply
;;
;; Calculate the factorial of "big numbers" mostly as a test of the
;; `now` function which times how long it took.
(apply (list 1 10 100 1000 10000 100000)
(lambda (x)
(let ((start (now)))
(print "%s! => %s [%s seconds]" x (fact x) (- (now) start)))))
; Split a string into a list, reverse it, and join it
(let ((input "Steve Kemp"))
(begin
(print "Starting string: %s" input)
(print "Reversed string: %s" (join (reverse (split "Steve Kemp" ""))))))
;; Define a variable "foo => 0"
;; but then change it, and show that result
(let ((foo 0))
(begin
(print "foo is set to %s" foo)
(set! foo 3)
(print "foo is now set to %s" foo)))
;;Now we're outside the scope of the `let` so `foo` is nil
(if foo
(print "something weird happened!")
(print "foo is unset now, outside the scope of the `let`"))
;; Define another function, and invoke it
(define sum2 (lambda (n acc) (if (= n 0) acc (sum2 (- n 1) (+ n acc)))))
(print "Sum of 1-100: %s" (sum2 100 0))
;; Now create a utility function to square a number
(define sq (lambda (x) (* x x)))
;; For each item in the range 1-10, print it, and the associated square.
;; Awesome! Much Wow!
(apply (nat 11)
(lambda (x)
(print "%s\tsquared is %s" x (sq x))))
;; Test our some of our earlier functions against a range of numbers
(apply (list -2 -1 0 1 2 3 4 5)
(lambda (x)
(begin
(if (neg? x) (print "%s is negative" x))
(if (zero? x) (print "%s is ZERO" x))
(if (even? x) (print "%s is EVEN" x))
(if (odd? x) (print "%s is ODD" x)))))
;; Test that we can get the correct type of each of our primitives
(apply (list 1 "steve" (list 1 2 3) true #t false #f nil boolean? print)
(lambda (x)
(print "'%s' has type '%s'" x (type x))))
;;
;; Show even numbers via the filter-function.
;;
(print "Even numbers from 0-10: %s" (filter (nat 11) even?))
;;
;; And again with square numbers.
;;
(print "Squared numbers from 0-10: %s" (map (nat 11) sq))
;;
;; Setup a list of integers, and do a few things with it.
;;
(let ((vals '(32 92 109 903 31 3 -93 -31 -17 -3)))
(begin
(print "Working with the list: %s " vals)
(print "\tBiggest item is %s" (max vals))
(print "\tSmallest item is %s" (min vals))
(print "\tReversed list is %s " (reverse vals))
(print "\tSorted list is %s " (sort vals))
(print "\tFirst item is %s " (first vals))
(print "\tRemaining items %s " (rest vals))
))
;;
;; A simple assertion function
;;
(define assert (lambda (result msg)
(if result ()
(print "ASSERT failed - %s" msg))))
;;
;; Make some basic tests using our assert function.
;;
(assert (function? print) "(function? print) failed")
(assert (function? assert) "(function? assert) failed")
(assert (eq 6 (+ 1 2 3)) "1+2+3 != 6")
(assert (eq 24 (* 2 3 4)) "2*3*4 != 24")
(assert (eq 70 (- 100 10 20)) "100-10-20 != 70")
(assert (eq (type type) "procedure(golang)") "(type type)")
(assert (eq (type assert) "procedure(lisp)") "(type assert)")
(assert (eq (type 1) "number") "(type number)")
(assert (eq (type "me") "string") "(type string)")
(assert (eq (type (list 1 2)) "list") "(type list)")
(assert (neg? -3) "negative number detected")
(assert (! (neg? 0) ) "zero is not negative")
(assert (! (neg? 30) ) "a positive number is not negative")
(assert (= (abs -3) (abs 3)) "abs(-3) == 3")
(assert (= (fact 1) 1) "1! = 1")
(assert (= (fact 2) 2) "2! = 2")
(assert (= (fact 3) 6) "3! = 6")
(assert (< 3 30) "3 < 30")
(assert (! (< 30 30)) "30 < 30")
(assert (<= 30 30) "30 < 30")
(assert (> 30 20) "30 > 20")
;; nth starts counting at zero which is perhaps surprising.
(assert (= (nth (list 10 20 30) 0) 10) "Got the first item of the list.")
(assert (= (nth (list 10 20 30) 1) 20) "Got the second item of the list.")
;; We have a built-in eval function, which operates upon symbols, or strings.
(define e "(+ 3 4)")
(print "Eval of '%s' resulted in %s" e (eval e))
(print "Eval of '%s' resulted in %s" "(+ 40 2)" (eval "(+ 40 2)"))
;; Simple test of `cond`
(define a 6)
(cond
(quote
(> a 20) (print "A > 20")
(> a 15) (print "A > 15")
true (print "A is %s" a)
))
;;
;; Trivial Read/Eval pair
;;
(print "The answer to life, the universe, and everything is %s!\n"
(eval (read "(* 6 7)")))
;; Upper-case and lower-casing of strings
(print "%s" (upper "hello, world"))
(print "%s" (lower "Hello, World; in LOWER-case."))
;; All done! -> In red :)
(define red (lambda (msg) (sprintf "\e[0;31m%s\e[0m" msg)))
(print (red "All done!"))