-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexamples.wick
More file actions
143 lines (120 loc) · 5.5 KB
/
Copy pathexamples.wick
File metadata and controls
143 lines (120 loc) · 5.5 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
;; examples.wick — a short tour of wick.
;; --- basic recursion ---
(def fact (fn (n) (if (<= n 1) 1 (* n (fact (- n 1))))))
(print "10! =" (fact 10))
;; --- fibonacci (slow, but shows recursion works) ---
(def fib (fn (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))
(print "fib 20 =" (fib 20))
;; --- closures: counter that remembers its own state ---
(def make-counter
(fn ()
(let ((n 0))
(fn ()
(set! n (+ n 1))
n))))
(def c (make-counter))
(print "counter:" (c) (c) (c) (c))
;; --- higher-order functions from the stdlib ---
(print "squares of 1..5 =" (map (fn (x) (* x x)) (list 1 2 3 4 5)))
(print "evens of 1..10 =" (filter (fn (x) (= (mod x 2) 0)) (range 11)))
(print "sum of 0..100 =" (sum (range 101)))
;; --- cond ---
(def sign (fn (n)
(cond
((< n 0) "negative")
((= n 0) "zero")
(else "positive"))))
(print "signs:" (sign -3) (sign 0) (sign 42))
;; --- tail-call optimization: this would blow a normal recursive stack ---
(def count-down (fn (n) (if (= n 0) "done" (count-down (- n 1)))))
(print "count-down 100000 =" (count-down 100000))
;; --- compose functions ---
(def compose (fn (f g) (fn (x) (f (g x)))))
(def inc (fn (x) (+ x 1)))
(def dbl (fn (x) (* x 2)))
(print "(inc . dbl) 5 =" ((compose inc dbl) 5))
;; --- everything is expressions ---
(def answer
(let ((xs (range 10)))
(sum (map (fn (x) (* x x)) xs))))
(print "sum of squares 0..9 =" answer)
;; --- bridging numbers and strings ---
(print (string-append "answer = " (number->string answer)))
(print "parsed:" (string->number "3.14") "+ 1 =" (+ (string->number "3.14") 1))
;; --- sort + min/max + member? ---
(def xs '(3 1 4 1 5 9 2 6 5 3 5))
(print "sorted:" (sort < xs))
(print "min/max:" (min xs) (max xs))
(print "has 7?" (member? 7 xs) "has 9?" (member? 9 xs))
;; --- fizzbuzz: cond + mod + number->string ---
(def fizzbuzz (fn (n)
(cond
((= (mod n 15) 0) "FizzBuzz")
((= (mod n 3) 0) "Fizz")
((= (mod n 5) 0) "Buzz")
(else (number->string n)))))
(print "fizzbuzz 1..15:")
(map (fn (n) (print " " (fizzbuzz n))) (map inc (range 15)))
;; --- dicts: immutable, string-keyed maps ---
;; {k v ...} is sugar for (dict k v ...); [a b c] is sugar for (list a b c).
(def patrick {"name" "Patrick" "tool" "wick" "version" "0.2"})
(print "name:" (dict-get patrick "name"))
(print "missing:" (dict-get patrick "title" "(unset)"))
(def with-title (dict-set patrick "title" "builder"))
(print "keys after set:" (dict-keys with-title))
(print "original unchanged:" (dict-keys patrick))
;; --- list literals: [a b c] desugars to (list a b c) ---
(print "squares of [1 2 3]:" (map (fn (n) (* n n)) [1 2 3]))
(def alice {"name" "Alice" "age" 30 "tags" ["admin" "user"]})
(print "alice tags:" (dict-get alice "tags"))
;; --- json: round-trip lists and dicts through JSON ---
(def doc {"name" "wick" "version" "0.3" "tags" ["tiny" "lisp"]})
(def encoded (json-stringify doc))
(print "json:" encoded)
(def decoded (json-parse encoded))
(print "tags from parsed:" (dict-get decoded "tags"))
;; --- file IO: a small persistent counter ---
(def counter-file "/tmp/wick-counter.txt")
(def current
(if (file-exists? counter-file)
(string->number (read-file counter-file))
0))
(def next (inc current))
(write-file counter-file (number->string next))
(print "runs so far:" next)
;; --- string ops: enough to actually process text ---
(print "contains 'wick':" (string-contains? "made of wick" "wick"))
(print "csv split:" (string-split "go,ruby,wick" ","))
(print "redact:" (string-replace "hello world hello" "hello" "***"))
(print "first word:" (substring "hello world" 0 5))
(print "shout:" (string-upcase "claude"))
(print "trim+downcase:" (string-downcase (string-trim " PATRICK ")))
;; --- regex: RE2 patterns, data-first ---
(print "has digits:" (re-match? "order #4271" "[0-9]+"))
(print "first num:" (re-find "order #4271 confirmed at 14:23" "[0-9]+"))
(print "all words:" (re-find-all "wick is a tiny lisp" "[a-z]+"))
(print "redact emails:" (re-replace "ping p@pwhite.org or me@byclaude.net"
"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-z]+"
"<email>"))
(print "split by punct:" (re-split "go,ruby; wick.lisp" "[,;.]\\s*"))
;; --- error handling: try / raise / error? / error-message ---
(print "caught:" (try (raise "something went wrong") (fn (e) (error-message e))))
(print "bad json:" (error? (try (json-parse "{not json}"))))
(def safe-divide (fn (a b)
(if (= b 0) (raise "divide by zero") (/ a b))))
(print "10/0 ->" (try (safe-divide 10 0) (fn (e) (error-message e))))
(print "10/2 ->" (try (safe-divide 10 2)))
;; --- http + json: fetch the world, parse it, pick a field out ---
;; http-get raises on network error; try lets us recover with a default.
(def resp (try (http-get "https://httpbingo.org/json")
(fn (e) (dict "status" 0 "body" "" "error" (error-message e)))))
(if (= (dict-get resp "status") 200)
(print "fetched title:" (dict-get (dict-get (json-parse (dict-get resp "body")) "slideshow") "title"))
(print "fetch failed:" (dict-get resp "error" (number->string (dict-get resp "status")))))
;; --- http-post: send JSON, read echo back ---
;; pass a Content-Type so the server treats the body as text and echoes it.
(def echo (try (http-post "https://httpbingo.org/post"
(json-stringify {"hello" "wick"})
{"Content-Type" "application/json"})
(fn (e) (dict "status" 0 "body" "" "error" (error-message e)))))
(print "post status:" (dict-get echo "status"))