├── answers
├── chapter01
│ └── 1_1.clj
├── chapter05
│ ├── 5_1.clj
│ └── 5_2.clj
├── chapter06
│ └── om-pm
│ │ ├── .gitignore
│ │ ├── LICENSE
│ │ ├── README.md
│ │ ├── dev-resources
│ │ ├── public
│ │ │ └── index.html
│ │ └── tools
│ │ │ ├── http
│ │ │ └── ring
│ │ │ │ └── server.clj
│ │ │ └── repl
│ │ │ └── brepl
│ │ │ └── connect.cljs
│ │ ├── doc
│ │ └── intro.md
│ │ ├── profiles.clj
│ │ ├── project.clj
│ │ └── src
│ │ └── cljs
│ │ └── om_pm
│ │ ├── core.cljs
│ │ └── util.cljs
└── chapter08
│ └── 8_1.clj
└── code
├── appendix-the-algebra-of-library-design
└── library-design
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ └── intro.md
│ ├── project.clj
│ ├── src
│ └── library_design
│ │ ├── core.clj
│ │ └── option.clj
│ └── test
│ └── library_design
│ └── core_test.clj
├── chapter01
├── calculator
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ │ └── intro.md
│ ├── project.clj
│ ├── src
│ │ └── calculator
│ │ │ └── core.clj
│ └── test
│ │ └── calculator
│ │ └── core_test.clj
└── sin-wave
│ ├── .gitignore
│ ├── LICENSE
│ ├── Procfile
│ ├── README.md
│ ├── env
│ ├── dev
│ │ └── cljs
│ │ │ └── sin_wave
│ │ │ └── dev.cljs
│ └── prod
│ │ └── cljs
│ │ └── sin_wave
│ │ └── prod.cljs
│ ├── project.clj
│ ├── resources
│ ├── index.html
│ └── public
│ │ └── css
│ │ └── style.css
│ ├── src
│ ├── clj
│ │ └── sin_wave
│ │ │ ├── dev.clj
│ │ │ └── server.clj
│ └── cljs
│ │ └── sin_wave
│ │ ├── core.cljs
│ │ └── repl.cljs
│ └── system.properties
├── chapter02
└── rx-playground
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ └── intro.md
│ ├── project.clj
│ ├── src
│ └── rx_playground
│ │ └── core.clj
│ └── test
│ └── rx_playground
│ └── core_test.clj
├── chapter03
└── stock-market-monitor
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ └── intro.md
│ ├── project.clj
│ ├── src
│ └── stock_market_monitor
│ │ ├── 01price_monitor.clj
│ │ ├── 02price_monitor_rolling_avg.clj
│ │ ├── 03frp_price_monitor.clj
│ │ ├── 04buffer.clj
│ │ └── 05frp_price_monitor_rolling_avg.clj
│ └── test
│ └── stock_market_monitor
│ └── core_test.clj
├── chapter04
├── core-async-playground
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ │ └── intro.md
│ ├── project.clj
│ ├── src
│ │ └── core_async_playground
│ │ │ ├── backpressure.clj
│ │ │ ├── core.clj
│ │ │ ├── error_handling.clj
│ │ │ └── stock_market.clj
│ └── test
│ │ └── core_async_playground
│ │ └── core_test.clj
├── core-async-transducers
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ │ └── intro.md
│ ├── project.clj
│ ├── src
│ │ └── core_async_transducers
│ │ │ └── core.clj
│ └── test
│ │ └── core_async_transducers
│ │ └── core_test.clj
└── repl.clj
├── chapter05
├── respondent-app
│ ├── .gitignore
│ ├── .nrepl-port
│ ├── LICENSE
│ ├── README.md
│ ├── dev-resources
│ │ ├── public
│ │ │ └── index.html
│ │ └── tools
│ │ │ ├── http
│ │ │ └── ring
│ │ │ │ └── server.clj
│ │ │ └── repl
│ │ │ └── brepl
│ │ │ └── connect.cljs
│ ├── doc
│ │ └── intro.md
│ ├── profiles.clj
│ ├── project.clj
│ ├── src
│ │ └── cljs
│ │ │ └── respondent_app
│ │ │ └── core.cljs
│ └── test
│ │ └── cljs
│ │ └── respondent_app
│ │ └── core_test.cljs
└── respondent
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ └── intro.md
│ ├── dotimes.perl
│ ├── hs_err_pid31450.log
│ ├── project.clj
│ ├── src
│ └── cljx
│ │ └── respondent
│ │ ├── core.cljx
│ │ └── repl.cljx
│ └── test
│ └── cljx
│ └── respondent
│ └── core_test.cljx
├── chapter06
└── reagi-game
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── dev-resources
│ ├── public
│ │ └── index.html
│ └── tools
│ │ ├── http
│ │ └── ring
│ │ │ └── server.clj
│ │ └── repl
│ │ └── brepl
│ │ └── connect.cljs
│ ├── doc
│ └── intro.md
│ ├── profiles.clj
│ ├── project.clj
│ ├── src
│ └── cljs
│ │ └── reagi_game
│ │ ├── core.cljs
│ │ ├── entities.cljs
│ │ └── util.cljs
│ └── test
│ └── cljs
│ └── reagi_game
│ └── core_test.cljs
├── chapter07
├── contacts
│ ├── .gitignore
│ ├── .nrepl-port
│ ├── LICENSE
│ ├── README.md
│ ├── dev-resources
│ │ ├── public
│ │ │ └── index.html
│ │ └── tools
│ │ │ ├── http
│ │ │ └── ring
│ │ │ │ └── server.clj
│ │ │ └── repl
│ │ │ └── brepl
│ │ │ └── connect.cljs
│ ├── doc
│ │ └── intro.md
│ ├── profiles.clj
│ ├── project.clj
│ └── src
│ │ └── cljs
│ │ └── contacts
│ │ └── core.cljs
├── om-pm
│ ├── .gitignore
│ ├── .repl
│ │ └── 76
│ │ │ ├── client.js
│ │ │ ├── cljs
│ │ │ ├── core.cljs
│ │ │ └── core.js
│ │ │ ├── clojure
│ │ │ └── browser
│ │ │ │ ├── event.cljs
│ │ │ │ ├── event.js
│ │ │ │ ├── net.cljs
│ │ │ │ ├── net.js
│ │ │ │ ├── repl.cljs
│ │ │ │ └── repl.js
│ │ │ └── om
│ │ │ ├── core.cljs
│ │ │ ├── core.js
│ │ │ ├── dom.cljs
│ │ │ └── dom.js
│ ├── LICENSE
│ ├── README.md
│ ├── dev-resources
│ │ ├── public
│ │ │ └── index.html
│ │ └── tools
│ │ │ ├── http
│ │ │ └── ring
│ │ │ │ └── server.clj
│ │ │ └── repl
│ │ │ └── brepl
│ │ │ └── connect.cljs
│ ├── doc
│ │ └── intro.md
│ ├── profiles.clj
│ ├── project.clj
│ └── src
│ │ └── cljs
│ │ └── om_pm
│ │ ├── core.cljs
│ │ └── util.cljs
└── scratch.clj
├── chapter08
├── clj-futures-playground
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ │ └── intro.md
│ ├── project.clj
│ ├── src
│ │ └── clj_futures_playground
│ │ │ └── core.clj
│ └── test
│ │ └── clj_futures_playground
│ │ └── core_test.clj
├── examples.clj
└── imminent-playground
│ ├── .gitignore
│ ├── LICENSE
│ ├── README.md
│ ├── doc
│ └── intro.md
│ ├── project.clj
│ ├── src
│ └── imminent_playground
│ │ ├── core.clj
│ │ └── repl.clj
│ └── test
│ └── imminent_playground
│ └── core_test.clj
└── chapter09
├── aws-api-stub
├── .gitignore
├── README.md
├── project.clj
├── src
│ └── aws_api_stub
│ │ ├── aws.clj
│ │ └── core
│ │ └── handler.clj
└── test
│ └── aws_api_stub
│ └── core
│ └── handler_test.clj
└── aws-dash
├── .gitignore
├── LICENSE
├── README.md
├── dev-resources
├── public
│ └── index.html
└── tools
│ ├── http
│ └── ring
│ │ └── server.clj
│ └── repl
│ └── brepl
│ └── connect.cljs
├── doc
└── intro.md
├── profiles.clj
├── project.clj
└── src
└── cljs
└── aws_dash
├── core.cljs
└── observables.cljs
/answers/chapter01/1_1.clj:
--------------------------------------------------------------------------------
1 | ;; Exercise 1.1
2 |
3 | (def repeat js/Rx.Observable.repeat)
4 | (def rainbow-colours (-> (.scan time
5 | (cycle ["red"
6 | "orange"
7 | "yellow"
8 | "green"
9 | "blue"
10 | "indigo"
11 | "violet"])
12 | (fn [acc _] (next acc)))
13 | (.map #(first %))
14 | (.flatMap #(repeat % 20))))
15 |
16 |
17 |
18 |
19 |
20 |
21 | (-> (.zip sine-wave rainbow-colours #(vector % %2))
22 | (.take 600)
23 | (.subscribe (fn [[{:keys [x y]} colour]]
24 | (fill-rect x y colour))))
25 |
--------------------------------------------------------------------------------
/answers/chapter05/5_1.clj:
--------------------------------------------------------------------------------
1 | ;; Exercise 5.1
2 |
3 | (defn take [es1 n]
4 | (let [count (atom 0)
5 | out-es (event-stream (chan n))
6 | dispose-token nil
7 | token (subscribe es1
8 | (fn [item]
9 | (if (< @count n)
10 | (do (deliver out-es item)
11 | (swap! count inc))
12 | (deliver out-es ::complete))))]
13 | (add-watch count :token (fn [_ _ _ new-state]
14 | (when (>= new-state n)
15 | (dispose token))))
16 |
17 | out-es))
18 |
19 | (def es1 (from-interval 500))
20 | (def take-es (take es1 5))
21 |
22 | (subscribe take-es #(prn "Take values: " %))
23 |
24 | ;; "Take values: " 0
25 | ;; "Take values: " 1
26 | ;; "Take values: " 2
27 | ;; "Take values: " 3
28 | ;; "Take values: " 4
29 |
--------------------------------------------------------------------------------
/answers/chapter05/5_2.clj:
--------------------------------------------------------------------------------
1 | ;; Exercise 5.2
2 |
3 | (defn zip [es1 es2]
4 | (let [out-vec (ref [nil nil])
5 | out-es (event-stream)
6 | emit-if-done! (fn []
7 | (let [vec @out-vec]
8 | (when (every? (comp not nil?) vec)
9 | (deliver out-es vec)
10 | (ref-set out-vec [nil nil]))))
11 |
12 | (subscribe es1
13 | (fn [item]
14 | (dosync
15 | (alter out-vec (fn [[_ b]]
16 | [item b]))
17 | (emit-if-done!))))
18 | (subscribe es2
19 | (fn [item]
20 | (dosync
21 | (alter out-vec (fn [[a _]]
22 | [a item]))
23 | (emit-if-done!))))]
24 |
25 | out-es))
26 |
27 | (def es1 (from-interval 500))
28 | (def es2 (map (from-interval 500) #(* % 2)))
29 | (def zipped (zip es1 es2))
30 |
31 | (def token (subscribe zipped #(prn "Zipped values: " %)))
32 |
33 | ;; "Zipped values: " [0 0]
34 | ;; "Zipped values: " [1 2]
35 | ;; "Zipped values: " [2 4]
36 | ;; "Zipped values: " [3 6]
37 | ;; "Zipped values: " [4 8]
38 |
39 | (dispose token)
40 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/.gitignore:
--------------------------------------------------------------------------------
1 | pom.xml
2 | *jar
3 | /lib/
4 | /classes/
5 | /out/
6 | /target/
7 | .repl
8 | .lein-deps-sum
9 | .lein-repl-history
10 | .lein-plugins/
11 | /dev-resources/public/js/*
12 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/LICENSE:
--------------------------------------------------------------------------------
1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
4 |
5 | 1. DEFINITIONS
6 |
7 | "Contribution" means:
8 |
9 | a) in the case of the initial Contributor, the initial code and
10 | documentation distributed under this Agreement, and
11 |
12 | b) in the case of each subsequent Contributor:
13 |
14 | i) changes to the Program, and
15 |
16 | ii) additions to the Program;
17 |
18 | where such changes and/or additions to the Program originate from and are
19 | distributed by that particular Contributor. A Contribution 'originates' from
20 | a Contributor if it was added to the Program by such Contributor itself or
21 | anyone acting on such Contributor's behalf. Contributions do not include
22 | additions to the Program which: (i) are separate modules of software
23 | distributed in conjunction with the Program under their own license
24 | agreement, and (ii) are not derivative works of the Program.
25 |
26 | "Contributor" means any person or entity that distributes the Program.
27 |
28 | "Licensed Patents" mean patent claims licensable by a Contributor which are
29 | necessarily infringed by the use or sale of its Contribution alone or when
30 | combined with the Program.
31 |
32 | "Program" means the Contributions distributed in accordance with this
33 | Agreement.
34 |
35 | "Recipient" means anyone who receives the Program under this Agreement,
36 | including all Contributors.
37 |
38 | 2. GRANT OF RIGHTS
39 |
40 | a) Subject to the terms of this Agreement, each Contributor hereby grants
41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
42 | reproduce, prepare derivative works of, publicly display, publicly perform,
43 | distribute and sublicense the Contribution of such Contributor, if any, and
44 | such derivative works, in source code and object code form.
45 |
46 | b) Subject to the terms of this Agreement, each Contributor hereby grants
47 | Recipient a non-exclusive, worldwide, royalty-free patent license under
48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise
49 | transfer the Contribution of such Contributor, if any, in source code and
50 | object code form. This patent license shall apply to the combination of the
51 | Contribution and the Program if, at the time the Contribution is added by the
52 | Contributor, such addition of the Contribution causes such combination to be
53 | covered by the Licensed Patents. The patent license shall not apply to any
54 | other combinations which include the Contribution. No hardware per se is
55 | licensed hereunder.
56 |
57 | c) Recipient understands that although each Contributor grants the licenses
58 | to its Contributions set forth herein, no assurances are provided by any
59 | Contributor that the Program does not infringe the patent or other
60 | intellectual property rights of any other entity. Each Contributor disclaims
61 | any liability to Recipient for claims brought by any other entity based on
62 | infringement of intellectual property rights or otherwise. As a condition to
63 | exercising the rights and licenses granted hereunder, each Recipient hereby
64 | assumes sole responsibility to secure any other intellectual property rights
65 | needed, if any. For example, if a third party patent license is required to
66 | allow Recipient to distribute the Program, it is Recipient's responsibility
67 | to acquire that license before distributing the Program.
68 |
69 | d) Each Contributor represents that to its knowledge it has sufficient
70 | copyright rights in its Contribution, if any, to grant the copyright license
71 | set forth in this Agreement.
72 |
73 | 3. REQUIREMENTS
74 |
75 | A Contributor may choose to distribute the Program in object code form under
76 | its own license agreement, provided that:
77 |
78 | a) it complies with the terms and conditions of this Agreement; and
79 |
80 | b) its license agreement:
81 |
82 | i) effectively disclaims on behalf of all Contributors all warranties and
83 | conditions, express and implied, including warranties or conditions of title
84 | and non-infringement, and implied warranties or conditions of merchantability
85 | and fitness for a particular purpose;
86 |
87 | ii) effectively excludes on behalf of all Contributors all liability for
88 | damages, including direct, indirect, special, incidental and consequential
89 | damages, such as lost profits;
90 |
91 | iii) states that any provisions which differ from this Agreement are offered
92 | by that Contributor alone and not by any other party; and
93 |
94 | iv) states that source code for the Program is available from such
95 | Contributor, and informs licensees how to obtain it in a reasonable manner on
96 | or through a medium customarily used for software exchange.
97 |
98 | When the Program is made available in source code form:
99 |
100 | a) it must be made available under this Agreement; and
101 |
102 | b) a copy of this Agreement must be included with each copy of the Program.
103 |
104 | Contributors may not remove or alter any copyright notices contained within
105 | the Program.
106 |
107 | Each Contributor must identify itself as the originator of its Contribution,
108 | if any, in a manner that reasonably allows subsequent Recipients to identify
109 | the originator of the Contribution.
110 |
111 | 4. COMMERCIAL DISTRIBUTION
112 |
113 | Commercial distributors of software may accept certain responsibilities with
114 | respect to end users, business partners and the like. While this license is
115 | intended to facilitate the commercial use of the Program, the Contributor who
116 | includes the Program in a commercial product offering should do so in a
117 | manner which does not create potential liability for other Contributors.
118 | Therefore, if a Contributor includes the Program in a commercial product
119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend
120 | and indemnify every other Contributor ("Indemnified Contributor") against any
121 | losses, damages and costs (collectively "Losses") arising from claims,
122 | lawsuits and other legal actions brought by a third party against the
123 | Indemnified Contributor to the extent caused by the acts or omissions of such
124 | Commercial Contributor in connection with its distribution of the Program in
125 | a commercial product offering. The obligations in this section do not apply
126 | to any claims or Losses relating to any actual or alleged intellectual
127 | property infringement. In order to qualify, an Indemnified Contributor must:
128 | a) promptly notify the Commercial Contributor in writing of such claim, and
129 | b) allow the Commercial Contributor tocontrol, and cooperate with the
130 | Commercial Contributor in, the defense and any related settlement
131 | negotiations. The Indemnified Contributor may participate in any such claim
132 | at its own expense.
133 |
134 | For example, a Contributor might include the Program in a commercial product
135 | offering, Product X. That Contributor is then a Commercial Contributor. If
136 | that Commercial Contributor then makes performance claims, or offers
137 | warranties related to Product X, those performance claims and warranties are
138 | such Commercial Contributor's responsibility alone. Under this section, the
139 | Commercial Contributor would have to defend claims against the other
140 | Contributors related to those performance claims and warranties, and if a
141 | court requires any other Contributor to pay any damages as a result, the
142 | Commercial Contributor must pay those damages.
143 |
144 | 5. NO WARRANTY
145 |
146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON
147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the
151 | appropriateness of using and distributing the Program and assumes all risks
152 | associated with its exercise of rights under this Agreement , including but
153 | not limited to the risks and costs of program errors, compliance with
154 | applicable laws, damage to or loss of data, programs or equipment, and
155 | unavailability or interruption of operations.
156 |
157 | 6. DISCLAIMER OF LIABILITY
158 |
159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
166 | OF SUCH DAMAGES.
167 |
168 | 7. GENERAL
169 |
170 | If any provision of this Agreement is invalid or unenforceable under
171 | applicable law, it shall not affect the validity or enforceability of the
172 | remainder of the terms of this Agreement, and without further action by the
173 | parties hereto, such provision shall be reformed to the minimum extent
174 | necessary to make such provision valid and enforceable.
175 |
176 | If Recipient institutes patent litigation against any entity (including a
177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself
178 | (excluding combinations of the Program with other software or hardware)
179 | infringes such Recipient's patent(s), then such Recipient's rights granted
180 | under Section 2(b) shall terminate as of the date such litigation is filed.
181 |
182 | All Recipient's rights under this Agreement shall terminate if it fails to
183 | comply with any of the material terms or conditions of this Agreement and
184 | does not cure such failure in a reasonable period of time after becoming
185 | aware of such noncompliance. If all Recipient's rights under this Agreement
186 | terminate, Recipient agrees to cease use and distribution of the Program as
187 | soon as reasonably practicable. However, Recipient's obligations under this
188 | Agreement and any licenses granted by Recipient relating to the Program shall
189 | continue and survive.
190 |
191 | Everyone is permitted to copy and distribute copies of this Agreement, but in
192 | order to avoid inconsistency the Agreement is copyrighted and may only be
193 | modified in the following manner. The Agreement Steward reserves the right to
194 | publish new versions (including revisions) of this Agreement from time to
195 | time. No one other than the Agreement Steward has the right to modify this
196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The
197 | Eclipse Foundation may assign the responsibility to serve as the Agreement
198 | Steward to a suitable separate entity. Each new version of the Agreement will
199 | be given a distinguishing version number. The Program (including
200 | Contributions) may always be distributed subject to the version of the
201 | Agreement under which it was received. In addition, after a new version of
202 | the Agreement is published, Contributor may elect to distribute the Program
203 | (including its Contributions) under the new version. Except as expressly
204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
205 | licenses to the intellectual property of any Contributor under this
206 | Agreement, whether expressly, by implication, estoppel or otherwise. All
207 | rights in the Program not expressly granted under this Agreement are
208 | reserved.
209 |
210 | This Agreement is governed by the laws of the State of Washington and the
211 | intellectual property laws of the United States of America. No party to this
212 | Agreement will bring a legal action under this Agreement more than one year
213 | after the cause of action arose. Each party waives its rights to a jury trial
214 | in any resulting litigation.
215 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/README.md:
--------------------------------------------------------------------------------
1 | # om-pm
2 |
3 | An OM project designed to ... well, that part is up to you.
4 |
5 | ## Usage
6 |
7 | FIXME
8 |
9 | ## License
10 |
11 | Copyright © 2014 FIXME
12 |
13 | Distributed under the Eclipse Public License either version 1.0 or (at
14 | your option) any later version.
15 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/dev-resources/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/dev-resources/tools/http/ring/server.clj:
--------------------------------------------------------------------------------
1 | ;;; This namespace is used for development and testing purpose only.
2 | (ns ring.server
3 | (:require [cemerick.austin.repls :refer (browser-connected-repl-js)]
4 | [net.cgrand.enlive-html :as enlive]
5 | [compojure.route :refer (resources)]
6 | [compojure.core :refer (GET defroutes)]
7 | [ring.adapter.jetty :as jetty]
8 | [clojure.java.io :as io]))
9 |
10 | (enlive/deftemplate page
11 | (io/resource "public/index.html")
12 | []
13 | [:body] (enlive/append
14 | (enlive/html [:script (browser-connected-repl-js)])))
15 |
16 | (defroutes site
17 | (resources "/")
18 | (GET "/*" req (page)))
19 |
20 | (defn run
21 | "Run the ring server. It defines the server symbol with defonce."
22 | []
23 | (defonce server
24 | (jetty/run-jetty #'site {:port 3000 :join? false}))
25 | server)
26 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/dev-resources/tools/repl/brepl/connect.cljs:
--------------------------------------------------------------------------------
1 | (ns brepl.connect
2 | (:require [clojure.browser.repl]))
3 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/doc/intro.md:
--------------------------------------------------------------------------------
1 | # Introduction to om-pm
2 |
3 | TODO: write [great documentation](http://jacobian.org/writing/great-documentation/what-to-write/)
4 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/profiles.clj:
--------------------------------------------------------------------------------
1 | {:shared {:clean-targets ["out" :target-path]}
2 |
3 | :tdd [:shared
4 | {:cljsbuild
5 | {:builds {:om-pm
6 | {:compiler
7 | {:optimizations :whitespace
8 | :pretty-print true}}}}}]
9 |
10 | :dev [:shared
11 | {:resources-paths ["dev-resources"]
12 | :source-paths ["dev-resources/tools/http" "dev-resources/tools/repl"]
13 | :dependencies [[ring "1.2.1"]
14 | [compojure "1.1.6"]
15 | [enlive "1.1.5"]]
16 | :plugins [[com.cemerick/austin "0.1.3"]]
17 | :cljsbuild
18 | {:builds {:om-pm
19 | {:source-paths ["dev-resources/tools/repl"]
20 | :compiler
21 | {:optimizations :whitespace
22 | :pretty-print true}}}}
23 |
24 | :injections [(require '[ring.server :as http :refer [run]]
25 | 'cemerick.austin.repls)
26 | (defn browser-repl-env []
27 | (reset! cemerick.austin.repls/browser-repl-env
28 | (cemerick.austin/repl-env)))
29 | (defn browser-repl []
30 | (cemerick.austin.repls/cljs-repl
31 | (browser-repl-env)))]}]}
32 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/project.clj:
--------------------------------------------------------------------------------
1 | (defproject om-pm "0.0.1-SNAPSHOT"
2 | :description "FIXME: write description"
3 | :url "http://example.com/FIXME"
4 | :license {:name "Eclipse Public License - v 1.0"
5 | :url "http://www.eclipse.org/legal/epl-v10.html"
6 | :distribution :repo}
7 |
8 | :min-lein-version "2.3.4"
9 |
10 | :source-paths ["src/clj" "src/cljs"]
11 |
12 | :dependencies [[org.clojure/clojure "1.6.0"]
13 | [org.clojure/clojurescript "0.0-2511"]
14 | [org.om/om "0.8.1"]
15 | [org.clojure/core.async "0.1.346.0-17112a-alpha"]
16 | [com.facebook/react "0.12.2"]]
17 |
18 | :plugins [[lein-cljsbuild "1.0.3"]]
19 |
20 | :hooks [leiningen.cljsbuild]
21 |
22 | :cljsbuild
23 | {:builds {:om-pm
24 | {:source-paths ["src/cljs"]
25 | :compiler
26 | {:output-to "dev-resources/public/js/om_pm.js"
27 | :optimizations :advanced
28 | :pretty-print false}}}})
29 |
--------------------------------------------------------------------------------
/answers/chapter06/om-pm/src/cljs/om_pm/core.cljs:
--------------------------------------------------------------------------------
1 | (ns om-pm.core
2 | (:require [om.core :as om :include-macros true]
3 | [om.dom :as dom :include-macros true]
4 | [cljs.core.async :refer [put! chan e .-nativeEvent .-dataTransfer)
5 | key value))
6 |
7 | (defn get-transfer-data! [e key]
8 | (-> (-> e .-nativeEvent .-dataTransfer)
9 | (.getData key)))
10 |
11 | (defn column-idx [title columns]
12 | (first (keep-indexed (fn [idx column]
13 | (when (= title (:title column))
14 | idx))
15 | columns)))
16 |
17 | (defn move-card! [columns {:keys [card-id source-column destination-column]}]
18 | (let [from (column-idx source-column columns)
19 | to (column-idx destination-column columns)]
20 | (-> columns
21 | (update-in [from :cards] (fn [cards]
22 | (remove #{card-id} cards)))
23 | (update-in [to :cards] (fn [cards]
24 | (conj cards card-id))))))
25 |
26 | (defn card-seq [columns]
27 | (mapcat (fn [{:keys [title cards]}]
28 | (map vector cards (repeat title))) columns))
29 |
30 | (def first-card (comp first card-seq))
31 |
32 | (defn next-sibling [pred coll]
33 | (first (drop 1 (drop-while pred coll))))
34 |
35 | (defn previous-sibling [pred coll]
36 | (last (take-while pred coll)))
37 |
38 | (defn next-down [id cards]
39 | (if-let [card (next-sibling (fn [[id' column']]
40 | (not= id' id)) cards)]
41 | card
42 | []))
43 |
44 | (defn next-up [id cards]
45 | (if-let [card (previous-sibling (fn [[id' column']]
46 | (not= id' id)) cards)]
47 | card
48 | []))
49 |
50 | (defn next-column [title columns]
51 | (next-sibling #(not= % title) (map :title columns)))
52 |
53 | (defn previous-column [title columns]
54 | (previous-sibling #(not= % title) (map :title columns)))
55 |
--------------------------------------------------------------------------------
/answers/chapter08/8_1.clj:
--------------------------------------------------------------------------------
1 | ;; Exercise 8.1
2 |
3 | (defn resouces-stream [_]
4 | (let [resources (obs/stack-resources)]
5 | (-> (.merge (obs/rds-instance-status resources)
6 | (obs/ec2-instance-status resources))
7 | (.reduce conj []))))
8 |
9 | (.subscribe (.flatMap (.interval js/Rx.Observable 100)
10 | resources-stream)
11 | #(swap! app-state assoc :instances %))
12 |
--------------------------------------------------------------------------------
/code/appendix-the-algebra-of-library-design/library-design/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /classes
3 | /checkouts
4 | pom.xml
5 | pom.xml.asc
6 | *.jar
7 | *.class
8 | /.lein-*
9 | /.nrepl-port
10 |
--------------------------------------------------------------------------------
/code/appendix-the-algebra-of-library-design/library-design/README.md:
--------------------------------------------------------------------------------
1 | # library-design
2 |
3 | A Clojure library designed to ... well, that part is up to you.
4 |
5 | ## Usage
6 |
7 | FIXME
8 |
9 | ## License
10 |
11 | Copyright © 2014 FIXME
12 |
13 | Distributed under the Eclipse Public License either version 1.0 or (at
14 | your option) any later version.
15 |
--------------------------------------------------------------------------------
/code/appendix-the-algebra-of-library-design/library-design/doc/intro.md:
--------------------------------------------------------------------------------
1 | # Introduction to library-design
2 |
3 | TODO: write [great documentation](http://jacobian.org/writing/what-to-write/)
4 |
--------------------------------------------------------------------------------
/code/appendix-the-algebra-of-library-design/library-design/project.clj:
--------------------------------------------------------------------------------
1 | (defproject library-design "0.1.0-SNAPSHOT"
2 | :description "FIXME: write description"
3 | :url "http://example.com/FIXME"
4 | :license {:name "Eclipse Public License"
5 | :url "http://www.eclipse.org/legal/epl-v10.html"}
6 | :dependencies [[org.clojure/clojure "1.6.0"]
7 | [com.leonardoborges/imminent "0.1.0"]
8 | [com.netflix.rxjava/rxjava-clojure "0.20.7"]
9 | [org.clojure/core.async "0.1.346.0-17112a-alpha"]
10 | [uncomplicate/fluokitten "0.3.0"]])
11 |
--------------------------------------------------------------------------------
/code/appendix-the-algebra-of-library-design/library-design/src/library_design/core.clj:
--------------------------------------------------------------------------------
1 | (ns library-design.core
2 | (:require [imminent.core :as i]
3 | [rx.lang.clojure.core :as rx]
4 | [clojure.core.async :as async]))
5 |
6 |
7 | (def repl-out *out*)
8 | (defn prn-to-repl [& args]
9 | (binding [*out* repl-out]
10 | (apply prn args)))
11 |
12 | (-> (i/const-future 31)
13 | (i/map #(* % 2))
14 | (i/on-success #(prn-to-repl (str "Value: " %))))
15 |
16 |
17 | (as-> (rx/return 31) obs
18 | (rx/map #(* % 2) obs)
19 | (rx/subscribe obs #(prn-to-repl (str "Value: " %))))
20 |
21 | (def c (async/chan))
22 | (def mapped-c (async/map< #(* % 2) c))
23 |
24 | (async/go (async/>! c 31))
25 | (async/go (prn-to-repl (str "Value: " (async/> pirates
18 | (filter #(= name (:name %)))
19 | first))
20 |
21 | (defn age [{:keys [born died]}]
22 | (- died born))
23 |
24 | (comment
25 |
26 | (-> (pirate-by-name "Jack Sparrow")
27 | age) ;; 40
28 |
29 | (-> (pirate-by-name "Davy Jones")
30 | age) ;; NullPointerException clojure.lang.Numbers.ops (Numbers.java:961)
31 |
32 |
33 |
34 |
35 | )
36 |
37 | (defrecord Some [v])
38 |
39 | (defrecord None [])
40 |
41 |
42 | (defn option [v]
43 | (if v
44 | (Some. v)
45 | (None.)))
46 |
47 |
48 | (comment
49 |
50 |
51 | ;; delete me
52 | (defprotocol Functor
53 |
54 | (fmap [fv g] ))
55 | ;; laws
56 |
57 |
58 | )
59 |
60 |
61 |
62 |
63 | (extend-protocol fkp/Functor
64 | Some
65 | (fmap [f g]
66 | (Some. (g (:v f))))
67 | None
68 | (fmap [_ _]
69 | (None.)))
70 |
71 |
72 | (->> (option (pirate-by-name "Jack Sparrow"))
73 | (fkc/fmap age)) ;; #library_design.option.Some{:v 40}
74 |
75 | (->> (option (pirate-by-name "Davy Jones"))
76 | (fkc/fmap age)) ;; #library_design.option.None{}
77 |
78 |
79 | (->> (option (pirate-by-name "Jack Sparrow"))
80 | (fkc/fmap age)
81 | (fkc/fmap inc)
82 | (fkc/fmap #(* 2 %))) ;; #library_design.option.Some{:v 82}
83 |
84 | (->> (option (pirate-by-name "Davy Jones"))
85 | (fkc/fmap age)
86 | (fkc/fmap inc)
87 | (fkc/fmap #(* 2 %))) ;; #library_design.option.None{}
88 |
89 |
90 |
91 | (some-> (pirate-by-name "Davy Jones")
92 | age
93 | inc
94 | (* 2)) ;; nil
95 |
96 |
97 | (->> (i/future (pirate-by-name "Jack Sparrow"))
98 | (fkc/fmap age)
99 | (fkc/fmap inc)
100 | (fkc/fmap #(* 2 %))) ;; #>
101 |
102 |
103 | ;; Functor laws
104 |
105 | ;; Identity
106 | (= (fkc/fmap identity (option 1))
107 | (identity (option 1))) ;; true
108 |
109 |
110 | ;; Composition
111 | (= (fkc/fmap (comp identity inc) (option 1))
112 | (fkc/fmap identity (fkc/fmap inc (option 1)))) ;; true
113 |
114 |
115 | (def repl-out *out*)
116 | (defn prn-to-repl [& args]
117 | (binding [*out* repl-out]
118 | (apply prn args)))
119 |
120 |
121 | ;;
122 | ;; Applicative
123 | ;;
124 |
125 | (defn avg [& xs]
126 | (float (/ (apply + xs) (count xs))))
127 |
128 | (comment
129 |
130 |
131 |
132 | (let [a (some-> (pirate-by-name "Jack Sparrow") age)
133 | b (some-> (pirate-by-name "Blackbeard") age)
134 | c (some-> (pirate-by-name "Hector Barbossa") age)]
135 | (avg a b c)) ;; 56.666668
136 |
137 | (let [a (some-> (pirate-by-name "Jack Sparrow") age)
138 | b (some-> (pirate-by-name "Davy Jones") age)
139 | c (some-> (pirate-by-name "Hector Barbossa") age)]
140 | (avg a b c)) ;; NullPointerException clojure.lang.Numbers.ops (Numbers.java:961)
141 |
142 | (let [a (some-> (pirate-by-name "Jack Sparrow") age)
143 | b (some-> (pirate-by-name "Davy Jones") age)
144 | c (some-> (pirate-by-name "Hector Barbossa") age)]
145 | (when (and a b c)
146 | (avg a b c))) ;; nil
147 |
148 | )
149 |
150 |
151 | (extend-protocol fkp/Applicative
152 | Some
153 | (pure [_ v]
154 | (Some. v))
155 |
156 | (fapply [ag av]
157 | (if-let [v (:v av)]
158 | (Some. ((:v ag) v))
159 | (None.)))
160 |
161 | None
162 | (pure [_ v]
163 | (Some. v))
164 |
165 | (fapply [ag av]
166 | (None.)))
167 |
168 |
169 | (fkc/fapply (option inc) (option 2))
170 | ;; #library_design.option.Some{:v 3}
171 |
172 | (fkc/fapply (option nil) (option 2))
173 | ;; #library_design.option.None{}
174 |
175 | (def age-option (comp (partial fkc/fmap age) option pirate-by-name))
176 |
177 | (let [a (age-option "Jack Sparrow")
178 | b (age-option "Blackbeard")
179 | c (age-option "Hector Barbossa")]
180 | (fkc/<*> (option (fkj/curry avg 3))
181 | a b c))
182 | ;; #library_design.option.Some{:v 56.666668}
183 |
184 | (defn alift
185 | "Lifts a n-ary function `f` into a applicative context"
186 | [f]
187 | (fn [& as]
188 | {:pre [(seq as)]}
189 | (let [curried (fkj/curry f (count as))]
190 | (apply fkc/<*>
191 | (fkc/fmap curried (first as))
192 | (rest as)))))
193 |
194 |
195 | (let [a (age-option "Jack Sparrow")
196 | b (age-option "Blackbeard")
197 | c (age-option "Hector Barbossa")]
198 | ((alift avg) a b c))
199 | ;; #library_design.option.Some{:v 56.666668}
200 |
201 | ((alift avg) (age-option "Jack Sparrow")
202 | (age-option "Blackbeard")
203 | (age-option "Hector Barbossa"))
204 | ;; #library_design.option.Some{:v 56.666668}
205 |
206 | ((alift avg) (age-option "Jack Sparrow")
207 | (age-option "Davy Jones")
208 | (age-option "Hector Barbossa"))
209 | ;; #library_design.option.None{}
210 |
211 |
212 |
213 | ((alift avg) (i/future (some-> (pirate-by-name "Jack Sparrow") age))
214 | (i/future (some-> (pirate-by-name "Blackbeard") age))
215 | (i/future (some-> (pirate-by-name "Hector Barbossa") age)))
216 | ;; #>
217 |
218 | (->> (i/future (pirate-by-name "Jack Sparrow"))
219 | (fkc/fmap age)
220 | (fkc/fmap inc)
221 | (fkc/fmap #(* 2 %)))
222 |
223 |
224 | ;;
225 | ;; Monad
226 | ;;
227 |
228 | (defn median [& ns]
229 | (let [ns (sort ns)
230 | cnt (count ns)
231 | mid (bit-shift-right cnt 1)]
232 | (if (odd? cnt)
233 | (nth ns mid)
234 | (/ (+ (nth ns mid) (nth ns (dec mid))) 2))))
235 |
236 | (defn std-dev [& samples]
237 | (let [n (count samples)
238 | mean (/ (reduce + samples) n)
239 | intermediate (map #(Math/pow (- %1 mean) 2) samples)]
240 | (Math/sqrt
241 | (/ (reduce + intermediate) n))))
242 |
243 |
244 | (comment
245 |
246 | (let [a (some-> (pirate-by-name "Jack Sparrow") age)
247 | b (some-> (pirate-by-name "Blackbeard") age)
248 | c (some-> (pirate-by-name "Hector Barbossa") age)
249 | avg (avg a b c)
250 | median (median a b c)
251 | std-dev (std-dev a b c)]
252 | {:avg avg
253 | :median median
254 | :std-dev std-dev})
255 | ;; {:avg 56.666668,
256 | ;; :median 60,
257 | ;; :std-dev 12.472191289246473}
258 |
259 |
260 | (let [a (some-> (pirate-by-name "Jack Sparrow") age)
261 | b (some-> (pirate-by-name "Davy Jones") age)
262 | c (some-> (pirate-by-name "Hector Barbossa") age)
263 | avg (avg a b c)
264 | median (median a b c)
265 | std-dev (std-dev a b c)]
266 | {:avg avg
267 | :median median
268 | :std-dev std-dev})
269 | ;; NullPointerException clojure.lang.Numbers.ops (Numbers.java:961)
270 |
271 | (let [a (some-> (pirate-by-name "Jack Sparrow") age)
272 | b (some-> (pirate-by-name "Davy Jones") age)
273 | c (some-> (pirate-by-name "Hector Barbossa") age)
274 | avg (when (and a b c) (avg a b c))
275 | median (when (and a b c) (median a b c))
276 | std-dev (when (and a b c) (std-dev a b c))]
277 | (when (and a b c)
278 | {:avg avg
279 | :median median
280 | :std-dev std-dev}))
281 | ;; nil
282 |
283 |
284 | )
285 |
286 |
287 | (extend-protocol fkp/Monad
288 | Some
289 | (bind [mv g]
290 | (g (:v mv)))
291 |
292 | None
293 | (bind [_ _]
294 | (None.)))
295 |
296 |
297 |
298 | ;; (fkc/bind (None.) identity)
299 |
300 | (def opt-ctx (None.))
301 |
302 | (fkc/bind (age-option "Jack Sparrow")
303 | (fn [a]
304 | (fkc/bind (age-option "Blackbeard")
305 | (fn [b]
306 | (fkc/bind (age-option "Hector Barbossa")
307 | (fn [c]
308 | (fkc/pure opt-ctx
309 | (+ a b c))))))))
310 | ;; #library_design.option.Some{:v 170.0}
311 |
312 | (fkc/mdo [a (age-option "Jack Sparrow")
313 | b (age-option "Blackbeard")
314 | c (age-option "Hector Barbossa")]
315 | (fkc/pure opt-ctx (+ a b c)))
316 | ;; #library_design.option.Some{:v 170.0}
317 |
318 | (require '[clojure.walk :as w])
319 |
320 | (w/macroexpand-all '(fkc/mdo [a (age-option "Jack Sparrow")
321 | b (age-option "Blackbeard")
322 | c (age-option "Hector Barbossa")]
323 | (fkc/pure opt-ctx (+ a b c))))
324 |
325 | ;; (uncomplicate.fluokitten.core/bind
326 | ;; (age-option "Jack Sparrow")
327 | ;; (fn*
328 | ;; ([a]
329 | ;; (uncomplicate.fluokitten.core/bind
330 | ;; (age-option "Blackbeard")
331 | ;; (fn*
332 | ;; ([b]
333 | ;; (uncomplicate.fluokitten.core/bind
334 | ;; (age-option "Hector Barbossa")
335 | ;; (fn* ([c] (fkc/pure opt-ctx (+ a b c)))))))))))
336 |
337 |
338 | (def avg-opt (comp option avg))
339 | (def median-opt (comp option median))
340 | (def std-dev-opt (comp option std-dev))
341 |
342 | (fkc/mdo [a (age-option "Jack Sparrow")
343 | b (age-option "Blackbeard")
344 | c (age-option "Hector Barbossa")
345 | avg (avg-opt a b c)
346 | median (median-opt a b c)
347 | std-dev (std-dev-opt a b c)]
348 | (fkc/pure opt-ctx {:avg avg
349 | :median median
350 | :std-dev std-dev}))
351 | ;; #library_design.option.Some{:v {:avg 56.666668,
352 | ;; :median 60,
353 | ;; :std-dev 12.472191289246473}}
354 |
355 | (fkc/mdo [a (age-option "Jack Sparrow")
356 | b (age-option "Davy Jones")
357 | c (age-option "Hector Barbossa")
358 | avg (avg-opt a b c)
359 | median (median-opt a b c)
360 | std-dev (std-dev-opt a b c)]
361 | (fkc/pure opt-ctx {:avg avg
362 | :median median
363 | :std-dev std-dev}))
364 | ;; #library_design.option.None{}
365 |
366 | (def avg-fut (comp i/future-call avg))
367 | (def median-fut (comp i/future-call median))
368 | (def std-dev-fut (comp i/future-call std-dev))
369 |
370 | (fkc/mdo [a (i/future (some-> (pirate-by-name "Jack Sparrow") age))
371 | b (i/future (some-> (pirate-by-name "Blackbeard") age))
372 | c (i/future (some-> (pirate-by-name "Hector Barbossa") age))
373 | avg (avg-fut a b c)
374 | median (median-fut a b c)
375 | std-dev (std-dev-fut a b c)]
376 | (i/const-future {:avg avg
377 | :median median
378 | :std-dev std-dev}))
379 | ;; #>
382 |
--------------------------------------------------------------------------------
/code/appendix-the-algebra-of-library-design/library-design/test/library_design/core_test.clj:
--------------------------------------------------------------------------------
1 | (ns library-design.core-test
2 | (:require [clojure.test :refer :all]
3 | [library-design.core :refer :all]))
4 |
5 | (deftest a-test
6 | (testing "FIXME, I fail."
7 | (is (= 0 1))))
8 |
--------------------------------------------------------------------------------
/code/chapter01/calculator/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /classes
3 | /checkouts
4 | pom.xml
5 | pom.xml.asc
6 | *.jar
7 | *.class
8 | /.lein-*
9 | /.nrepl-port
10 |
--------------------------------------------------------------------------------
/code/chapter01/calculator/README.md:
--------------------------------------------------------------------------------
1 | # calculator
2 |
3 | A Clojure library designed to ... well, that part is up to you.
4 |
5 | ## Usage
6 |
7 | FIXME
8 |
9 | ## License
10 |
11 | Copyright © 2014 FIXME
12 |
13 | Distributed under the Eclipse Public License either version 1.0 or (at
14 | your option) any later version.
15 |
--------------------------------------------------------------------------------
/code/chapter01/calculator/doc/intro.md:
--------------------------------------------------------------------------------
1 | # Introduction to calculator
2 |
3 | TODO: write [great documentation](http://jacobian.org/writing/great-documentation/what-to-write/)
4 |
--------------------------------------------------------------------------------
/code/chapter01/calculator/project.clj:
--------------------------------------------------------------------------------
1 | (defproject calculator "0.1.0-SNAPSHOT"
2 | :description "FIXME: write description"
3 | :url "http://example.com/FIXME"
4 | :license {:name "Eclipse Public License"
5 | :url "http://www.eclipse.org/legal/epl-v10.html"}
6 | :dependencies [[org.clojure/clojure "1.5.1"]
7 | [seesaw "1.4.4"]])
8 |
--------------------------------------------------------------------------------
/code/chapter01/calculator/src/calculator/core.clj:
--------------------------------------------------------------------------------
1 | (ns calculator.core
2 | (:require [seesaw.core :refer :all]))
3 |
4 | (native!)
5 |
6 | (def main-frame (frame :title "Calculator" :on-close :exit))
7 |
8 | (def field-x (text "1"))
9 | (def field-y (text "2"))
10 |
11 | (def result-label (label "Type numbers in the boxes to add them up!"))
12 |
13 | (defn update-sum [e]
14 | (try
15 | (text! result-label
16 | (str "Sum is " (+ (Integer/parseInt (text field-x))
17 | (Integer/parseInt (text field-y)))))
18 | (catch Exception e
19 | (println "Error parsing input."))))
20 |
21 | (listen field-x :key-released update-sum)
22 | (listen field-y :key-released update-sum)
23 |
24 | (config! main-frame :content
25 | (border-panel
26 | :north (horizontal-panel :items [field-x field-y])
27 | :center result-label
28 | :border 5))
29 |
30 | (defn -main [& args]
31 | (-> main-frame pack! show!))
32 |
--------------------------------------------------------------------------------
/code/chapter01/calculator/test/calculator/core_test.clj:
--------------------------------------------------------------------------------
1 | (ns calculator.core-test
2 | (:require [clojure.test :refer :all]
3 | [calculator.core :refer :all]))
4 |
5 | (deftest a-test
6 | (testing "FIXME, I fail."
7 | (is (= 0 1))))
8 |
--------------------------------------------------------------------------------
/code/chapter01/sin-wave/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /classes
3 | /checkouts
4 | pom.xml
5 | pom.xml.asc
6 | *.jar
7 | *.class
8 | /.lein-*
9 | /.nrepl-port
10 | /resources/public/js
11 | /out
12 | /.repl
13 |
--------------------------------------------------------------------------------
/code/chapter01/sin-wave/LICENSE:
--------------------------------------------------------------------------------
1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
4 |
5 | 1. DEFINITIONS
6 |
7 | "Contribution" means:
8 |
9 | a) in the case of the initial Contributor, the initial code and
10 | documentation distributed under this Agreement, and
11 |
12 | b) in the case of each subsequent Contributor:
13 |
14 | i) changes to the Program, and
15 |
16 | ii) additions to the Program;
17 |
18 | where such changes and/or additions to the Program originate from and are
19 | distributed by that particular Contributor. A Contribution 'originates' from
20 | a Contributor if it was added to the Program by such Contributor itself or
21 | anyone acting on such Contributor's behalf. Contributions do not include
22 | additions to the Program which: (i) are separate modules of software
23 | distributed in conjunction with the Program under their own license
24 | agreement, and (ii) are not derivative works of the Program.
25 |
26 | "Contributor" means any person or entity that distributes the Program.
27 |
28 | "Licensed Patents" mean patent claims licensable by a Contributor which are
29 | necessarily infringed by the use or sale of its Contribution alone or when
30 | combined with the Program.
31 |
32 | "Program" means the Contributions distributed in accordance with this
33 | Agreement.
34 |
35 | "Recipient" means anyone who receives the Program under this Agreement,
36 | including all Contributors.
37 |
38 | 2. GRANT OF RIGHTS
39 |
40 | a) Subject to the terms of this Agreement, each Contributor hereby grants
41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
42 | reproduce, prepare derivative works of, publicly display, publicly perform,
43 | distribute and sublicense the Contribution of such Contributor, if any, and
44 | such derivative works, in source code and object code form.
45 |
46 | b) Subject to the terms of this Agreement, each Contributor hereby grants
47 | Recipient a non-exclusive, worldwide, royalty-free patent license under
48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise
49 | transfer the Contribution of such Contributor, if any, in source code and
50 | object code form. This patent license shall apply to the combination of the
51 | Contribution and the Program if, at the time the Contribution is added by the
52 | Contributor, such addition of the Contribution causes such combination to be
53 | covered by the Licensed Patents. The patent license shall not apply to any
54 | other combinations which include the Contribution. No hardware per se is
55 | licensed hereunder.
56 |
57 | c) Recipient understands that although each Contributor grants the licenses
58 | to its Contributions set forth herein, no assurances are provided by any
59 | Contributor that the Program does not infringe the patent or other
60 | intellectual property rights of any other entity. Each Contributor disclaims
61 | any liability to Recipient for claims brought by any other entity based on
62 | infringement of intellectual property rights or otherwise. As a condition to
63 | exercising the rights and licenses granted hereunder, each Recipient hereby
64 | assumes sole responsibility to secure any other intellectual property rights
65 | needed, if any. For example, if a third party patent license is required to
66 | allow Recipient to distribute the Program, it is Recipient's responsibility
67 | to acquire that license before distributing the Program.
68 |
69 | d) Each Contributor represents that to its knowledge it has sufficient
70 | copyright rights in its Contribution, if any, to grant the copyright license
71 | set forth in this Agreement.
72 |
73 | 3. REQUIREMENTS
74 |
75 | A Contributor may choose to distribute the Program in object code form under
76 | its own license agreement, provided that:
77 |
78 | a) it complies with the terms and conditions of this Agreement; and
79 |
80 | b) its license agreement:
81 |
82 | i) effectively disclaims on behalf of all Contributors all warranties and
83 | conditions, express and implied, including warranties or conditions of title
84 | and non-infringement, and implied warranties or conditions of merchantability
85 | and fitness for a particular purpose;
86 |
87 | ii) effectively excludes on behalf of all Contributors all liability for
88 | damages, including direct, indirect, special, incidental and consequential
89 | damages, such as lost profits;
90 |
91 | iii) states that any provisions which differ from this Agreement are offered
92 | by that Contributor alone and not by any other party; and
93 |
94 | iv) states that source code for the Program is available from such
95 | Contributor, and informs licensees how to obtain it in a reasonable manner on
96 | or through a medium customarily used for software exchange.
97 |
98 | When the Program is made available in source code form:
99 |
100 | a) it must be made available under this Agreement; and
101 |
102 | b) a copy of this Agreement must be included with each copy of the Program.
103 |
104 | Contributors may not remove or alter any copyright notices contained within
105 | the Program.
106 |
107 | Each Contributor must identify itself as the originator of its Contribution,
108 | if any, in a manner that reasonably allows subsequent Recipients to identify
109 | the originator of the Contribution.
110 |
111 | 4. COMMERCIAL DISTRIBUTION
112 |
113 | Commercial distributors of software may accept certain responsibilities with
114 | respect to end users, business partners and the like. While this license is
115 | intended to facilitate the commercial use of the Program, the Contributor who
116 | includes the Program in a commercial product offering should do so in a
117 | manner which does not create potential liability for other Contributors.
118 | Therefore, if a Contributor includes the Program in a commercial product
119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend
120 | and indemnify every other Contributor ("Indemnified Contributor") against any
121 | losses, damages and costs (collectively "Losses") arising from claims,
122 | lawsuits and other legal actions brought by a third party against the
123 | Indemnified Contributor to the extent caused by the acts or omissions of such
124 | Commercial Contributor in connection with its distribution of the Program in
125 | a commercial product offering. The obligations in this section do not apply
126 | to any claims or Losses relating to any actual or alleged intellectual
127 | property infringement. In order to qualify, an Indemnified Contributor must:
128 | a) promptly notify the Commercial Contributor in writing of such claim, and
129 | b) allow the Commercial Contributor tocontrol, and cooperate with the
130 | Commercial Contributor in, the defense and any related settlement
131 | negotiations. The Indemnified Contributor may participate in any such claim
132 | at its own expense.
133 |
134 | For example, a Contributor might include the Program in a commercial product
135 | offering, Product X. That Contributor is then a Commercial Contributor. If
136 | that Commercial Contributor then makes performance claims, or offers
137 | warranties related to Product X, those performance claims and warranties are
138 | such Commercial Contributor's responsibility alone. Under this section, the
139 | Commercial Contributor would have to defend claims against the other
140 | Contributors related to those performance claims and warranties, and if a
141 | court requires any other Contributor to pay any damages as a result, the
142 | Commercial Contributor must pay those damages.
143 |
144 | 5. NO WARRANTY
145 |
146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON
147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the
151 | appropriateness of using and distributing the Program and assumes all risks
152 | associated with its exercise of rights under this Agreement , including but
153 | not limited to the risks and costs of program errors, compliance with
154 | applicable laws, damage to or loss of data, programs or equipment, and
155 | unavailability or interruption of operations.
156 |
157 | 6. DISCLAIMER OF LIABILITY
158 |
159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
166 | OF SUCH DAMAGES.
167 |
168 | 7. GENERAL
169 |
170 | If any provision of this Agreement is invalid or unenforceable under
171 | applicable law, it shall not affect the validity or enforceability of the
172 | remainder of the terms of this Agreement, and without further action by the
173 | parties hereto, such provision shall be reformed to the minimum extent
174 | necessary to make such provision valid and enforceable.
175 |
176 | If Recipient institutes patent litigation against any entity (including a
177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself
178 | (excluding combinations of the Program with other software or hardware)
179 | infringes such Recipient's patent(s), then such Recipient's rights granted
180 | under Section 2(b) shall terminate as of the date such litigation is filed.
181 |
182 | All Recipient's rights under this Agreement shall terminate if it fails to
183 | comply with any of the material terms or conditions of this Agreement and
184 | does not cure such failure in a reasonable period of time after becoming
185 | aware of such noncompliance. If all Recipient's rights under this Agreement
186 | terminate, Recipient agrees to cease use and distribution of the Program as
187 | soon as reasonably practicable. However, Recipient's obligations under this
188 | Agreement and any licenses granted by Recipient relating to the Program shall
189 | continue and survive.
190 |
191 | Everyone is permitted to copy and distribute copies of this Agreement, but in
192 | order to avoid inconsistency the Agreement is copyrighted and may only be
193 | modified in the following manner. The Agreement Steward reserves the right to
194 | publish new versions (including revisions) of this Agreement from time to
195 | time. No one other than the Agreement Steward has the right to modify this
196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The
197 | Eclipse Foundation may assign the responsibility to serve as the Agreement
198 | Steward to a suitable separate entity. Each new version of the Agreement will
199 | be given a distinguishing version number. The Program (including
200 | Contributions) may always be distributed subject to the version of the
201 | Agreement under which it was received. In addition, after a new version of
202 | the Agreement is published, Contributor may elect to distribute the Program
203 | (including its Contributions) under the new version. Except as expressly
204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
205 | licenses to the intellectual property of any Contributor under this
206 | Agreement, whether expressly, by implication, estoppel or otherwise. All
207 | rights in the Program not expressly granted under this Agreement are
208 | reserved.
209 |
210 | This Agreement is governed by the laws of the State of New York and the
211 | intellectual property laws of the United States of America. No party to this
212 | Agreement will bring a legal action under this Agreement more than one year
213 | after the cause of action arose. Each party waives its rights to a jury trial
214 | in any resulting litigation.
215 |
--------------------------------------------------------------------------------
/code/chapter01/sin-wave/Procfile:
--------------------------------------------------------------------------------
1 | web: java $JVM_OPTS -cp target/sin-wave.jar clojure.main -m sin-wave.server
2 |
--------------------------------------------------------------------------------
/code/chapter01/sin-wave/README.md:
--------------------------------------------------------------------------------
1 | # sin-wave
2 |
3 |
4 | ## Development
5 |
6 | Start a REPL (in a terminal: `lein repl`, or from Emacs: open a
7 | clj/cljs file in the project, then do `M-x cider-jack-in`. Make sure
8 | CIDER is up to date).
9 |
10 | In the REPL do
11 |
12 | ```clojure
13 | (run)
14 | (browser-repl)
15 | ```
16 |
17 | The call to `(run)` does two things, it starts the webserver at port
18 | 10555, and also the Figwheel server which takes care of live reloading
19 | ClojureScript code and CSS. Give them some time to start.
20 |
21 | Running `(browser-repl)` starts the Weasel REPL server, and drops you
22 | into a ClojureScript REPL. Evaluating expressions here will only work
23 | once you've loaded the page, so the browser can connect to Weasel.
24 |
25 | When you see the line `Successfully compiled "resources/public/app.js"
26 | in 21.36 seconds.`, you're ready to go. Browse to
27 | `http://localhost:10555` and enjoy.
28 |
29 | **Attention: It is not longer needed to run `lein figwheel`
30 | separately. This is now taken care of behind the scenes**
31 |
32 | ## Trying it out
33 |
34 | If all is well you now have a browser window saying 'Hello Chestnut',
35 | and a REPL prompt that looks like `cljs.user=>`.
36 |
37 | Open `resources/public/css/style.css` and change some styling of the
38 | H1 element. Notice how it's updated instantly in the browser.
39 |
40 | Open `src/cljs/sin-wave/core.cljs`, and change `dom/h1` to
41 | `dom/h2`. As soon as you save the file, your browser is updated.
42 |
43 | In the REPL, type
44 |
45 | ```
46 | (ns sin-wave.core)
47 | (swap! app-state assoc :text "Interactivity FTW")
48 | ```
49 |
50 | Notice again how the browser updates.
51 |
52 | ## Deploying to Heroku
53 |
54 | This assumes you have a
55 | [Heroku account](https://signup.heroku.com/dc), have installed the
56 | [Heroku toolbelt](https://toolbelt.heroku.com/), and have done a
57 | `heroku login` before.
58 |
59 | ``` sh
60 | git init
61 | git add -A
62 | git commit
63 | heroku create
64 | git push heroku master:master
65 | heroku open
66 | ```
67 |
68 | ## Running with Foreman
69 |
70 | Heroku uses [Foreman](http://ddollar.github.io/foreman/) to run your
71 | app, which uses the `Procfile` in your repository to figure out which
72 | server command to run. Heroku also compiles and runs your code with a
73 | Leiningen "production" profile, instead of "dev". To locally simulate
74 | what Heroku does you can do:
75 |
76 | ``` sh
77 | lein with-profile -dev,+production uberjar && foreman start
78 | ```
79 |
80 | Now your app is running at
81 | [http://localhost:5000](http://localhost:5000) in production mode.
82 |
83 | ## License
84 |
85 | Copyright © 2014 FIXME
86 |
87 | Distributed under the Eclipse Public License either version 1.0 or (at
88 | your option) any later version.
89 |
--------------------------------------------------------------------------------
/code/chapter01/sin-wave/env/dev/cljs/sin_wave/dev.cljs:
--------------------------------------------------------------------------------
1 | (ns sin-wave.dev
2 | (:require [sin-wave.core :as core]
3 | [figwheel.client :as figwheel :include-macros true]
4 | [cljs.core.async :refer [put!]]
5 | [weasel.repl :as weasel]))
6 |
7 | (enable-console-print!)
8 |
9 | (figwheel/watch-and-reload
10 | :websocket-url "ws://localhost:3449/figwheel-ws"
11 | :jsload-callback (fn []
12 | (core/main)
13 | ))
14 |
15 | (weasel/connect "ws://localhost:9001" :verbose true)
16 |
17 | (core/main)
18 |
--------------------------------------------------------------------------------
/code/chapter01/sin-wave/env/prod/cljs/sin_wave/prod.cljs:
--------------------------------------------------------------------------------
1 | (ns sin-wave.prod
2 | (:require [sin-wave.core :as core]))
3 |
4 | (core/main)
5 |
--------------------------------------------------------------------------------
/code/chapter01/sin-wave/project.clj:
--------------------------------------------------------------------------------
1 | (defproject sin-wave "0.1.0-SNAPSHOT"
2 | :description "FIXME: write description"
3 | :url "http://example.com/FIXME"
4 | :license {:name "Eclipse Public License"
5 | :url "http://www.eclipse.org/legal/epl-v10.html"}
6 |
7 | :source-paths ["src/clj" "src/cljs"]
8 |
9 | :dependencies [[org.clojure/clojure "1.6.0"]
10 | [org.clojure/clojurescript "0.0-2371" :scope "provided"]
11 | [ring "1.3.1"]
12 | [compojure "1.2.0"]
13 | [enlive "1.1.5"]
14 | [om "0.7.3"]
15 | [figwheel "0.1.4-SNAPSHOT"]
16 | [environ "1.0.0"]
17 | [com.cemerick/piggieback "0.1.3"]
18 | [weasel "0.4.0-SNAPSHOT"]
19 | [leiningen "2.5.0"]]
20 |
21 | :plugins [[lein-cljsbuild "1.0.3"]
22 | [lein-environ "1.0.0"]]
23 |
24 | :min-lein-version "2.5.0"
25 |
26 | :uberjar-name "sin-wave.jar"
27 |
28 | :cljsbuild {:builds {:app {:source-paths ["src/cljs"]
29 | :compiler {:output-to "resources/public/js/app.js"
30 | :output-dir "resources/public/js/out"
31 | :source-map "resources/public/js/out.js.map"
32 | :preamble ["react/react.min.js"]
33 | :externs ["react/externs/react.js"]
34 | :optimizations :none
35 | :pretty-print true}}}}
36 |
37 | :profiles {:dev {:repl-options {:init-ns sin-wave.server
38 | :nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}
39 |
40 | :plugins [[lein-figwheel "0.1.4-SNAPSHOT"]]
41 |
42 | :figwheel {:http-server-root "public"
43 | :port 3449
44 | :css-dirs ["resources/public/css"]}
45 |
46 | :env {:is-dev true}
47 |
48 | :cljsbuild {:builds {:app {:source-paths ["env/dev/cljs"]}}}}
49 |
50 | :uberjar {:hooks [leiningen.cljsbuild]
51 | :env {:production true}
52 | :omit-source true
53 | :aot :all
54 | :cljsbuild {:builds {:app
55 | {:source-paths ["env/prod/cljs"]
56 | :compiler
57 | {:optimizations :advanced
58 | :pretty-print false}}}}}})
59 |
--------------------------------------------------------------------------------
/code/chapter01/sin-wave/resources/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |