Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a926ce6

Browse files
author
Ryan Neufeld
committed
Reflow and mildly re-organize resource-to-sequence recipe
1 parent de6eaf9 commit a926ce6

File tree

1 file changed

+44
-51
lines changed

1 file changed

+44
-51
lines changed

kitchen-sink/resource-to-sequence/resource-to-sequence.asciidoc

Lines changed: 44 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ by Gerrit Jansen van Vuuren
44

55
==== Problem
66

7-
You have a resource that you want to access as a sequence, but you do not want to keep a connection open and close it only when the whole sequence have been read
8-
thus potentially leaking the connection.
7+
You have a resource that you want to access as a sequence, but you do
8+
not want to keep a connection open and close it only when the whole
9+
sequence have been read thus potentially leaking the connection.
910

1011
==== Solution
1112

@@ -14,59 +15,45 @@ The solution is simple.
1415
1. A select function
1516
2. The initial position
1617

17-
The select function takes a single argument which is the last index position of data returned, and returns a snapshot of the data from the position
18-
to N amount of rows (here N is up to the function itself).
19-
20-
The initial position depends on the context that this pattern is used in, it can be 0, 1, 10 etc.
21-
18+
The select function takes a single argument which is the last index
19+
position of data returned, and returns a snapshot of the data from the
20+
position to N amount of rows (here N is up to the function itself).
2221

22+
The initial position depends on the context that this pattern is used
23+
in, it can be 0, 1, 10 etc.
2324

2425
[source,clojure]
2526
----
2627
(defn buffered-select [f-select init-pos]
27-
"Creates a lazy sequence of messages for this datasource"
28-
(letfn [
29-
(m-seq [buff pos]
30-
(if-let [buff2 (if (empty? buff) (f-select pos) buff)]
31-
(cons (first buff2) (lazy-seq (m-seq (rest buff2) (inc pos) )))))
32-
]
33-
(m-seq nil init-pos)))
28+
"Creates a lazy sequence from f-select"
29+
(letfn [(m-seq [buff pos]
30+
(if-let [buff2 (if (empty? buff) (f-select pos) buff)]
31+
(cons (first buff2) (lazy-seq (m-seq (rest buff2) (inc pos) )))))]
32+
(m-seq nil init-pos)))
3433
----
3534

36-
You can explore the usage of this recipe by going through a simple file reading example.
35+
You can explore the usage of this recipe by going through a simple
36+
file reading example.
3737

3838
[source,clojure]
3939
----
40-
(use 'clojure.pprint)
41-
4240
(defn load-example []
43-
"Methods that will build and read from a RandomAccessFile"
44-
(let [file "testfile.txt"
45-
get-bytes (fn [pos max]
46-
;reads the file from the line position pos
47-
(with-open [raf (java.io.RandomAccessFile. file "r")]
48-
(if (> pos 0) (.seek raf pos))
49-
(doall (take max (repeatedly #(.readByte raf))))))
50-
]
51-
52-
(with-open [writer (clojure.java.io/writer file)]
53-
(doseq [x (range 1000) ] (.write writer x)))
54-
{:file file :bytes get-bytes} ))
55-
56-
(defn buffered-select [f-select init-pos]
57-
"Creates a lazy sequence from f-select"
58-
(letfn [
59-
(m-seq [buff pos]
60-
(if-let [buff2 (if (empty? buff) (f-select pos) buff)]
61-
(cons (first buff2) (lazy-seq (m-seq (rest buff2) (inc pos) )))))
62-
]
63-
(m-seq nil init-pos)))
64-
41+
"Methods that will build and read from a RandomAccessFile"
42+
(let [file "testfile.txt"
43+
get-bytes (fn [pos max]
44+
;; reads the file from the line position pos
45+
(with-open [raf (java.io.RandomAccessFile. file "r")]
46+
(if (> pos 0) (.seek raf pos))
47+
(doall (take max (repeatedly #(.readByte raf))))))]
48+
(with-open [writer (clojure.java.io/writer file)]
49+
(doseq [x (range 1000)]
50+
(.write writer x)))
51+
{:file file :bytes get-bytes}))
6552
6653
(def db (load-example))
6754
68-
;;normally you'd make the max argument much bigger for performance reasons,
69-
;;here its set to 5 to show how connecting and querying is done.
55+
;; Normally you'd make the max argument much bigger for performance reasons,
56+
;; here its set to 5 to show how connecting and querying is done.
7057
(defn select [pos] ((:bytes db) pos 5 ) )
7158
7259
(def bts (buffered-select select 0))
@@ -78,13 +65,19 @@ You can explore the usage of this recipe by going through a simple file reading
7865

7966
==== Discussion
8067

81-
The solution showed is a simple pattern (monad) with simple constructs, and its usage applies directly to database queries and network io,
82-
and more generally to all resources that are accessed using a connection or resource interface (as shown in the example).
83-
84-
The select function connects (opens a file), queries (sees to the position and reads max amount of bytes) and closes a connection (closes the file), then returns a sequence.
85-
The sequence can then be consumed by the using code and after the buffer has been consumed the select function is called again. To the user of the function it appears as if the sequence is
86-
one huge sequence over which higher order functions like map filter partition can be applied.
87-
88-
The pattern also helps unroll the typical with-open pattern; where work must be done inside the scope of another function and cannot be pulled, to something more pull orientated and functional.
89-
90-
68+
The solution showed is a simple pattern (monad) with simple
69+
constructs, and its usage applies directly to database queries and
70+
network io, and more generally to all resources that are accessed
71+
using a connection or resource interface (as shown in the example).
72+
73+
The select function connects (opens a file), queries (sees to the
74+
position and reads max amount of bytes) and closes a connection
75+
(closes the file), then returns a sequence. The sequence can then be
76+
consumed by the using code and after the buffer has been consumed the
77+
select function is called again. To the user of the function it
78+
appears as if the sequence is one huge sequence over which higher
79+
order functions like map filter partition can be applied.
80+
81+
The pattern also helps unroll the typical with-open pattern; where
82+
work must be done inside the scope of another function and cannot be
83+
pulled, to something more pull orientated and functional.

0 commit comments

Comments
 (0)