I found this line of Clojure code: #(d/transact conn schema-tx). It's a Datomic statement that creates a database schema. I couldn't find anything relevant on Google due to difficulties searching for characters like "#".
What does the 'at' sign mean before the first parenthesis?
This is the deref macro character. What you're looking for in the context of Datomic is at:
http://docs.datomic.com/transactions.html
under Processing Transactions:
In Clojure, you can also use the deref method or # to get a
transaction's result.
For more on deref in Clojure, see:
http://clojuredocs.org/clojure_core/clojure.core/deref
Here is a useful overview of Clojure default syntax and "sugar" (i.e. macro definitions).
http://java.ociweb.com/mark/clojure/article.html#Overview
You'll find explained the number sign #, which indicates regex or hash map, the caret ^, which is for meta data, and among many more the "at sign" #. It is a sugar form for dereferencing, which means you get the real value the reference is pointing to.
Clojure has three reference types: Refs, Atoms and Agents.
http://clojure-doc.org/articles/language/concurrency_and_parallelism.html#clojure-reference-types
Your term #(d/transact conn schema-tx) seems to deliver a reference to an atom, and by the at sign # you defer and thus get the value this reference points to.
BTW, you'll find results with search engines if you look e.g. for "Clojure at sign". But it needs some patience ;-)
The # is equivalent to deref in Clojure. transact returns a future which you deref to get the result. deref/# will block until the the transaction completes/aborts/times out.
Related
I've been learning Clojure and am a good way through a book on it when I realized how much I'm still struggling to interpret the code. What I'm looking for is the abstract structure, interface, or rules, Clojure uses to parse code. I think it looks something like:
(some-operation optional-args)
optional-args can be nearly anything and that's where I start getting confused.
(operation optional-name-string [vector of optional args]) would equal (defn newfn [argA, argB])
I think this pattern holds for all lists () but with so much flexibility and variation in Clojure, I'm not sure. It would be really helpful to see the rules the interpreter follows.
You are not crazy. Sure it's easy to point out how "easy" ("simple"? but that another discussion) Clojure syntax is but there are two things for a new learner to be aware of that are not pointed out very clearly in beginning tutorials that greatly complicate understanding what you are seeing:
Destructuring. Spend some quality time with guides on destructuring in Clojure. I will say that this adds a complexity to the language and is not dissimilar from "*args" and "**kwargs" arguments in Python or from the use of the "..." spread operator in javascript. They are all complicated enough to require some dedicated time to read. This relates to the optional-args you reference above.
macros and metaprogramming. In the some-operation you reference above, you wish to "see the rules the interpreter follows". In the majority of the cases it is a function but Clojure provides you no indication of whether you are looking at a function or a macro. In the standard library, you will just need to know some standard macros and how they affect the syntax they headline. (e.g. if, defn etc). For included libraries, there will typically be a small set of macros that are core to understanding that library. Any macro will to modify, dare I say, complicate the syntax in the parens you are looking at so be on your toes.
Clojure is fantastic and easy to learn but those two points are not to be glossed over IMHO.
Before you start coding with Clojure, I highly recommend studying functional programming and LISB. In Clojure, everything is a prefix, and when you want to run and specific function, you will call it and then feed it with some arguments. for example, 1+2+3 will be (+ 1 2 3) in Clojure. In other words, every function you call will be at the start of a parenthesis, and all of its arguments will be follows the function name.
If you define a function, you may do as follow:
(defn newfunc [a1 a2]
(+ 100 a1 a2))
Which newfunc add 100 and a1 and a2. When you call it, you should do this:
(newfunc 1 2)
and the result will be 103.
in the first example, + is a function, so we call it at the beginning of the parenthesis.
Clojure is a beautiful world full of simplicity. Please learn it deeply.
I am relatively new to Clojure and can't quite wrap my mind around the difference between reader macros and regular macros, and why the difference is significant.
In what situations would you use one over the other and why?
Reader macros change the syntax of the language (for example, #foo turns into (deref foo)) in ways that normal macros can't (a normal macro wouldn't be able to get rid of the parentheses, so you'd have to do something like (# foo)). It's called a reader macro, because it's implemented in the read pass of the repl (check out the source).
As a clojure developer, you'll only create regular macros, but you'll use plenty of reader macros, without necessarily considering them explicitly.
The full list of reader macros is here: https://clojure.org/reference/reader and includes common things like # ', and #{}.
Clojure (unlike some other lisps) doesn't support user-defined reader macros, but there is some extensibility built into the reader via tagged literals (e.g. #inst or #uuid)
tl;dr*
Macros [normal macros] are expanded during evaluation (E of REPL), tied to symbols, operate on lisp objects, and appear in the first, or "function", part of a form. Clojure, and all lisps, allow defining new macros.
Reader macros run during reading, prior to evaluation, are single characters, operate on a character string, prior to all the lisp objects being emitted from the reader, and are not restricted to being in the first, or "function", part of a form. Clojure, unlike some other lisps, does not allow defining new reader macros, short of editing the Clojure compiler itself.
more words:
Normal non-reader macros, or just "macros", operate on lisp objects. Consider:
(and 1 b :x)
The and macro will be called with two values, one value is 1 and the other is a list consisting of the symbol b (not the value of b) and the keyword :x. Everything the and macro is dealing with is already a lisp (Clojure) value.
Macro expansion only happens when the macro is at the beginning of a list. (and 1 2) expands the and macro. (list and) returns an error, "Can't take value of a macro"
The reader is reasponsible for turning a character string into In Clojure a reader macro is a single character that changes how the reader, the part responsible for turning a text stream into lisp objects, operates. The dispatch for Clojure's lisp reader is in LispReader.java. As stated by Alejandro C., Clojure does not support adding reader macros.
Reader macros are one character. (I do not know if that is true for all lisps, but Clojure's current implementation only supports single character reader macros.)
Reader macros can exist at any point in the form. Consider (conj [] 'a) if the ' macro were normal, the tick would need to become a lisp object so the code wold be a list of the symbol conj, an empty vector, the symbol ' and finally the symbol a. But now the evaulation rules would require that ' be evaluated by itself. Instead the reader, upon seeing the ' wraps the complete s-exp that follows with quote so that the value returned to the evaluator is a list of conj, an empty vector, and a list of quote followed by a. Now quote is the head of a list and can change the evaluation rules for what it quotes.
Talking shortly, a reader macros is a low-level feature. That's why there are so few of them (just #, quiting and a bit more). Having to many reader rules will turn any language into a mess.
A regular macro is a tool that is widely used in Clojure. As a developer, you are welcome to write your own regular macroses but not reader ones if you are not a core Clojure developer.
Your may always use your own tagged literals as a substitution of reader rules, for example #inst "2017" will give you a Date instance and so forth.
code include something like '(1+2) in Clojure will cause a java.lang.RuntimeException, which leaves a error message "Unmatched delimiter: )".
But in any other lisp dialect I've ever used like Emacs Lisp or Racket, '(1+2) will just return a list, which should act like this because with the special form quote, anything in the list should not be evaluate.
So I just wonder is that because of the limitation of JVM so these codes can't act like how they act in other dialects? Or is it a bug of Clojure? Or maybe there is something different between the definition of quote in Clojure and other lisp dialects?
These are artifacts of the way tokenizers are set in different languages. In Clojure, if a token starts with a digit, it is consumed until the next reader macro character (that includes parentheses among other things,) whitespace or end of file (whitespace includes comma.) And what's consumed must be a valid number, which includes integer, float and rational. So when you feed '(1+2) to the reader, it consumes 1+2 as one token, which then fails to match against integer, float or rational number patterns. After that, the reader tries to recover, which resets its state. In this state, a ) is unmatched.
Try to enter '(1 + 2) instead (mind the spaces around +,) you will see exactly what you expect.
I'm trying to figure out if there is a macro similar to delay in clojure to get a lazy expression/ variable that can be evaluated later.
The use case is a default value for Map.get/3, since the default value comes from a database call, I'd prefer it to be called only when it's needed.
Elixir's macro could be used for writing simple wrapper function for conditional evaluation. I've put one gist in the following, though it may be better/smarter way.
https://gist.github.com/parroty/98a68f2e8a735434bd60
"Generic" laziness is a bit of a tough nut to crack because it's a fairly broad question. Streams allow laziness for enumerables but I'm not sure what laziness for an expression would mean. For example what would a lazy form of x = 1 + 2 be? When would it be evaluated?
The thought that comes to mind for a lazy form of an expression is a procedure expression:
def x, do: 1 + 2
Because the value of x wouldn't be calculated until the expression is actually invoked (as far as I know). I'm sure others will correct me if I'm wrong on that point. But I don't think that's what you want.
Maybe you want to rephrase your question--leaving out streams and lazy evaluation of enumerated values.
One way to do this would be using processes. For example the map could be wrapped in a process like a GenServer or an Agent where the default value will be evaluated lazy.
The default value can be a function which makes the expensive call. If Map.get/3 isn't being used to return functions you can check if the value is a function and invoke it if it is returned. Like so:
def default_value()
expensive_db_call()
end
def get_something(dict, key) do
case Map.get(dict, key, default_value) do
value when is_fun(value) ->
value.() # invoke the default function and return the result of the call
value ->
value # key must have existed, return value
end
end
Of course if the map contains functions this type of solution probably won't work.
Also check Elixir's Stream module. While I don't know that it would help solve your particular problem it does allow for lazy evaluation. From the documentation:
Streams are composable, lazy enumerables. Any enumerable that generates items one by one during enumeration is called a stream. For example, Elixir’s Range is a stream:
More information is available in the Stream documentation.
Map.get_lazy and Keyword.get_lazy hold off on generating the default until needed, links the documentation below
https://hexdocs.pm/elixir/Map.html#get_lazy/3
https://hexdocs.pm/elixir/Keyword.html#get_lazy/3
You can wrap it in an anonymous function, then it will be evaluated when the function is called:
iex()> lazy = fn -> :os.list_env_vars() end
#Function<45.79398840/0 in :erl_eval.expr/5>
iex()> lazy.()
I have a string which will evaluate to true or false, can I use macro and pass the string as parameter? I write the following, but the result is string of (= 0 0) instead of true. How to get true result?
(def a "(= 0 0)")
(defmacro test [code-string] code-string)
(test a)
update:
The purpose is replace dynamic SQL. Currently we store code like 'column_a > 1' in database, and then we will get the code, and assemble a sql like
select case when column_a>1 then 0 else 1 end as result from table
There are many such code, and I hope to use clojure run in parallel to speed it up. To use clojure I could store '(> row["column_a"] 1)' in database, and then in jdbc looping, call (> row["column_a"] 1) to do my logic, like storing some code section in database and need to run it.
As TaylanUB already said, Clojure provides eval to evaluate some expression at run-time. However, using eval is frowned upon unless you have very good reasons to use it. It's not clear what you're really intending to do, so it would be helpful to provide a more real world example. If you don't have one, you don't need eval.
Similarly, macros are used to transform code and are not run at run-time, instead the code to which the macro evaluates gets run. The typical approach would be to try to solve a problem with a mere function, only if a macro would buy you something in terms of applicability to a wider range of code, consider turning the code into a macro. Edit: take a look at some introduction to macros in Clojure, e.g. this part from Clojure from the ground up
No, you cannot directly use a string as code. Defmacro takes s-expressions not strings. Clojure might have something like read which can parse a string and make an s-expression out of it which you might then be able to execute as code via something like eval.
There is usually no good reason to put code in strings or other data structures which will exist during program execution anyway, try to just work with first-class functions instead. Or mention the precise problem you're trying to solve and people might be able to give better answers. This might be an instance of the XY problem.
Note: I don't know Clojure, but all of this is pretty Lisp-generic.
(defn eval-code [code-string]
(eval (read-string code-string)))
(eval-code "(= 0 0)")
;; you don't need macro here.