A src/assets/question.svg => src/assets/question.svg +1 -0
@@ 0,0 1,1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z"/></svg><
\ No newline at end of file
M src/chapter-page.css.pp => src/chapter-page.css.pp +17 -0
@@ 515,6 515,16 @@ body.chapter-page main aside {
padding: ◊|paragraph-spacing|px ◊(* 2 paragraph-spacing)px;
}
+body.chapter-page main aside.question {
+ margin-bottom: ◊|(* 2 article-paragraph-spacing)|px;
+}
+
+body.chapter-page main aside.question header h1 {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+}
+
body.chapter-page main aside header h1 {
font-variant: all-small-caps;
font-size: ◊|body-font-size|px;
@@ 522,6 532,13 @@ body.chapter-page main aside header h1 {
text-align: center;
}
+body.chapter-page main div.answer {
+ padding: 0 ◊(* 2 paragraph-spacing)px;
+}
+body.chapter-page main div.answer label {
+ padding-left: ◊|paragraph-spacing|px;
+}
+
body.chapter-page main div.highlight div.scala .k { color: ◊|dark-needle-colour| } /* Keyword */
body.chapter-page main div.highlight div.scala .s { color: #547054 } /* Strings */
body.chapter-page main div.highlight div.scala .c1 { color: ◊|dark-needle-colour| } /* Comments */
M src/chapters/2022-02-12-cats-effect-ioruntime/the-IORuntime.html.pm => src/chapters/2022-02-12-cats-effect-ioruntime/the-IORuntime.html.pm +20 -2
@@ 117,7 117,17 @@ pool, we must use a different constructor: the aptly named ◊code-inline{IO.blo
◊snippet[#:name "better-snooze"]{}
◊p{Let’s run a few better snoozes using our
-◊code-inline{boundedRuntime}. How long should they take?}
+◊code-inline{boundedRuntime}.}
+
+◊question-block{
+◊question{It took ◊|snooze-time| seconds to run ◊code-inline{snooze} and ◊|snooze-time-double|
+seconds to run ◊code-inline{tenSnoozes} on a
+◊code-inline{boundedRuntime}. How long should it take to run
+◊code-inline{tenBetterSnoozes}?}
+
+◊answer{◊|(string-titlecase snooze-time-double)| seconds.}
+◊answer{◊|(string-titlecase snooze-time)| seconds.}
+}
◊snippet[#:name "better-snooze-run"]{}
@@ 136,9 146,17 @@ compute-intensive ones?}
◊snippet[#:name "combined-blocking"]{}
-◊p{The previous ◊code-inline{snoozeAndCompute} task took six
+
+
+◊question-block{
+◊question{The previous ◊code-inline{snoozeAndCompute} task took six
seconds. How long should this one take?}
+◊answer{Six seconds.}
+◊answer{Less than six seconds.}
+}
+
+
◊snippet[#:name "combined-blocking-run"]{}
◊p{It’s much faster: the threads in the bounded compute pool no longer
M src/chapters/2022-02-12-cats-effect-ioruntime/thread-pools.html.pm => src/chapters/2022-02-12-cats-effect-ioruntime/thread-pools.html.pm +56 -18
@@ 35,8 35,17 @@ running it using our handy ◊code-inline{time} function:}
◊p{The ◊code-inline{parSequence} function produces an ◊code-inline{IO}
that runs multiple tasks in
-parallel. If each task takes ◊|snooze-time| seconds, how long should
-◊code-inline{parallelSnoozes} take?}
+parallel.}
+
+◊question-block{
+◊question{
+If each task takes ◊|snooze-time| seconds, how long should
+◊code-inline{parallelSnoozes} take?
+}
+◊answer{◊|(string-titlecase snooze-time-double)| seconds.}
+◊answer{◊|(string-titlecase snooze-time)| seconds.}
+◊answer{Between ◊|snooze-time| and ◊|snooze-time-double| seconds.}
+}
◊snippet[#:name "snooze-parallel-run"]{}
@@ 88,9 97,13 @@ with ◊code-inline{parSequence}:}
◊snippet[#:name "factorial-io-parallelized"]{}
-◊p{How long should ◊code-inline{factorials} take to run?}
+◊question-block{
+◊question{How long should ◊code-inline{tenFactorials} take to run?}
+◊answer{Two seconds.}
+◊answer{Longer than two seconds.}
+}
◊p{It took two seconds to run ◊code-inline{factorial} once, so it
-should also take two seconds to run in parallel, shouldn’t it?:}
+should also take two seconds to run in parallel, shouldn’t it?}
◊snippet[#:name "factorial-io-parallelized-run"]{}
@@ 99,7 112,7 @@ bit. You might have also found that the code ◊em{didn’t} take two seconds
— it took longer.}
◊p{This is different to our ◊code-inline{snooze} task, which always took
-◊|snooze-time| seconds regardless of whether we ran one, ten or a
+◊|snooze-time| seconds regardless of whether we ran one, two or a
thousand in parallel.}
◊p{Why would that be?}
@@ 140,16 153,23 @@ by timing each task:}
◊p{This gives a string description for each of the
twenty tasks corresponding to how long the task took to run.}
-◊p{Let’s run it to check the times:}
+◊question-block{
+◊question{It took two seconds to run ◊code-inline{factorial} once and three
+seconds to run ◊code-inline{tenFactorials}. How long should each of the
+twenty tasks in ◊code-inline{timedFactorials} take to run?}
+
+◊answer{Two seconds.}
+◊answer{Six seconds.}
+◊answer{Anywhere between two and six seconds.}
+◊answer{◊code-inline{0.3} seconds.}
+}
◊snippet[#:name "factorial-io-parallelized-time-each-run"]{}
-◊p{That’s strange! The ◊code-inline{factorials} task may have taken
-six seconds in total, but shouldn’t each task have taken two seconds?}
-◊p{Instead, we see times of anywhere between two and six.}
+◊p{Strange! We see times of anywhere between two and six.}
-◊p{This is because all tasks are fired off at the same time, but our
+◊p{All tasks are fired off at the same time, but our
processors switch between them as they run. A processor might start
computing a task, but put it on hold in order to compute a different
one, switching back to it at a later time.
@@ 176,10 196,8 @@ many memory-intensive computations would give us
◊code-inline{OutOfMemoryError} exceptions.}
}
-◊p{This is why it’s generally much more useful to limit the number of
-tasks that can be run in parallel.}
-
-◊p{We can do this using ◊keyword{thread pools}.}
+◊p{It’s generally much more useful to limit the number of
+tasks that can be run in parallel. We can do this using ◊keyword{thread pools}.}
◊headline-link{Bounded and unbounded thread pools}
@@ 198,10 216,21 @@ number of tasks in parallel.}
◊p{It’s much slower than before — only two tasks are run at once.}
-◊p{How long does each task take to run? We can check with ◊code-inline{timedFactorials}:}
+
+◊question-block{
+◊question{It took two seconds to run ◊code-inline{factorial} once and twelve
+seconds to run ◊code-inline{tenFactorials} on a bounded
+thread pool with two threads. How long should each of the
+twenty tasks in ◊code-inline{timedFactorials} take to run?}
+
+◊answer{Two seconds.}
+◊answer{Twenty-four seconds.}
+◊answer{Anywhere between two and twenty-four seconds.}
+}
◊snippet[#:name "factorial-time-bounded-threadpool"]{}
+
◊p{Unlike the previous unbounded thread pool, each task takes two
seconds ⸺ the tasks might be ◊em{scheduled} at once, but they’re fired
off over time, once a ◊keyword{thread} is free to compute them.}
@@ 257,9 286,18 @@ construct an ◊code-inline{IO} that runs ten tasks in parallel:}
◊snippet[#:name "snooze-10"]{}
-◊p{Let’s try running this our bounded thread pool. Each task takes
-◊|snooze-time| seconds. How long should the ◊code-inline{tenSnoozes}
-task take?}
+◊p{Let’s try running this our bounded thread pool.}
+
+◊question-block{
+◊question{
+Each ◊code-inline{snooze} takes ◊|snooze-time| seconds.
+How long should ◊code-inline{tenSnoozes} take on a bounded thread pool
+with eight threads?
+}
+◊answer{◊|(string-titlecase snooze-time)| seconds.}
+◊answer{◊|(string-titlecase snooze-time-double)| seconds.}
+◊answer{Longer than ◊|snooze-time-double| seconds.}
+}
◊snippet[#:name "snooze-10-run"]{}
M src/pollen.rkt => src/pollen.rkt +30 -1
@@ 23,7 23,8 @@
external-link
image
diagram
- abstract)
+ abstract
+ question-block)
(module setup racket/base
(require racket/runtime-path)
@@ 96,3 97,31 @@
(define (abstract . text)
`(p ([class "abstract"]) ,@text))
+
+(define (question-block . contents)
+ (let* (
+ [question (car (filter-map (λ (sexpr) (and (pair? sexpr)
+ (equal? (car sexpr) 'question)
+ (cdr sexpr)))
+ contents))]
+ [question-str (string-join (map (λ (x) (format "~a" x)) question) "-")]
+ [answers (filter-map (λ (sexpr)
+ (and (pair? sexpr)
+ (equal? (car sexpr) 'answer)
+ (cdr sexpr)))
+ contents)]
+ [indexed-answers (for/list ([answer answers]
+ [idx (in-naturals)])
+ `(div ([class "answer"])
+ (input ([id ,(string-append question-str "-" (number->string idx))]
+ [name ,question-str]
+ [type "radio"]))
+ (label ([for ,(string-append question-str "-" (number->string idx))]) ,@answer)))])
+ `(aside ([class "question"])
+ (header (h1 (img ([alt ""]
+ [src "/assets/question.svg"]))
+ (span "question")
+ (img ([alt ""]
+ [src "/assets/question.svg"]))))
+ (p ,@question)
+ ,@indexed-answers)))