Differences between names and symbols, vars and bindings, forms and expressions

What is the relationship hierarchy between these things in Clojure?

  1. forms and expressions
  2. vars and bindings
  3. symbols and names

I recall reading somewhere that forms are a more generalized way of referring to both expressions and special forms, but I am not confident that this is the case. If it is, are there forms that are neither expressions nor special forms, and what might those be?

My understanding is that def and let can be rebound, and that, while not generally best practice to do so, this means that they are Vars, as in, variables, that can change. Does Clojure have true constants, that once set, can never be changed, such as a JavaScript const my_var = 25? If we generally do not call def and let variables, then what is/are the preferred way(s) to call them; bindings, names, or something else?

Last but not least, I am still unclear about the relationship between names and symbols. Is there overlap where all names are symbols, or all symbols are names, or is the relationship different than these? On that note, I wonder if “names” and “identifiers” are interchangeable terms in Clojure :thinking:

Thank you for helping me to clarify!

Ps. I found that reading on the Clojure website and in Clojuredocs wasn’t particularly helpful to me in answering these questions. I don’t know what I don’t know, and it’s quite possible that I missed something while reading through the above resources.

2 Likes

I don’t think such a thing is readily available, and it if were, I’d prefer not to use it because it would be an obstacle to interactive development. I need to re-define the functions and values held by vars as I refine my understanding of what I’m building. I seem to remember that this was explicitly stated as Rich’s rationale for vars but can’t find it today except for “Functions defined with defn are stored in Vars, allowing for the re-definition of functions in a running program.” on the vars reference page.

I feel like Clojure’s convention & immutable data structures solve the same problem constants aim to ameliorate in JavaScript.

If we generally do not call def and let variables, then what is/are the preferred way(s) to call them; bindings, names, or something else?

I call the result of a def a “var” and the result of a let a “binding” or a “local symbol”. I think this is supported by the special forms reference.

I’m not precisely clear what “name” means in this context. (For instance, a keyword has a name, but I suspect that’s not what you mean.) I think the straightforward answer is that yes, names (as in, identifiers for vars) are symbols (per the reader).

2 Likes

This is a very helpful answer, thank you. I especially appreciate your use of references. After working with Clojure for some time, I sometimes forget where I get my ideas/knowhow from, and desire to ask myself, “How do I know that what I believe to be true is indeed actually true?”

Here are my takeaways:

  • def makes vars
  • let makes bindings
  • names are identifiers for things such as vars and keywords
  • immutability can help a lot in problem solving, but without any mutability, problem solving could become especially difficult/inconvenient
1 Like

I tried asking the new ChatGPT-4 “Is everything in Clojure a form, or an expression?”

@dave.liepmann May I ask for your help to validate the accuracy of the chat model’s answer?

Far be it from me to disagree with our new :robot: overlords!

Seems OK to me, per https://clojure.org/reference/evaluation:

Clojure programs are composed of expressions. Every form not handled specially by a special form or macro is considered by the compiler to be an expression, which is evaluated to yield a value.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.