
Elements of Clojure - ingve
http://elementsofclojure.com/
======
zdkl
The learning experience for Clojure is superb. Coming from C/Python languages,
it really put things in perspective to learn to think more in terms of
composing primitives than wrangling syntax.

OT: Does anyone know of other projects in the spirit of Pixie? To be more
specific I'm looking for existing work on a clojure->rust project, would
contribute or start one if none exist. Sorry for the offtopic!

~~~
eriksvedang
I'm working on Clojure-looking lisp with a borrow checker and static analysis
in the vein of Rust. It's especially tailored for games since most lisps don't
account for that use case (GC, dynamic types). Here's a link, let me know if
you have any questions:
[https://github.com/eriksvedang/Carp](https://github.com/eriksvedang/Carp)

~~~
zdkl
This looks nice and feels right in terms of syntax. I'm not sure I see the
value of exposing the borrow checker to the user however; couldn't it be used
implicitly while handling the s-expr to c compilation? In any case I'd love to
talk more about it, can I reach out via the github project?

~~~
eriksvedang
Absolutely! We have a gitter chat that would be a perfect place for that kind
of discussion
[https://gitter.im/eriksvedang/Carp](https://gitter.im/eriksvedang/Carp)

------
onetwotree
"Natural names allow every reader, novice or expert, to reason by analogy.
Reasoning by analogy is a powerful tool, especially when our software models
and interacts with the real world. Synthetic names defy analogies, and prevent
novices from understanding even the basic intent behind your code. Use them
sparingly."

I'm not sure that I completely agree, but this is a great conversation to be
having!

~~~
prospero
Hi, I'm the author. I would be very happy to discuss this point (or any other)
in more depth on the mailing list:
[https://groups.google.com/forum/#!forum/elements-of-
clojure](https://groups.google.com/forum/#!forum/elements-of-clojure).

------
sotojuan
I really wish I had the time to learn Clojure. Between Rich Hickey's general
wisdom and skill, my (small but fun) exposure to Lisps, and David Nolen's
ClojureScript, it looks like a great environment to get into.

~~~
jfaucett
"really wish I had the time to learn Clojure."

I would say don't bother. The language is a nice lisp (nice simplifications,
great immutable ADTs, edn, pretty good async libs, etc), but the ecosystem
tooling is still miserable IMHO - this is coming from someone who has worked
around 6-12 months on a couple of clojure projects, so I'm not a die hard
expert but I've worked enough with it to build with/have used
clojurescript,clojure,java bindings,leiningen/boot,clojars etc.

I really wanted to like clojure. The idea that I could run my code on the JVM
and in the browser is alluring. And, I would add, if you like using mvn or ant
or gradle or in general the java way of doing things, you will probably think
leiningen is good enough.

But I have zero tolerence for annoying/unnecessary headaches, and so I can't
take it, and don't program any of my projects in it.

What do I consider good? Well an analogous project is Mix for Erlang/Elixir,
and I think its an excellent example of what I wish leiningen were. Anyone can
learn Mix in about 10 minutes, you can easily use it for erlang & elixir
projects, I have had zero problems and stuff just works. This is not the case
with leiningen, which makes building and deployments unnecessarily complicated
in clojure.

I don't see clojure getting mainstream until someone starts concentrating more
on the user experience in the tooling, though this may be more of a java/jvm
originated problem, still it affects your whole experience while using
clojure.

~~~
afhammad
As much as I love Clojure and even more so ClojureScript, I would have to
agree with you on this. To add to what you said, another big pain point for me
is starting new projects. Although I wouldn't say don't spend any time
learning the language, especially if you are new to functional languages, you
can learn a lot from Clojure.

~~~
jfaucett
"Although I wouldn't say don't spend any time learning the language"

Yes, I can see your point. And there are some really good innovations clojure
has made I think - specifically the immutable data types are really beyond
compare, anyone wishing to learn more about immutable data structs should
definately read their source in clojure its clear and understandable.

Still, if anyone wants to learn what lisp is all about. I'd just recommend
common lisp (clisp or sbcl) for getting the special forms, repl, and beauty of
macros bits. It also means you don't have to know anything about java to get
the key concepts of a lisp, which is less overhead overall.

Regardless of common lisp or clojure, I'd always recommend anyone listen to
Rich Hickey's talks on clojure, they are very good, especially his talks about
values, composition, and simplicity. ([http://www.infoq.com/author/Rich-
Hickey](http://www.infoq.com/author/Rich-Hickey))

------
devty
Exciting! Zach Tellman's work had always impressed me. Looking forward to
seeing what he brings this time around.

------
pixelmonkey
I wrote a similar kind of style guide for Python.

[https://github.com/amontalenti/elements-of-python-
style](https://github.com/amontalenti/elements-of-python-style)

"Elements of Python Style": goes beyond PEP8 to discuss what makes Python code
feel great.

Looking forward to reading Elements of Clojure. Python is my primary language
but Clojure is my hobby language.

------
sedlich
Surely a good book. But it would be nice to see the complete TOC... Leanpub
says it's 25% complete?!

~~~
prospero
The four chapters shown are the complete list, only the first chapter has been
completed. I have tried to make this as clear as possible, let me know if you
see a way to make it more so.

------
sbochins
Can't wait, I'm sure I'll learn a lot from this.

------
lispm
I fear this reads not very precise, mostly arbitrary and random.

Examples:

> If a value is an arbitrary Clojure expression, it should be called form. If
> a macro takes many expressions, the variadic parameters should be called
> body.

A value is an expression? what is a Clojure 'expression'? Why should it be
called a 'form'? If it is arbitrary, why not call it 'expression'? What does
it mean to 'take an expression'? What is 'many'? A macro, the variadic
parameterS, which should be called 'body'? The macro has more than one
variadic parameter and they all should be called 'body'?

> These defaults derive from the idioms of the Clojure ecosystem and common
> sense.

'Common sense'? What?

> If a value can be anything, we should call it x. This is fairly rare, as
> usually the only things we can do with an object involve =, hash, and str.

What is a value? what is 'anything'? The next sentence talks about 'objects'.
Is 'anything' always an object? Why don't we talk about 'any object', instead
of 'anything'? What does the number of possible actions have to do how 'rare'
a name is?

> Let’s consider a student datatype, which is represented as a map whose keys
> and values are well defined, either using documentation or a formal schema.
> Anything called student should have at least these entries, and sometimes
> only these entries.

A data type is 'represented' by a map? What does that even mean? 'Anything'?
What is 'anything' in this context and what means 'entry' in this context?

This goes on and on.

> At runtime, our scope is any data we can see from within our thread.

What is this 'we' at runtime and what does it mean for 'we' to 'see' data?

> Conversely, we can think of sending an HTTP request as sailing across an
> ocean; any transfer of data, pushed or pulled, requires effort.

What?

> If a function crosses scope boundaries, there should be a verb in the name.
> If it pulls data, it should describe the datatype it returns.

What does it mean for a function to cross scope boundaries? What is a scope
boundary?

> There are two kinds of macros: those which we understand syntactically, and
> those which we understand semantically.

There are two kinds of macros, those who begin with WITH and those who do not.
What does it mean to 'understand syntactically'/'semantically'?

> To use with-open effectively, we must macroexpand it in our heads whenever
> it appears in the code.

what?

> syntactic macros

What is that exactly?

> Transforming arbitrary code is difficult and sometimes impossible

What?

Macros: ... > Readers must not only understand the semantics of the
transformation, but also its exceptions and failure modes.

Personally I, as a reader, am more interested in the semantics of the
generated code.

> macroexpanded syntax

How can I macroexpand syntax?

> Naming is a problem which cannot be solved, but also cannot be ignored.

What kind of problem is it and why can't it be solved. But then I can not
ignore it? It can't be solved, but I can not ignore it?

Worse: much of the advice assumes a static text program where the only option
I have is to read the text. Not a Lisp system with data<->code.

Probably also a good idea to write a glossary, where the basic terms (form,
value, expression, scope, scope boundary, data, parameter, argument, variadic
argument, syntactic macro, failure mode, ...) are defined/described.

~~~
groovy2shoes
> To use with-open effectively, we must macroexpand it in our heads whenever
> it appears in the code.

I'd like to add that if you find yourself needing to mentally expand a macro
every time you use/read it, you have a poor abstraction. Consider going back
to the drawing board and coming up with a good abstraction instead.

~~~
lispm
Right.

For a macro which only implements a 'simple' syntactic transformation, I would
expect that I need to understand the semantics anyway. Additionally I need to
understand the syntax it implements.

What I don't want at all, is to macroexpand macro forms. If I need to
macroexpand those, then I would do this for debugging, when there is something
wrong during expansion or with the generated code. I would also do the
expansion not in my head, but using a function called 'macroexpand'.

For example as a reader, I don't want to macroexpand the following form in my
head:

    
    
        (with-open-file (foo "bar.text")
          (read foo))
    

What I really want is to understand the syntax of WITH-OPEN-FILE and semantics
of such a form. To what it transforms itself is the least important thing I
(as a code reader) want to know when dealing with macro forms.

* it's a WITH- type macro which sets up a scope.

* a WITH- type macro usually expects a variable, something which helps creating an object that is bound to the variable and a bunch of options
    
    
       (foo-var "the-file-name.text" :direction :input)
    

* it then expects a body, a sequence of forms, where the variable FOO-VAR is bound to a file

That's the syntax.

The semantics is that at runtime it opens a file as a stream and makes sure
that on all forms of exit, the stream gets closed.

To what form this actually expands (even if it is a simple transformation) is
uninteresting and may be different from implementation to implementation.

------
smel
Really brillant !

