Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d59215d

Browse filesBrowse files
committed
Merge branch 'master' of github.com:fluentpython/example-code-2e
2 parents 2c12305 + ade9577 commit d59215d
Copy full SHA for d59215d

File tree

Expand file treeCollapse file tree

14 files changed

+1314
-23
lines changed
Filter options
Expand file treeCollapse file tree

14 files changed

+1314
-23
lines changed
+258Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
"""
2+
Doctests for `parse`
3+
--------------------
4+
5+
# tag::PARSE[]
6+
>>> from lis import parse
7+
>>> parse('1.5')
8+
1.5
9+
>>> parse('ni!')
10+
'ni!'
11+
>>> parse('(gcd 18 45)')
12+
['gcd', 18, 45]
13+
>>> parse('''
14+
... (define double
15+
... (lambda (n)
16+
... (* n 2)))
17+
... ''')
18+
['define', 'double', ['lambda', ['n'], ['*', 'n', 2]]]
19+
20+
# end::PARSE[]
21+
22+
Doctest for `Environment`
23+
-------------------------
24+
25+
# tag::ENVIRONMENT[]
26+
>>> from lis import Environment
27+
>>> inner_env = {'a': 2}
28+
>>> outer_env = {'a': 0, 'b': 1}
29+
>>> env = Environment(inner_env, outer_env)
30+
>>> env['a'] = 111 # <1>
31+
>>> env['c'] = 222
32+
>>> env
33+
Environment({'a': 111, 'c': 222}, {'a': 0, 'b': 1})
34+
>>> env.change('b', 333) # <2>
35+
>>> env
36+
Environment({'a': 111, 'c': 222}, {'a': 0, 'b': 333})
37+
38+
# end::ENVIRONMENT[]
39+
40+
Doctests for `evaluate`
41+
-----------------------
42+
43+
# tag::EVAL_NUMBER[]
44+
>>> from lis import parse, evaluate, standard_env
45+
>>> evaluate(parse('1.5'), {})
46+
1.5
47+
48+
# end::EVAL_NUMBER[]
49+
50+
# tag::EVAL_SYMBOL[]
51+
>>> from lis import standard_env
52+
>>> evaluate(parse('+'), standard_env())
53+
<built-in function add>
54+
>>> evaluate(parse('ni!'), standard_env())
55+
Traceback (most recent call last):
56+
...
57+
KeyError: 'ni!'
58+
59+
# end::EVAL_SYMBOL[]
60+
61+
62+
# tag::EVAL_QUOTE[]
63+
>>> evaluate(parse('(quote no-such-name)'), standard_env())
64+
'no-such-name'
65+
>>> evaluate(parse('(quote (99 bottles of beer))'), standard_env())
66+
[99, 'bottles', 'of', 'beer']
67+
>>> evaluate(parse('(quote (/ 10 0))'), standard_env())
68+
['/', 10, 0]
69+
70+
# end::EVAL_QUOTE[]
71+
72+
# tag::EVAL_IF[]
73+
>>> evaluate(parse('(if (= 3 3) 1 0))'), standard_env())
74+
1
75+
>>> evaluate(parse('(if (= 3 4) 1 0))'), standard_env())
76+
0
77+
78+
# end::EVAL_IF[]
79+
80+
81+
# tag::EVAL_LAMBDA[]
82+
>>> expr = '(lambda (a b) (* (/ a b) 100))'
83+
>>> f = evaluate(parse(expr), standard_env())
84+
>>> f # doctest: +ELLIPSIS
85+
<lis.Procedure object at 0x...>
86+
>>> f(15, 20)
87+
75.0
88+
89+
# end::EVAL_LAMBDA[]
90+
91+
# tag::EVAL_DEFINE[]
92+
>>> global_env = standard_env()
93+
>>> evaluate(parse('(define answer (* 7 6))'), global_env)
94+
>>> global_env['answer']
95+
42
96+
97+
# end::EVAL_DEFINE[]
98+
99+
# tag::EVAL_DEFUN[]
100+
>>> global_env = standard_env()
101+
>>> percent = '(define (% a b) (* (/ a b) 100))'
102+
>>> evaluate(parse(percent), global_env)
103+
>>> global_env['%'] # doctest: +ELLIPSIS
104+
<lis.Procedure object at 0x...>
105+
>>> global_env['%'](170, 200)
106+
85.0
107+
108+
# end::EVAL_DEFUN[]
109+
110+
function call:
111+
112+
# tag::EVAL_CALL[]
113+
>>> evaluate(parse('(% (* 12 14) (- 500 100))'), global_env)
114+
42.0
115+
116+
# end::EVAL_CALL[]
117+
118+
# tag::EVAL_SYNTAX_ERROR[]
119+
>>> evaluate(parse('(lambda is not like this)'), standard_env())
120+
Traceback (most recent call last):
121+
...
122+
SyntaxError: (lambda is not like this)
123+
124+
# end::EVAL_SYNTAX_ERROR[]
125+
126+
"""
127+
128+
import math
129+
130+
from lis import run
131+
132+
133+
fact_src = """
134+
(define (! n)
135+
(if (< n 2)
136+
1
137+
(* n (! (- n 1)))
138+
)
139+
)
140+
(! 42)
141+
"""
142+
def test_factorial():
143+
got = run(fact_src)
144+
assert got == 1405006117752879898543142606244511569936384000000000
145+
assert got == math.factorial(42)
146+
147+
148+
gcd_src = """
149+
(define (mod m n)
150+
(- m (* n (// m n))))
151+
(define (gcd m n)
152+
(if (= n 0)
153+
m
154+
(gcd n (mod m n))))
155+
(display (gcd 18 45))
156+
"""
157+
def test_gcd(capsys):
158+
run(gcd_src)
159+
captured = capsys.readouterr()
160+
assert captured.out == '9\n'
161+
162+
163+
quicksort_src = """
164+
(define (quicksort lst)
165+
(if (null? lst)
166+
lst
167+
(begin
168+
(define pivot (car lst))
169+
(define rest (cdr lst))
170+
(append
171+
(quicksort
172+
(filter (lambda (x) (< x pivot)) rest))
173+
(list pivot)
174+
(quicksort
175+
(filter (lambda (x) (>= x pivot)) rest)))
176+
)
177+
)
178+
)
179+
(quicksort (list 2 1 6 3 4 0 8 9 7 5))
180+
"""
181+
def test_quicksort():
182+
got = run(quicksort_src)
183+
assert got == [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
184+
185+
186+
# Example from Structure and Interpretation of Computer Programs
187+
# https://mitpress.mit.edu/sites/default/files/sicp/full-text/sicp/book/node12.html
188+
189+
newton_src = """
190+
(define (sqrt x)
191+
(sqrt-iter 1.0 x))
192+
(define (sqrt-iter guess x)
193+
(if (good-enough? guess x)
194+
guess
195+
(sqrt-iter (improve guess x) x)))
196+
(define (good-enough? guess x)
197+
(< (abs (- (* guess guess) x)) 0.001))
198+
(define (improve guess x)
199+
(average guess (/ x guess)))
200+
(define (average x y)
201+
(/ (+ x y) 2))
202+
(sqrt 123454321)
203+
"""
204+
def test_newton():
205+
got = run(newton_src)
206+
assert math.isclose(got, 11111)
207+
208+
209+
closure_src = """
210+
(define (make-adder increment)
211+
(lambda (x) (+ increment x))
212+
)
213+
(define inc (make-adder 1))
214+
(inc 99)
215+
"""
216+
def test_closure():
217+
got = run(closure_src)
218+
assert got == 100
219+
220+
closure_with_change_src = """
221+
(define (make-counter)
222+
(define n 0)
223+
(lambda ()
224+
(set! n (+ n 1))
225+
n)
226+
)
227+
(define counter (make-counter))
228+
(display (counter))
229+
(display (counter))
230+
(display (counter))
231+
"""
232+
def test_closure_with_change(capsys):
233+
run(closure_with_change_src)
234+
captured = capsys.readouterr()
235+
assert captured.out == '1\n2\n3\n'
236+
237+
238+
239+
# tag::RUN_AVERAGER[]
240+
closure_averager_src = """
241+
(define (make-averager)
242+
(define count 0)
243+
(define total 0)
244+
(lambda (new-value)
245+
(set! count (+ count 1))
246+
(set! total (+ total new-value))
247+
(/ total count)
248+
)
249+
)
250+
(define avg (make-averager))
251+
(avg 10)
252+
(avg 11)
253+
(avg 15)
254+
"""
255+
def test_closure_averager():
256+
got = run(closure_averager_src)
257+
assert got == 12.0
258+
# end::RUN_AVERAGER[]

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.