I'm studying Clojure, and I've read that in Clojure a function definition is just data, i.e. parameters vector is just an ordinary vector. If that's the case, why can I do this
(def add (fn [a b]
(+ a b)))
but not this
(def vector-of-symbols [a b])
?
I know I normally would have to escape symbols like this:
(def vector-of-symbols [`a `b])
but why don't I have to do it in fn/defn? I assume this is due to fn/defn being macros. I tried examining their source, but they are too advanced for me so far. My attempts to recreate defn also fail, and I'm not sure why (I took example from a tutorial):
(defmacro defn2 [name param & body]
`(def ~name (fn ~param ~#body)))
(defn2 add [a b] (+ a b)) ;;I get "Use of undeclared Var app.core/defn2"
Can someone please explain, how exactly does Clojure turn data structures, especially symbols, into code? And what am I missing about the macro example?
Update Apparently, macro does not work because my project is actually in Clojurescript (in Clojure it does work). I did not think it matters, but as I progress - I discover more and more things that somehow don't work for me in with Clojurescript.
Update 2 This helps: https://www.clojurescript.org/about/differences
A function is a first-class citizen as other data in Clojure.
To define a vector you use (vector ...) or reader has syntaxic sugar [...], for a list it's (list ...) or '(...) the quote not to evaluate the list as a function call, for a set (set ...) or #{...}.
So the factory function for a function is fn (in fact fn*, that comes from Java core of Clojure, fn is a series of macros to manage to destructure and all).
(fn args body)
is a function call that returns a function, where args is a vector of argument(s) event. empty and body is a series of Clojure expressions to be evaluated with args bind to the environment. If nothing is to be evaluated it returns nil. There is also a syntactic sugar #(...) with %x as argument x and % as argument 1.
(fn ...) return a value that is a function. So
(def my-super-function (fn [a b c d] (println "coucou") (+ a b c d)))
binds the symbol my-super-function with the anonymous function returned by (fn [a b c d] (println "coucou") (+ a b c d)).
(def my_vector [1 2 3])
binds the symbol my_vector with the vector [1 2 3]
List of learning resources: https://github.com/io-tupelo/clj-template#documentation
As #jas said, your defn2 macro looks fine.
The main point is that macros are an advanced feature that one almost never needs. A macro is equivalent to a compiler extension, and that is almost never the best solution to a problem. Also keep in mind that functions can do some things macros can't.
Another point: the syntax-quote (aka backquote) ` is very different from a single quote '. In your example you want the single quote for ['a 'b]. Even better would be to quote the entire vector form '[a b].
As to your primary question, it is poorly explained how source-file text is converted into code. This is a 2-step process. The Clojure Reader consumes text string data (from a file or a literal string) and produces data structures like lists, vectors, strings, numbers, symbols. The Clojure compiler takes these data structures as input and produces java byte code that can be executed.
It is confusing because, when printed, one can't tell the difference between the text representation of a vector [1 2 3] and the text string that is input to the reader [1 2 3]. Ideally it would be color-coded or something. This problem doesn't exist in Java, etc since they don't have macros and hence there is no confusion between the source code (text) and the data structures used by a macro (not text).
For a more detailed answer on creating macros in Clojure, please see this answer.
Related
Is there a way to serialize functions at runtime in Clojure? I'd like to be able to send stateless (but not pure) functions over the wire in a serialized format (probably edn, but I'm open to anything).
For example...
If I run prn-str on a function, I don't get what I expected/wanted.
user=> (def fn1 (fn [x] (* x 2)))
#'user/fn1
user=> (def data {:test 1 :key "value"})
#'user/data
user=> (defn fn2 [x] (* x 2))
#'user/fn2
user=> (prn-str fn1)
"#object[user$fn1 0x28b9c6e2 \"user$fn1#28b9c6e2\"]\n"
user=> (prn-str data)
"{:test 1, :key \"value\"}\n"
user=> (prn-str fn2)
"#object[user$fn2 0x206c48f5 \"user$fn2#206c48f5\"]\n"
user=>
I would have wanted/expected something like this:
user=> (prn-str fn2)
"(fn [x] (* x 2))\n"
or, maybe,
user=> (prn-str fn2)
"(defn fn2 [x] (* x 2))\n"
You would have to use quote or ' to prevent evaluation and eval to force evaluation:
(def fn1 '(fn [x] (* x 2)))
(prn-str fn1) ;;=> "(fn [x] (* x 2))\n"
((eval fn1) 1) ;;=> 2
Flambo, a Clojure wrapper for Spark, uses the serializable-fn library to serialize functions (which Spark requires). Sparkling, another wrapper for Spark, uses native Clojure functions through this Java abstract class that implements the Java interface Serializable.
You have basically two choices:
pass source code (s-expressions stored as clojure data)
pass jar files and load them on the other side.
for the first option you save the source at the time the function is compiles (almost always when it is defined) and then pass the same source expression to the other computer and let it compile the same thing. so first you might make a vector of expressions:
(domain-functions '[(defn foo [x] x)
(defn bar [y] (inc y)]
then you can store this into a database and each client can pass it to read and then they will all have the same functions.
The second option depends on the fact that each time you define a function it produces a class file in the /target directory and then loads it. You can then syncronize this directory and load them on the other side. This approach is of course completely crazy, though people do crazy stuff around here. I recommend the first approach
And as a personal note:
I'm doing this now with datomic, and I have adopted the practice of putting the git-hash into the function name using a macro so I know absolutly for certain that when I call a function, I'm getting the same function I see in the editor. This brings peace of mind when running many instances that all pull from the same DB.
At some point it ceases to be Clojure, so the expectation that we can arbitrarily round trip from source to machine instructions and back is a little bit off.
We should be able to serialize a function to a byte array and send that across the wire though. I suspect you'd need to grab the function's java.lang.Class object and then pass that through a java.lang.instrument.ClassFileTransformer to get the bytes. Once you have those you can pass them through to the friendly java.lang.ClassLoader on the remote jvm.
You could use clojure.repl/source.
(with-out-str (source filter))
to get a string, or
(read-string (with-out-str (source filter)))
to get a clojure list.
There really isn't a good way, and for good reason simply shipping a function to another computer or storing it in a DB can cause lots of problems, not the least of which is that that function may require other functions that aren't on the other end.
A much better idea is to stick with data. Instead of writing the function, write the name of the function as a event, and then that even can be translated later by whatever is reading your data. Stick with data, that's the idiomatic way.
I would like to create a nil function that takes any number of symbols and sets them all to nil.
(defun clean (as many args as given by user)
(setq each-arg nil)
)
(clean x y z)
How to do this 'cleanly'?
Since you're not quoting the arguments, it has to be a macro:
(defmacro clean (&rest symbols)
`(progn
,#(mapcar (lambda (sym) (list 'setq sym 'nil))
symbols)))
Similar idea as Dmitry, but generates slightly less code:
(defmacro clean (&rest variables)
`(setq ,#(loop for var in variables nconc (list var nil))))
(macroexpand '(clean a b c d))
;; (setq a nil b nil c nil d nil)
Regarding your other questions:
simple, but time consuming way to know is to move the point to the function that you don't know and C-h f or M-xdescribe-function this will put the function name in the prompt (if it is indeed an Emacs Lisp function) and show the description and, if availably the location in the source code.
I'll try to explain, but I'm no language reference :)
defmacro - is similar to function, but it doesn't evaluate arguments. Macros are executed when your code is read and compiled into the bytecode. Their primary goal is to generate other code.
lambda - is a macro that creates an anonymous function and returns it.
mapcar - is a high-order function that applies a function to all elements of the list in succession and collects the result into a list in the order it applied the function.
&rest - is a special keyword in the function's lambda-list (i.e. the definition of parameters) which means literally that the identifier following this symbol is a list of all arguments on the right of it).
,# is a special operator used in macros, inside back-quote macros. It instructs the reader that the expression following it must be evaluated, treated as list, and all of its conses must be appended to the form that is being currently parsed.
There's something I don't understand about anonymous functions using the short notation #(..)
The following works:
REPL> ((fn [s] s) "Eh")
"Eh"
But this doesn't:
REPL> (#(%) "Eh")
This works:
REPL> (#(str %) "Eh")
"Eh"
What I don't understand is why (#(%) "Eh") doesn't work and at the same time I don't need to use str in ((fn [s] s) "Eh")
They're both anonymous functions and they both take, here, one parameter. Why does the shorthand notation need a function while the other notation doesn't?
#(...)
is shorthand for
(fn [arg1 arg2 ...] (...))
(where the number of argN depends on how many %N you have in the body). So when you write:
#(%)
it's translated to:
(fn [arg1] (arg1))
Notice that this is different from your first anonymous function, which is like:
(fn [arg1] arg1)
Your version returns arg1 as a value, the version that comes from expanding the shorthand tries to call it as a function. You get an error because a string is not a valid function.
Since the shorthand supplies a set of parentheses around the body, it can only be used to execute a single function call or special form.
As the other answers have already very nicely pointed out, the #(%) you posted actually expands to something like (fn [arg1] (arg1)), which is not at all the same as (fn [arg1] arg1).
#John Flatness pointed out that you can just use identity, but if you're looking for a way to write identity using the #(...) dispatch macro, you can do it like this:
#(-> %)
By combining the #(...) dispatch macro with the -> threading macro it gets expanded to something like (fn [arg1] (-> arg1)), which expands again to (fn [arg1] arg1), which is just want you wanted. I also find the -> and #(...) macro combo helpful for writing simple functions that return vectors, e.g.:
#(-> [%2 %1])
When you use #(...), you can imagine you're instead writing (fn [args] (...)), including the parentheses you started right after the pound.
So, your non-working example converts to:
((fn [s] (s)) "Eh")
which obviously doesn't work because the you're trying to call the string "Eh". Your example with str works because now your function is (str s) instead of (s). (identity s) would be the closer analogue to your first example, since it won't coerce to str.
It makes sense if you think about it, since other than this totally minimal example, every anonymous function is going to call something, so it'd be a little foolish to require another nested set of parens to actually make a call.
If you're in doubt what your anonymous function gets converted to, you can use the macroexpand procedure to get the representation. Remember to quote your expression before passing it to macroexpand. In this case we could do:
(macroexpand '#(%))
# => (fn* [p1__281#] (p1__281#))
This might print different names for p1__281# which are representations of the variables %.
You can also macroexpand the full invocation.
(macroexpand '(#(%) "Eh"))
# => ((fn* [p1__331#] (p1__331#)) "Eh")
Converted to more human readable by replacing the cryptic variable names by short names. We get what the accepted answers have reported.
# => ((fn* [s] (s)) "Eh")
Resources:
https://clojure.org/guides/weird_characters#_n_anonymous_function_arguments
https://clojuredocs.org/clojure.core/macroexpand
I am trying to determine whether a given argument within a macro is a function, something like
(defmacro call-special? [a b]
(if (ifn? a)
`(~a ~b)
`(-> ~b ~a)))
So that the following two calls would both generate "Hello World"
(call-special #(println % " World") "Hello")
(call-special (println " World") "Hello")
However, I can't figure out how to convert "a" into something that ifn? can understand. Any help is appreciated.
You might want to ask yourself why you want to define call-special? in this way. It doesn't seem particularly useful and doesn't even save you any typing - do you really need a macro to do this?
Having said that, if you are determined to make it work then one option would be to look inside a and see if it is a function definition:
(defmacro call-special? [a b]
(if (#{'fn 'fn*} (first a))
`(~a ~b)
`(-> ~b ~a)))
This works because #() function literals are expanded into a form as follows:
(macroexpand `#(println % " World"))
=> (fn* [p1__2609__2610__auto__]
(clojure.core/println p1__2609__2610__auto__ " World"))
I still think this solution is rather ugly and prone to failure once you start doing more complicated things (e.g. using nested macros to generate your functions)
First, a couple of points:
Macros are simply functions that receive as input [literals, symbols, or collections of literals and symbols], and output [literals, symbols, or collections of literals and symbols]. Arguments are never functions, so you could never directly check the function the symbol maps to.
(call-special #(println % " World") "Hello") contains reader macro code. Since reader macros are executed before regular macros, you should expand this before doing any more analysis. Do this by applying (read-string "(call-special #(println % \" World\") \"Hello\")") which becomes (call-special (fn* [p1__417#] (println p1__417# "world")) "Hello").
While generally speaking, it's not obvious when you would want to use something when you should probably use alternative methods, here's how I would approach it.
You'll need to call macroexpand-all on a. If the code eventually becomes a (fn*) form, then it is guaranteed to be a function. Then you can safely emit (~a ~b). If it macroexpands to eventually be a symbol, you can also emit (~a ~b). If the symbol wasn't a function, then an error would throw at runtime. Lastly, if it macroexpands into a list (a function call or special form call), like (println ...), then you can emit code that uses the thread macro ->.
You can also cover the cases such as when the form macroexpands into a data structure, but you haven't specified the desired behavior.
a in your macro is just a clojure list data structure (it is not a function yet). So basically you need to check whether the data structure a will result is a function or not when it is evaluated, which can be done like show below:
(defmacro call-special? [a b]
(if (or (= (first a) 'fn) (= (first a) 'fn*))
`(~a ~b)
`(-> ~b ~a)))
By checking whether the first element of the a is symbol fn* or fn
which is used to create functions.
This macro will only work for 2 cases: either you pass it a anonymous function or an expression.
I finally started learning functional languages (emacs lisp) and it makes explicit distinction between functions and special forms such as flow control , for example if.
Is there a fundamental/theoretical reason why special forms are distinct from functions? do any languages provide functional if?
Thanks
With eager evaluation the distinction is required, languages with lazy evaluation (i.e. Haskell) if et al. can be functions.
Eager evaluation: The function's arguments are evaluated before calling the function, and only the results are passed to the function.
Lazy evaluation: A function's arguments evaluated if and only if they are accessed.
If if was a normal function, then both its arguments—the then form and the else form—would both be evaluated before calling the if function, because that's the rule of function evaluation: evaluate all arguments to produce values, then provide that sequence of values as arguments to the function designated by the first symbol in the list.
Instead, with if what you want to do is evaluate exactly one of the then form and else form, not both. In order to suppress evaluation of one or the other, you need either a macro or a special form.
In languages like Emacs Lisp and Common Lisp, special forms are built-in language constructs. They have different evaluation rules that normal function calls. For normal function calls all arguments are evaluated. So, you can't write an IF as a normal function - the condition determines which clause gets evaluated. Also usually you can't write your own special forms - in Common Lisp there is no language construct for defining a special form (though individual implementations must have implemented the existing ones somehow. This leads to macros. With macros you can write a syntactic transformation that transforms one expression into another one. To be able to write IF as a macro, you need to have another conditional form, which you can use for the transformed code. Lisp provides conditionals as basic constructs. Let's assume COND is such a basic construct, then you could expand IF into a usage of COND.
MY-IF as a macro in Common Lisp:
(defmacro my-if (condition true-clause false-clause)
`(cond (,condition ,true-clause)
(t ,false-clause)))
So
(my-if (foo-p) 'one 'two)
gets expanded into
(cond ((foo-p) 'one)
(t 'two))
For completeness: there are no special forms in the Pico language for example, and if is a primitive function while Pico is inspired by Scheme and has eager evaluation by default.
In Scheme you could write
(define (true t f)
(t))
(define (false t f)
(f))
(define (function_if c t e)
(c t e))
and then
(function_if true (lambda () 'true) (lambda () 'false))
==> true
What makes this manageable in Pico is that you can define functional parameters that take functional arguments that are "automatically" delayed. This means that you don't have to do the wrapping inside lambdas yourself. Pico therefore has eager evaluation but with lazy evaluation on demand, bypassing the need for special forms.
So, in Scheme syntax with functional parameters you can encode booleans as:
(define (true (t) (f))
(t))
(define (false (t) (f))
(f))
Then function if becomes:
(define (function_if c (t) (e))
(c (t) (e)))
and
(function_if true 'true 'false)
==> true
As another example, the definition of the function and is (define (and p (q)) (p (q) false)).
Similarly you can define or, not, while, for, ... as functions, using the above encoding of booleans.
Short answer: No.
Long(er) answer: (if ...) requires that you control the evaluation order of the arguments. Lisp, being an eager language cannot do this in a function.
Workaround: do it in a macro:
(defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
For example:
[dsm#localhost:~]$ clisp -q
[1]> (defmacro _if (cnd true false)
(let ( (gcond (gensym))
(gresp (gensym)))
`(let ( (,gcond ,cnd) ;`#quotes
(,gresp nil))
(and ,gcond (setf ,gresp (multiple-value-list ,true)))
(and (not ,gcond) (setf ,gresp (multiple-value-list ,false)))
(values-list ,gresp))))
_IF
[2]> (_if (= 1 1) (+ 2 3) "bar")
5
[3]> (_if (= 1 2) (+ 2 3) "bar")
"bar"
[4]>
In Scala it's possible to model if with correct side-effect evaluation using call-by-name arguments.
def If[A](cond : Boolean, truePart : => A, falsePart : => A) = if (cond) truePart else falsePart
These feature can be used to model lots of new control structures as well.
IF could be a function in a functional language having call-by-name semantics (lazy evaluation), as in Lambda Calculus or Algol. In fact that is, I think, at the heart of the relationship between Turing Machines and Lambda Calculus as equivalent foundations for computing. However, in languages having side-effects (like assignments to variables) it is not much use, because when things happen is important.