Clojure macros: quoting and syntax quoting - clojure

Say I have the following code:
(defmacro test1 [x]
(list 'fn '[y]
(if (pos? x)
'(println y)
'(println (- y)))))
It does what I need, composes a function based on x, and leaves no references to x. For example, (test1 1) macroexpands into (fn* ([y] (println y))).
Now, I'd like to rewrite it using syntax quoting. This is what I have so far:
(defmacro test2 [x]
`(fn [y#]
(if ~(pos? x)
(println y#)
(println (- y#)))))
This does exactly the same, with one exception: it leaves an (if true ..) expression in the expanded expression:
(fn* ([y__12353__auto__]
(if true
(clojure.core/println y__12353__auto__)
(clojure.core/println (clojure.core/- y__12353__auto__)))))
This might not be an issue if the compiler can optimize it out. Still, is there a way I could omit it?

When you use test2 it will unquote the whole form (pos? x) which will work at compile time if it's a constant number or perhaps a gloabl that is already defined, but not if you pass a lexically scoped variable name that doesn't exist yet.
Thus, you really want this instead:
(defmacro test2 [x]
`(fn [y#]
(if (pos? ~x) ; just unquote x, not the whole predicate expression
(println y#)
(println (- y#)))))
(macroexpand '(test2 y))
; ==>
; (fn* ([y__1__auto__]
; (if (clojure.core/pos? y)
; (clojure.core/println y__1__auto__)
; (clojure.core/println (clojure.core/- y__1__auto__)))))
(defn test-it []
(let [y -9]
(test2 y)))
((test-it) 5) ; prints "-5"
Feel free to try this with your version. (hint: You'll get an Exception since clojure.lang.Symbol cannot be cast to java.lang.Number)
UPDATE
Since you want to make the function based on a constant you need to write it a little differently:
(defmacro test3 [x]
(assert (number? x) "needs to be a compile time number")
(if (pos? x)
`(fn [y#] (println y#))
`(fn [y#] (println (- y#)))))
Now you'll get an error if you use (test3 x) since x is not a number but get what you want when you evaluate (test3 -10) since -10 is a number we can work with compile time. I'm not sure you'll notice a speed improvement though since these are hardly heavy algorithms.

Related

Null pointer exception when executing loop in clojure

(defn my-loop [x]
(cond (> x 1)
((println x)
(my-loop (- x 1)))
)
)
;; => #'user/my-loop
user> (my-loop 10)
Why do i get a null pointer exception, when executing this function?
Is this not a normal recursion?
You are invoking the return of (println x) with the additional layer of parentheses. println returns nil so invoking it will lead to the NullPointerException.
To evaluate more than one form where only one is expected use the do special form, which evaluates any number of forms and returns the value of the last one:
(defn my-loop [x]
(cond (> x 1) (do
(println x)
(my-loop (- x 1)))))
In this case, when can replace a one armed cond and do
(defn my-loop [x]
(when (> x 1)
(println x)
(my-loop (- x 1))))
The code should typically look something like so:
(defn my-loop
"Some docstring"
[x]
(cond
(> x 1) (println x)
:else (my-loop (- x 1))))
Keeping to good formatting helps to see problems early.
You may also be interested in this list of documentation sources, especially the Clojure CheatSheet & the book "Getting Clojure".

What is the "name?" argument in Clojure's fn?

I am reading the book "Getting Clojure" by Russ Olsen. In chapter 8, "Def, Symbols, and Vars", there is the following function definition:
(def second (fn second [x] (first (next x))))
^^^^^^
My question is regarding the underlined second, which comes second.
At first, I thought this syntax is wrong as anonymous functions don't need a name. But as it turnes out, this syntax is correct.
Usage: (fn name? [params*] exprs*)
(fn name? ([params*] exprs*) +)
I tried comparing the following two function calls.
user> (fn second [x] (first (rest x)))
#function[user/eval5642/second--5643]
user> (fn [x] (first (rest x)))
#function[user/eval5646/fn-5647]
Besides the name of the function, there does not seem to be a difference.
Why would there be a name? argument to fn?
You can use it when creating multiple arities:
(fn second
([x] (second x 1))
([x y] (+ x y)))
or if you need to make a recursive call:
(fn second [x] (when (pos? x)
(println x)
(second (dec x))))
There are two main usages:
recursive functions (you now know the name)
user=> ((fn foo [x] (when (pos? x) (println x) (foo (dec x)))) 3)
3
2
1
nil
better stacktraces (the name will give you a better hint, where things went wrong)
user=> (map (fn bar [x] (inc x)) ["a"])
Error printing return value (ClassCastException) at clojure.lang.Numbers/inc (Numbers.java:137).
java.lang.String cannot be cast to java.lang.Number
user=> (pst)
ClassCastException java.lang.String cannot be cast to java.lang.Number
clojure.lang.Numbers.inc (Numbers.java:137)
user/eval8020/bar--8021 (NO_SOURCE_FILE:1)
clojure.core/map/fn--5866 (core.clj:2753)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:51)
clojure.lang.RT.seq (RT.java:535)
clojure.core/seq--5402 (core.clj:137)
clojure.core/seq--5402 (core.clj:137)
puget.printer.PrettyPrinter (printer.clj:529)
puget.printer/iseq-handler--1663 (printer.clj:314)
puget.printer/iseq-handler--1663 (printer.clj:312)
puget.printer/format-doc* (printer.clj:223)
(note user/eval8020/bar--8021)

Clojure: Find even numbers in a vector

I am coming from a Java background trying to learn Clojure. As the best way of learning is by actually writing some code, I took a very simple example of finding even numbers in a vector. Below is the piece of code I wrote:
`
(defn even-vector-2 [input]
(def output [])
(loop [x input]
(if (not= (count x) 0)
(do
(if (= (mod (first x) 2) 0)
(do
(def output (conj output (first x)))))
(recur (rest x)))))
output)
`
This code works, but it is lame that I had to use a global symbol to make it work. The reason I had to use the global symbol is because I wanted to change the state of the symbol every time I find an even number in the vector. let doesn't allow me to change the value of the symbol. Is there a way this can be achieved without using global symbols / atoms.
The idiomatic solution is straightfoward:
(filter even? [1 2 3])
; -> (2)
For your educational purposes an implementation with loop/recur
(defn filter-even [v]
(loop [r []
[x & xs :as v] v]
(if (seq v) ;; if current v is not empty
(if (even? x)
(recur (conj r x) xs) ;; bind r to r with x, bind v to rest
(recur r xs)) ;; leave r as is
r))) ;; terminate by not calling recur, return r
The main problem with your code is you're polluting the namespace by using def. You should never really use def inside a function. If you absolutely need mutability, use an atom or similar object.
Now, for your question. If you want to do this the "hard way", just make output a part of the loop:
(defn even-vector-3 [input]
(loop [[n & rest-input] input ; Deconstruct the head from the tail
output []] ; Output is just looped with the input
(if n ; n will be nil if the list is empty
(recur rest-input
(if (= (mod n 2) 0)
(conj output n)
output)) ; Adding nothing since the number is odd
output)))
Rarely is explicit looping necessary though. This is a typical case for a fold: you want to accumulate a list that's a variable-length version of another list. This is a quick version:
(defn even-vector-4 [input]
(reduce ; Reducing the input into another list
(fn [acc n]
(if (= (rem n 2) 0)
(conj acc n)
acc))
[] ; This is the initial accumulator.
input))
Really though, you're just filtering a list. Just use the core's filter:
(filter #(= (rem % 2) 0) [1 2 3 4])
Note, filter is lazy.
Try
#(filterv even? %)
if you want to return a vector or
#(filter even? %)
if you want a lazy sequence.
If you want to combine this with more transformations, you might want to go for a transducer:
(filter even?)
If you wanted to write it using loop/recur, I'd do it like this:
(defn keep-even
"Accepts a vector of numbers, returning a vector of the even ones."
[input]
(loop [result []
unused input]
(if (empty? unused)
result
(let [curr-value (first unused)
next-result (if (is-even? curr-value)
(conj result curr-value)
result)
next-unused (rest unused) ]
(recur next-result next-unused)))))
This gets the same result as the built-in filter function.
Take a look at filter, even? and vec
check out http://cljs.info/cheatsheet/
(defn even-vector-2 [input](vec(filter even? input)))
If you want a lazy solution, filter is your friend.
Here is a non-lazy simple solution (loop/recur can be avoided if you apply always the same function without precise work) :
(defn keep-even-numbers
[coll]
(reduce
(fn [agg nb]
(if (zero? (rem nb 2)) (conj agg nb) agg))
[] coll))
If you like mutability for "fun", here is a solution with temporary mutable collection :
(defn mkeep-even-numbers
[coll]
(persistent!
(reduce
(fn [agg nb]
(if (zero? (rem nb 2)) (conj! agg nb) agg))
(transient []) coll)))
...which is slightly faster !
mod would be better than rem if you extend the odd/even definition to negative integers
You can also replace [] by the collection you want, here a vector !
In Clojure, you generally don't need to write a low-level loop with loop/recur. Here is a quick demo.
(ns tst.clj.core
(:require
[tupelo.core :as t] ))
(t/refer-tupelo)
(defn is-even?
"Returns true if x is even, otherwise false."
[x]
(zero? (mod x 2)))
; quick sanity checks
(spyx (is-even? 2))
(spyx (is-even? 3))
(defn keep-even
"Accepts a vector of numbers, returning a vector of the even ones."
[input]
(into [] ; forces result into vector, eagerly
(filter is-even? input)))
; demonstrate on [0 1 2...9]
(spyx (keep-even (range 10)))
with result:
(is-even? 2) => true
(is-even? 3) => false
(keep-even (range 10)) => [0 2 4 6 8]
Your project.clj needs the following for spyx to work:
:dependencies [
[tupelo "0.9.11"]

factorial function for Church numerals

I'm trying to implement the factorial lambda expression as described in the book Lambda-calculus, Combinators and Functional Programming
The way it's described there is :
fact = (Y)λf.λn.(((is-zero)n)one)((multiply)n)(f)(predecessor)n
Y = λy.(λx.(y)(x)x)λx.(y)(x)x
where
(x)y is equivalent to (x y) and
(x)(y)z is equivalent to (x (y x)) and
λx.x is equivalent to (fn [x] x)
and is-zero, one, multiply and predecessor are defined for the standard church numerals. Actual definitions here.
I translated that to the following
(defn Y-mine [y] ; (defn Y-rosetta [y]
((fn [x] (y (x x))) ; ((fn [f] (f f))
(fn [x] ; (fn [f]
(y ; (y (fn [& args]
(x x))))) ; (apply (f f) args))))))
and
(def fac-mine ; (def fac-rosetta
(fn [f] ; (fn [f]
(fn [n] ; (fn [n]
(is-zero n ; (if (zero? n)
one ; 1
(multiply n (f (predecessor n))))))) ; (* n (f (dec n)))))))
The commented out versions are the equivalent fac and Y functions from Rosetta code.
Question 1:
I understand from reading up elsewhere that the Y-rosetta β-reduces to Y-mine. In which case why is it preferable to use that one over the other?
Question 2:
Even if I use Y-rosetta. I get a StackOverflowError when I try
((Y-rosetta fac-mine) two)
while
((Y-rosetta fac-rosetta) 2)
works fine.
Where is the unguarded recursion happening?
I suspect it's something to do with how the if form works in clojure that's not completely equivalent to my is-zero implementation. But I haven't been able to find the error myself.
Thanks.
Update:
Taking into consideration #amalloy's answer, I changed fac-mine slightly to take lazy arguments. I'm not very familiar with clojure so, this is probably not the right way to do it. But, basically, I made is-zero take anonymous zero argument functions and evaluate whatever it returns.
(def lazy-one (fn [] one))
(defn lazy-next-term [n f]
(fn []
(multiply n (f (predecessor n)))))
(def fac-mine
(fn [f]
(fn [n]
((is-zero n
lazy-one
(lazy-next-term n f))))))
I now get an error saying:
=> ((Y-rosetta fac-mine) two)
ArityException Wrong number of args (1) passed to: core$lazy-next-term$fn clojure.lang.AFn.throwArity (AFn.java:437)
Which seems really strange considering that lazy-next-term is always called with n and f
The body of fac-mine looks wrong: it's calling (is-zero n one) for side effects, and then unconditionally calling (multiply n (f (predecessor n))). Presumably you wanted a conditional choice here (though I don't see why this doesn't throw an arity exception, given your definition of is-zero).

Single predicate to test for "self-evaluating" atoms in Clojure

At the home site of Clojure, there is the following statement:
Strings, numbers, characters, true,
false, nil and keywords evaluate to
themselves.
Is there a single combined predicate that tests for any of these, combining string?, number?, char?, true?, false?, nil?, and keyword?. Should I just use (complement symbol?)?
Maybe I'm missing something, but you could use the following to test for any of those conditions and return true if one is true:
(defn self-eval?
[x]
(or (string? x)
(number? x)
(char? x)
(keyword? x)
(true? x)
(false? x)
(nil? x)))
It's easy enough to write a macro that asks "does the given expression evaluate to itself". In fact this is a good example of tasks that can only be done with a macro because they need to see the argument both evaluated and unevaluated.
(defmacro selfp [a] `(= ~a (quote ~a)))
#'user/selfp
user> (selfp 1)
true
user> (selfp +)
false
user> (selfp [1 2])
true
user> (selfp '(+ 1 2 3))
false
While strings, numbers, characters, keywords, and the booleans are all self-evaluating, other things such as [1 2] are as well,so this may not be a useful test in general.
Another option is to create a function that uses a map:
(defn myclassifier? [x]
(let [types-I-care-about #{java.lang.Sring ...}]
(if (types-I-care-about (type x))
true
false)))
Another option which may have better performance is to use java's dynamism:
(extend-type Object
IMyClassifier
(myclassifier? [x]
(let [c (.getClass x)]
(if (types-I-care-about (type c))
(do
(extend-type (.getClass x)
IMyClassifier
(myclassifier? [x] true))
true)
false))))
where types-I-care-about is a set of types you care about.