A set of training materials (based on https://github.com/alain-picard/clojure-training) prepared by Benson Zhang for use in training new clojure engineers at Blue Ridge Global.
PREPARING
Before each lesson, you must come prepared by having completed the necessary reading in each of the Lesson Plans. Make sure you keep an eye on this repo for new lesson plans, and I will email you all each time a new one is added.
DURING THE LESSONS
This repo will periodically be updated with the code developed in
each lesson (when applicable) so you can download and play with the
examples I provide during the lessons. Jack will also record the
lessons and make the videos available to you all.
After each lesson, the code will be added in a
file (or subdirectory) named lesson-01
, lesson-02
etc. (in the src subdir).
AFTER THE LESSONS
You will have to fork this repo so you can submit your assignment solutions for review.
At the end of the lesson, I will sometimes set assignments
which I will detail in the Assignments section. You should
attempt to answer these, placing your answers in the file
/src/assignments/your_name//lesson_XX_answers.clj
. When you
can cleanly load your file into a repl, raise a pull request for
me to review your code and merge it back into the main repo. Thus,
you’ll be able to view your colleague’s solutions after I merge your
answers back into the main repo.
REVIEWING SOLUTIONS
After the lessons, I will place my solutions in this directory. You can peruse them at your leisure and compare against the code you have written.
I will also place the code I present during the live coding sessions in here; the files beginning with live_XXX are the code you see on the screen during the presentation; the files without the live_ prefix are the preparatory material I produce (which is close, but doesn’t include the tangents I go off on during the lessons as questions arise, etc.)
- [X] how to get help
- [X] navigate sources
- [X] structural editing
- [X] using maps
- [X] gotchas with
conj
- [X] destructuring
- [X] sequences, lazy seqs
- [X] lexical vs dynamic scoping
- [X] reduce, functional idioms
- [X] tracing, debugging
- [X] writing tests
- [X] Introduction to
leiningen
, dependency management, and finding and using libraries in clojure. - [X] The philosophical underpinning of state handling in clojure
- [X] vars, atoms, refs, agents
- [X] threads, futures, promises (concurrency primitives)
- [X] The reader, it’s syntax, and brief macro overview
- [X] java interop, definining new types
- [X] namespaces, the ns macro
- [X] i/o
- [X] writing (good!) docstrings
- [X] metadata
- [ ] strings; regexes
- [X] throw/catch, slingshot
- [X] making simple HTTP requests
- [X] multimethods
- [X] finding and using libraries
- [X] supply a list of recommended good libs.
- [X] reader syntax
- [X] Simple HTTP service: ring handlers, libraries
- [X] Sending HTTP requests
- [X] core.async
- [ ] clojurescript
- [ ] reframe
- [ ] macros, threading macros
We are going to make extensive use of the following:
- The excellent online book: Clojure for the Brave and True
- The clojure koans
- Many of the excellent at 4clojure sample problems
- In lessons 7 and 8, we will make use of this simple server playground.
- In lessons 9 and 10, we will study a bit of reagent (TODO).
- In lessons 11 and 12, we will build our own version of the New York Times Spelling Bee.
I urge you all to have a look at:
- Awesome clojure: a curated list
- The clojure cookbook
- The figwheel documentation (TODO: Look into possibly changing this to shadow-cljs)
- The reagent documentation
- The re-frame documentation
Newer lesson plans will be added in as lessons are completed.
- Lesson 1
- intro
- Lesson 2
- Functional Programming
- Lesson 3
- More functional programming
- Lesson 4
- References and identities, threads
- Lesson 5
- Java interop, namespaces, i/o
- Lesson 6
- Clojure odds and ends
- Lesson 7
- Building a simple HTTP service - Guess the right number!
- Lesson 8
- core.async and Postgresql
- Lesson 9
- Clojurescript
- Lesson 10
- Re-Frame
- Lesson 11
- The word puzzle (part 1)
- Lesson 12
- The word puzzle (part 2)
- Course summary
- A quick review
These will be added in over time as lessons are completed. Assignment answers should be committed in src/assignments/YOUR_NAME/assignmentXX.clj in your forked branch Pull this branch separately, and merge it into your source branch, commit, and raise a pull request to the main branch.
These are the assignment problems following Lesson 2. We will discuss your solutions and see my solutions at the beginning of Lesson 3.
- Implement your own version of
filter
using a loop form, then using reduce. - Implement your own version of
update-in
- Write a function which solves this problem: https://4clojure.oxal.org/#/problem/77
- Write a function which solves this problem: https://4clojure.oxal.org/#/problem/53
- Read chapters 9 and 10 of Clojure for the Brave and True
- Listen to the this online talk: Are we there yet
Take notes! Listen carefully! Rich is a very deep thinker.
Pay particular attention to the analogy about the baseball game,
when he discusses how state evolves and should be modelled.
Can you see why clojure has
atoms
andrefs
, and immutable values, as its programming model? - Try to solve the best poker hand
problem (The original is down so we will use an archived version). This will require you
to first solve problem 128, recognizing poker hands.
This is an excercise is structuring and factoring your code
as cleanly as possible; pay close attention to your representation
and clearly separate the parsing code from the evaluation code.
See what reusable functions exist in recognizing all the various
types of hands.
Here I want you to think not simply in terms of learning clojure syntax; (you should have all the necessary tools to solve this already), but at the next level of sophistication; that is, worry about
- choosing good names for functions and variables
- representation of your data structures
- clearly separating out functionality
- making things as readable and understandable as you possibly can
- write a test harness for your code.
- There are no koans dealing with multiprocessing (probably just too hard to write them!) So we’ll be doing the book excercises instead. Do the exercises at the end of chapter 9.
- Do the exercises at the end of chapter 10. Note that in the
second excercise, the URL shown is incorrect; it should be HTTPS,
not http, thus:
(slurp "https://www.braveclojure.com/random-quote")
THIS SEEMS TO BE DOWN, create a function with a random delay of 1-3 seconds instead and use that to simulate a delay.
These exercises are longer and more challenging than the ones you have done so far. Don’t hesitate to reach out on the issues board!
- Read chapter 6, specially the ns macro
- write a unix-like grep command in clojure, so that, e.g.
(grep "/tmp/somefile.txt" regex)
;; =>
["match 1" "match 2" "..."]
- for extra difficulty, make it return a lazy sequence of matches instead. What difficulties does this present? Which version is better/more useful? Can you implement the former in terms of the latter? Discuss.
- You now know >90% of clojure syntax and functions, so you
should start exercising your newfound powers as much as possible.
Practice makes perfect! Here are some problem ideas for you to try:
The Advent of code is always fun; the last 2 years had good problems.
You can try to get as far as you can on these:
Solve as many of the 4 clojure problems as you can; they are arranged either by topic or difficulty. Try those which you understand least! Don’t be afraid to call out for help!
- Extend the coin operated state machine so it can make proper change if user pays too much.
- Do the reading in preparation for Lesson 7; get to understand HTTP!
- Continue working on your AOC challenges. Rewrite your existing solutions to be clearer and more elegant, on the basis of the comments I’ve made on your pull reviews.
- Clone the sample toy problem repository, and create a new branch (use your name).
Add the following features to the code in your new branch:
- Restrict the game so that the player is told she loses if she fails to guess the correct number in 5 guesses or less.
- Add a “login” page where the user enters their name before being allowed to play the game. Modify your test client so that this authorization is sent; the server should refuse to play the game if the authorization is not present.
- Make the server be able to play multiple games, against multiple players, simultaneously.
- If you are keeping any stateful information in the system (and you’ll have to do do these features, make sure the functions to manipulate and inspect that state are abstracted away, so we can re-implement them using a database next class.
- The current game uses the GET verb to play the game, but this is bad form for operations which modify state on the server (such as creating the game, recording number of attempts etc. because GET requests can be cached by intermediate proxies. What are more appropriate verbs to use in for the uris in this game? Make the proper modification to the game.
- Modify the README file to clearly indicate all urls, and how I’m supposed to proceed to play the game to verify your work. Pretend I’m a naive user; this is an exercise in writing good documentation.
- Sending HTTP Requests to pipedrive end points
- Sign up for https://www.pipedrive.com/ dev account
- https://developers.pipedrive.com/docs/api/v1
- Implement some functionality in viewing, creating, filtering, deleting persons
- NOTE: Filter within the request itself, not grab every person and filter in clojure
- Create functionality around leads
- Create some additional functionality on a section / sections you find interesting
- Extend the “guess the number game” code you did at the end of lesson 7 by replacing all the state keeping functions with calls to Postgres. Design your tables carefully.
- Revisit the problem of returning the first hits from
multiple search engines, this time using
core.async
constructs instead of futures and promises. (You’ll need to use thealts!
macro). Compare and contrast the two approaches.
- The final assignment for the training module will be to re-implement
the “spelling bee” game of the New York Times, located at https://www.nytimes.com/puzzles/spelling-bee
In preparation for this, see if you can design some
reagent
components which:- display a list of words on the screen
- keeps these words alphabetically sorted at all times
- have an input field where user can type in new words, which should appear, in their proper place, when the user hits the carriage return
Add as many bells and whistles to your components as you like. (fonts, fade ins, fade outs, animations, error checking on repeated words, etc. Use your imagination!)
- Re-implement the “guess the number game”, this time in clojurescript. For extra difficulty, obtain the initial game state from a back end server.
## License
Copyright © 2024 Benson Zhang
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.