I’m a beginner, I haven’t done any serious programming for 20+ years. Here are my raw notes as I’m going through the tutorial. Let me say up front that I really like the format - my professional background is in standards development, so I’m nit-picky by nature :), hence the detailed comments.
On hello_clojure.clj
;; The way to use the guide is to read about the
;; concepts and evaluate the examples. Please feel
;; encouraged to edit the examples, and add new code
;; and evaluate that.
It is proposed to play with the code, but if I just change some values, the evaluation does not change automatically. I’m guessing I need to somehow refresh the evaluation?
;; (There are no statements.) Unless there is
;; en error when evaluating the expressions there
;; is always a return value
Typo (en->an)
;; Character types
"hello" ; string
\e ; character
#"[0-9]+" ; regular expression
CTRL+ENTER for evaluating regular expression leads to an error. Why?
map ; symbol
So the later example of map leads me to believe this is some kind of key-value pair? I think the symbols section should be explored a bit more, considering this is a newbie tutorial.
;; They compose
{:foo [1 2]
:bar #{1 2}}
The compose example needs a bit more explanation. What is the relevance of “:”? Overall, the syntax was never really covered, especially the reverse polish notation. This is important as the next section on lists with “proper functions at position 1” really requires the reader to get their head around this concept!
(*)
why does * evaluate to 1? What is it?
;; You define new functions and bind them to names
;; in the current namespace using the macro `defn`.
What’s a namespace in Clojure? Is this related to variables, do variables inside functions have their own namespace?
;; ... but that was a detour, back to special forms.
;; Official docs:
;; https://clojure.org/reference/special_forms#_other_special_forms
URL for the special forms includes an anchor, which does not fit with the context of the description (“official docs”).
(def foo :foo)
Does “:” have a special meaning here?
Why does (def foo foo)
evaluate also to :foo
?
Why does (= foo foo)
and (= foo :foo)
both evaluate to true?
;; This is what the macro `defn` does.
;; We can use the function `macroexpand` to see this:
(macroexpand '(defn add2
[arg]
(+ arg 2)))
What are we trying to understand with the example of macroexpand? The line looks the same as above except for the “’” before the opening bracket and the “n” after def? I’m lost. (Edit: turns out this becomes clear at line 586).
Overall, clearly this prefix of a single quote (´) seems to be important but why?
(range 1 ; 10)
;; and then place a line comment so that the closing
;; bracket of that form gets commented out, the
;; structure breaks.
)
I realize this is not to explain range but I’m guessing it returns a value up to but not including x?
;; == EXTRA SYNTAX ===
;; We've already seen the single quote
'something
;; Which is, as we have seen, transformed to
(quote something)
Ok, I’m officially lost on why we need the quote
function? Is it a variable that holds as value its name?
(deref an-atom)
(type (deref an-atom))
Ok, I get the value out of a variable (of type atom?) But I’m more interested in the tooltip that talks about delays etc. Is this related to some timing issues - a value change is not instant? Also, type seems to be “PersistentVector” - tell me more!? Especially if “;; This is so common that there is shorthand syntax”.
@an-atom
(= (deref an-atom)
@an-atom)
So, the @-notation gives us access to the value of the variable but clearly this is not a normal variable as we’ve seen those before and we did not need the @-syntax…
#"reg(?:ular )?exp(?:ression)?"
Right, regular expressions are a big topic and cannot be covered here - perhaps a link to a more comprehensive source? And maybe explain what this particular regex does?
;; That hash sign shows up now and then, for instance
#(+ % 2)
Hold on. You just told me that hash is used in front of regular expressions. This is not a regular expression. How many syntaxes start with a hash? … oh wait, you explain it further down:
;; The hash sign has a special role. It is aka
;; Dispatch. Depending on what character is following
;; it, different cool things happen.
;; In addition to sets, regexps and function literals
;; we have seen var-quotes in this guide
Maybe lead with this explanation?
(= #:foo {:bar 'bar
:baz 'baz}
{:foo/bar 'bar
:foo/baz 'baz})
So we never really explained namespaces but I’m guessing we implicitly assign “foo” (or is it “:foo”?) namespace for the bar bar and baz baz key value-pairs? Is the “:” for key and “’” for the value? Then we compare the second kv pair that has explicit namespace declared via “:foo/”? Are namespaces of all variables automatically evaluated even if they are not explicitly declared in the evaluation? Does the linter keep track of these?
;; Unrelated to the #: There is another shorthand for
;; specifying namespaced keywords. Double colon
;; keywords get namespaced with the current namespace
::foo
(= ::foo :hello-clojure/foo)
When we say “current namespace”, is that declared “globally” for the whole file or can you have some kind of “from this point on, all variables are in xyz namespace”?
;; #inst will convert the string it tags to an instance
#inst "2018-03-28T10:48:00.000"
(type *1)
So here I’m being confused - probably due to the overloaded term “instance”, is this only seen as instant - as in a moment in time (vs. instance of a object)? Or is it just a particular variable type of java.util.date (what exactly does that imply?)
(as a side note: macros, whoa! Very cool - it’s turtles all the way down!)
;; It is similar to the lexical scope of other
;; programming lannguages (even if this rather is
Typo
(for [x [1 2 3]
y [1 2 3 4]
:let [d' (- x y)
d (Math/abs d')]]
d)
Ok, in this case “’” has no reserved meaning, we can use “special characters” in variable names.
;; Filters and bindings can be used together.
;; Use both `:let` and `:when` to make this
;; comprehension return a list of all `[x y]` where
;; their sum is odd. The functions `+` and `odd?`
;; are your friends here.
I did not quite get this - why would I need the :let
? The only solution I came up with was:
(for [x [1 2 3]
y [1 2 3 4]
:when (odd? (+ x y))]
[x y])
Anyway, it is a good idea to have little puzzles sprinkled in the tutorial.
(as-> 15 $
(range 1 $ 3)
(interpose ":" $))
I think this is the first time we are using $ as a variable name. Maybe we should go over the allowed characters in variable names?
[Edit stops here - line 1000 or so, I’ll come back once I’ve reached line 1500]
(Side note: the file has many comment forms
but their usage is never explained)