-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathatom.xml
More file actions
444 lines (375 loc) · 23.1 KB
/
Copy pathatom.xml
File metadata and controls
444 lines (375 loc) · 23.1 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
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Continous Improvement]]></title>
<link href="http://hkhan.github.com/atom.xml" rel="self"/>
<link href="http://hkhan.github.com/"/>
<updated>2015-06-06T19:59:44+01:00</updated>
<id>http://hkhan.github.com/</id>
<author>
<name><![CDATA[Haroon Khan]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Y Combinator Derivation]]></title>
<link href="http://hkhan.github.com/blog/2014/01/15/y-combinator-derivation/"/>
<updated>2014-01-15T14:17:46+00:00</updated>
<id>http://hkhan.github.com/blog/2014/01/15/y-combinator-derivation</id>
<content type="html"><![CDATA[<p>One of the benefits of going through The Little Schemer, which I’ve <a href="http://hkhan.github.com/blog/2014/01/14/review-little-schemer/">reviewed</a> recently is that it dedicates one of the later chapters solely to arriving at the <a href="http://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator">Y combinator</a>. It starts with a constraint that a function definition is not allowed to refer to itself. Up till this point, recursion has been the key technique for computation but what if a language only contains anonymous functions. In this case, its not possible to refer to the function which is describing the computation. How can recursion be implemented in such a language?</p>
<!-- more -->
<p>This is an interesting and challenging exercise. Of course, its of little practical value in every day programming as all languages allow named function definitions. Nonetheless, its a fascinating question to ask and the real value is in the journey towards understanding and working through a problem methodically. The book provides a great step-by-step treatment of the problem but there are lots of ways to arrive at the solution. I’ve found that each one gives new insights into functional programming techniques and ideas.</p>
<p>Here is a detailed derivation inspired by <a href="http://www.ps.uni-sb.de/courses/sem-prog97/material/YYWorks.ps">A Lecture on the Why of Y</a>.</p>
<div><script src='https://gist.github.com/8436742.js'></script>
<noscript><pre><code>#lang racket
(require rackunit)
;; Y combinator derivation in detailed steps
;; (based on Why of Y derivation by Matthias Felleisen)
;; Is it possible to define a recursive function without referrring to itself?
;; Sounds almost magical but lets give it a go.
;; Define a simple recursive function which refers to itself.
;; The aim is to remove the call to length from within itself.
(define (length l)
(if (null? l) 0
(add1 (length (cdr l)))))
(check-equal? (length '(1 2 3)) 3)
;; Step 1: remove the recursive call to length.
;; Now it will work for length 0 but fail for everything else but its a start.
(define (length0 l)
(if (null? l) 0
(add1 (hukairs (cdr l)))))
;; aptly named as this function should never be called
(define (hukairs)
("ERROR - should not get here"))
(check-equal? (length0 '()) 0)
; (check-equal? (length0 '(x)) 2) FAIL
;; Step 2: now make it work for a list of length 1 by calling length0
(define (length1 l)
(if (null? l) 0
(add1 (length0 (cdr l)))))
(check-equal? (length1 '()) 0)
(check-equal? (length1 '(test)) 1)
;; Step 3: now make it work for list of length 2 by calling length1...I see a pattern
(define (length2 l)
(if (null? l) 0
(add1 (length1 (cdr l)))))
(check-equal? (length2 '()) 0)
(check-equal? (length2 '(test)) 1)
(check-equal? (length2 '(x y)) 2)
; (check-equal? (length1 '(x y z)) 3) FAIL
;; From here on in, we can just use anonymous functions instead of redefining functions
;; Step 4: rewrite length0 so that length reappears and we pass in the seed function
;; (which ofcourse shouldn't be called for list of length 0.
(
((lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l)))))) hukairs)
'())
;; -> 0
;; Step 5: rewrite length1 in the same style as above where we immediately call the
;; new function passing in the length0 definition from Step 4
(
((lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l))))))
((lambda (length) ; 'inlined' definition from step 4
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l)))))) hukairs))
'(1))
;; -> 1
;; Step 6: rewrite length2 in the same style as above...I see a pattern here.
(
((lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l))))))
((lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l))))))
((lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l)))))) hukairs)))
'(1 2))
;; -> 2
;; Step 7: back to length0 - extract the function which looks like length for length0.
;; Now we call the passed in function with hukairs which should never be called.
(
((lambda (mk-length)
(mk-length hukairs))
(lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l)))))))
'())
;; -> 0
;; Step 8: repeat the above step for length1 i.e. make another call to the
;; passed in length-like function
(
((lambda (mk-length)
(mk-length (mk-length hukairs)))
(lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l)))))))
'(a))
;; -> 1
;; Step 9: repeat for length2....I can see the pattern again.
(
((lambda (mk-length)
(mk-length (mk-length (mk-length hukairs))))
(lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l)))))))
'(a b))
;; -> 2
;; Step 10: repeat for length3...just to make sure.
(
((lambda (mk-length)
(mk-length (mk-length (mk-length (mk-length hukairs)))))
(lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l)))))))
'(a b c))
;; -> 3
;; Step 11: back to length0 variant - since we don't care about the hukairs,
;; we could pass mk-length to mk-length instead of hukairs and no one would care.
(
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
(lambda (l)
(if (null? l) 0
(add1 (mk-length (cdr l)))))))
'())
;; -> 0
;; Step 12: in order to create length1, we can now call the passed in function with
;; hukairs function as that will never be called
(
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
(lambda (l)
(if (null? l) 0
(add1 ((mk-length hukairs) (cdr l)))))))
'(a))
;; -> 1
;; Step 13: in order to create length2, we can replace hukairs with the passed in
;; mk-length which means that as the recursion process is about to terminate and it
;; requires one more call, it won't call mk-length with hukaris (which was the case
;; in previous steps). Instead it will call the passed-in function (mk-length) with
;; the same passed in function (mk-length) which can reach the termination condition
;; (null? l) or call itself again, if required....MAGIC
(
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
(lambda (l)
(if (null? l) 0
(add1 ((mk-length mk-length) (cdr l)))))))
'(a b))
;; -> 2
;; Now its just a matter of refactoring and generalizing
;; Step 14: extract the self application and call that length.
(
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
((lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l))))))
(lambda (x) ((mk-length mk-length) x)))))
'(a b c))
;; -> 3
;; Step 15: extract the function which looks like length
(
((lambda (le)
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
(le (lambda (x) ((mk-length mk-length) x))))))
(lambda (length)
(lambda (l)
(if (null? l) 0
(add1 (length (cdr l)))))))
'(a b c))
;; -> 3
;; Step 16: separate the function that makes length from the function
;; that looks like length (le). Notice that mk-length is bound separately in two
;; different scopes
(lambda (le)
((lambda (mk-length)
(mk-length mk-length))
(lambda (mk-length)
(le (lambda (x) ((mk-length mk-length) x))))))
;; -> <procedure>
;; Step 17: give the above a name Y and we have arrived at the Y-Combinator
(define (Y le)
((lambda (f) (f f))
(lambda (g) (le (lambda (x) ((g g) x))))))
;; back to where we started from....define a function which look like length....
(define (f mk-length)
(lambda (l)
(if (null? l) 0
(add1 (mk-length (cdr l))))))
;; and pass that to Y to return a function which is length (without referring to itself)
(define length-Y (Y f))
(check-equal? (length-Y '(a b c d e)) 5)
;; also works for factorials and all other functions which can be defined recursively.
;; (fact is not referenced from within the body)
(define (fact n)
((Y (lambda (mk-fact)
(lambda (n)
(if (= n 0) 1
(* n (mk-fact (- n 1))))))) n))
(check-equal? (fact 5) 120)
;; MAGICAL....did I hear Lambda Calculus......</code></pre></noscript></div>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Review: Little Schemer, Fourth Edition]]></title>
<link href="http://hkhan.github.com/blog/2014/01/14/review-little-schemer/"/>
<updated>2014-01-14T11:34:48+00:00</updated>
<id>http://hkhan.github.com/blog/2014/01/14/review-little-schemer</id>
<content type="html"><![CDATA[<p><a href="http://mitpress.mit.edu/books/little-schemer">The Little Schemer</a> is very different from the usual books on programming. It can probably be considered the first ‘koan-style’ book - it presents a dialogue between a student and a teacher which is used to further the student’s progress and understanding.</p>
<p>The book starts off with the very basics and gradually builds more and more complex ideas namely <a href="http://en.wikipedia.org/wiki/Recursion_(computer_science)">recursion</a>, <a href="http://en.wikipedia.org/wiki/Fixed-point_combinator#Y_combinator">Y combinator</a> and the <a href="http://en.wikipedia.org/wiki/Meta-circular_evaluator">metacirular evaluator</a>. The code translates seamlessly to Racket which is a modern descendent of Scheme and working in DrRacket is a very enjoyable experience. I adopted a TDD approach using RackUnit as the testing framework to give a red-green-refactor style workflow. Gradually, the idea of recursion begins to sink in, the fog begins to clear and the choice of Lisp for expressing these ideas becomes clear. Its a very liberating feeling to be able to express solutions using the very minimal set of constructs whilst taking a peek at what’s so special about Lisp.</p>
<p>In short, this is a wonderful book which has something for everyone. For those new to Lisp and previously used to imperative style, its an eye-opener. It exposes the reader to elegant and beautiful ideas of computation through its learn-by-doing and learn-by-reflection approach. For curious minds, these are fascinating avenues for further exploration. I’ve thoroughly enjoyed going through the exercises, grasping the ideas presented and learning some Lisp along the way. Its definitely on my recommendation list.</p>
<p>Arguably, you can get all this with SICP which gives a much more rigorous and formal treatment of these topics (and more) but this is so much more fun and that’s what its about, isn’t it?</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Builder With Lombok]]></title>
<link href="http://hkhan.github.com/blog/2012/09/25/builder-with-lombok/"/>
<updated>2012-09-25T14:41:35+01:00</updated>
<id>http://hkhan.github.com/blog/2012/09/25/builder-with-lombok</id>
<content type="html"><![CDATA[<p>The Builder Pattern is well known as an alternative to the constructors with multiple arguments; it increases code readability and the fluent interface allows object creation without passing null in the constructor etc. In a recent project, I was creating the domain objects and wanted to generate the builders for these objects cleanly and automatically; the less code the better. There are several Eclipse plugins that can generate the boilerplate code but there is a very clean way to remove the need for these plugins.</p>
<!-- more -->
<p><a href="https://github.com/peichhorn/lombok-pg">lombok-pg</a> provides an alternative. This library extends <a href="http://projectlombok.org/">Project Lombok</a> with even more funky stuff and one of those things is <code>@Builder</code>. The usage is best illustrated with a simple example.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="kn">package</span> <span class="n">co</span><span class="o">.</span><span class="na">uk</span><span class="o">.</span><span class="na">agiletech</span><span class="o">.</span><span class="na">ecommerce</span><span class="o">.</span><span class="na">domain</span><span class="o">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">lombok.Builder</span><span class="o">;</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">lombok.Data</span><span class="o">;</span>
</span><span class='line'>
</span><span class='line'><span class="nd">@Data</span>
</span><span class='line'><span class="nd">@Builder</span>
</span><span class='line'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Customer</span> <span class="o">{</span>
</span><span class='line'>
</span><span class='line'> <span class="kd">private</span> <span class="n">String</span> <span class="n">title</span><span class="o">;</span>
</span><span class='line'> <span class="kd">private</span> <span class="n">String</span> <span class="n">firstName</span><span class="o">;</span>
</span><span class='line'> <span class="kd">private</span> <span class="n">String</span> <span class="n">lastName</span><span class="o">;</span>
</span><span class='line'> <span class="kd">private</span> <span class="n">List</span><span class="o"><</span><span class="n">Order</span><span class="o">></span> <span class="n">orders</span><span class="o">;</span>
</span><span class='line'>
</span><span class='line'> <span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">hasOrders</span><span class="o">()</span> <span class="o">{</span>
</span><span class='line'> <span class="k">return</span> <span class="n">orders</span> <span class="o">!=</span> <span class="kc">null</span> <span class="o">&&</span> <span class="n">orders</span><span class="o">.</span><span class="na">isEmpty</span><span class="o">();</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>The builder can then be used in the test cases with ease.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='java'><span class='line'><span class="kn">package</span> <span class="n">co</span><span class="o">.</span><span class="na">uk</span><span class="o">.</span><span class="na">agiletech</span><span class="o">.</span><span class="na">ecommerce</span><span class="o">.</span><span class="na">domain</span><span class="o">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">static</span> <span class="n">co</span><span class="o">.</span><span class="na">uk</span><span class="o">.</span><span class="na">agiletech</span><span class="o">.</span><span class="na">ecommerce</span><span class="o">.</span><span class="na">domain</span><span class="o">.</span><span class="na">Customer</span><span class="o">.</span><span class="na">customer</span><span class="o">;</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">static</span> <span class="n">org</span><span class="o">.</span><span class="na">hamcrest</span><span class="o">.</span><span class="na">MatcherAssert</span><span class="o">.</span><span class="na">assertThat</span><span class="o">;</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">static</span> <span class="n">org</span><span class="o">.</span><span class="na">hamcrest</span><span class="o">.</span><span class="na">Matchers</span><span class="o">.</span><span class="na">is</span><span class="o">;</span>
</span><span class='line'>
</span><span class='line'><span class="kn">import</span> <span class="nn">org.junit.Test</span><span class="o">;</span>
</span><span class='line'>
</span><span class='line'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">CustomerTest</span> <span class="o">{</span>
</span><span class='line'>
</span><span class='line'> <span class="kd">private</span> <span class="n">Customer</span> <span class="n">customer</span><span class="o">;</span>
</span><span class='line'>
</span><span class='line'> <span class="nd">@Test</span>
</span><span class='line'> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">returnsFalseWhenCustomerHasNoOrders</span><span class="o">()</span> <span class="o">{</span>
</span><span class='line'> <span class="n">customer</span> <span class="o">=</span> <span class="n">customer</span><span class="o">().</span><span class="na">title</span><span class="o">(</span><span class="s">"Mr"</span><span class="o">)</span>
</span><span class='line'> <span class="o">.</span><span class="na">firstName</span><span class="o">(</span><span class="s">"John"</span><span class="o">)</span>
</span><span class='line'> <span class="o">.</span><span class="na">lastName</span><span class="o">(</span><span class="s">"Smith"</span><span class="o">)</span>
</span><span class='line'> <span class="o">.</span><span class="na">build</span><span class="o">();</span>
</span><span class='line'> <span class="n">assertThat</span><span class="o">(</span><span class="n">customer</span><span class="o">.</span><span class="na">hasOrders</span><span class="o">(),</span> <span class="n">is</span><span class="o">(</span><span class="kc">false</span><span class="o">));</span>
</span><span class='line'> <span class="o">}</span>
</span><span class='line'><span class="o">}</span>
</span></code></pre></td></tr></table></div></figure>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Git: A Simple Workflow]]></title>
<link href="http://hkhan.github.com/blog/2011/11/26/git-a-simple-workflow/"/>
<updated>2011-11-26T23:41:00+00:00</updated>
<id>http://hkhan.github.com/blog/2011/11/26/git-a-simple-workflow</id>
<content type="html"><![CDATA[<p>This is a very simple yet effective workflow in small teams to encourage knowledge sharing and improve code quality. I have been using this lately and seems to be working very well. The following illustrates the workflow assuming the upstream remote named ‘origin’ on github.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c"># create and switch to a new feature branch</span>
</span><span class='line'>git checkout -b new-feature
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c"># do some work on the feature branch and commit locally</span>
</span><span class='line'>git commit -m <span class="s1">'Initial commit'</span>
</span><span class='line'>
</span><span class='line'><span class="c"># push the 'feature' branch to remote 'origin'</span>
</span><span class='line'>git push -u origin new-feature and <span class="nb">set </span>up tracking
</span></code></pre></td></tr></table></div></figure>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'>git commit -m <span class="s1">'Some more feature work'</span>
</span><span class='line'>
</span><span class='line'><span class="c"># push some more commited work to remote</span>
</span><span class='line'>git push new-feature
</span></code></pre></td></tr></table></div></figure>
<p>Once the feature has been completed, raise a <strong>pull request</strong> which will result in a notification to the team members to review and merge the feature code into the master branch.</p>
<p>After successful code review and merging, get <strong>Hubot</strong> to deploy the master branch, test the feature and have a cup of tea!</p>
]]></content>
</entry>
</feed>