How do you programatically create multiple compile-time defs in clojure? - clojure

I want to create multiple defs in a file at compile time without having to type everything out. I'd like to do something like:
(ns itervals)
(loop [i 0]
(if (<= i 128)
(do
(def (symbol (str "i" i)) i)
(recur (+ i 1)))))
In that way, we define the variables i1,..., i128 in the current context. I can't figure out a way to do it at compile time without defining them all explicitly. I think macros might be the way to go, but I have no idea how.

This feels more like compile time:
(defmacro multidef[n]
`(do ~#(for [i (range n)]
`(def ~(symbol (str "i" i)) ~i))))
(multidef 128)
i0 ; 0
i127 ; 127
i128 ; unable to resolve
But I can't think of a test that will tell the difference, so maybe the distinction is false.

Try this:
(for [i (range 1 129)]
(eval `(def ~(symbol (str "i" i)) ~i)))

Related

How to identify the variable of thread-last?

Consider the following code:
(defn delete-last-line [list]
(take (- (count list) 1) list)
)
(->>
(create-list)
(delete-last-line))
Now i would like to replace delete-last-line by an anonymous function in thread-last. Something like the following, but this will not work. The problem is the i need to somehow have an identifier of the variable.
(take (- (count %) 1))
Put an extra pair of parens around your anonymous function so you're calling it; that way ->> threads into the invocation of the function, not its definition.
(->>
(create-list)
(#(take (- (count %) 1) %)))
I don't know what you mean by "somehow have an identifier of the variable", but if you want to give it a name instead of using %, you can always do that:
(println
(->>
(create-list)
((fn [lst] (take (- (count lst) 1) lst)))))

How to write clojure conditional statements

How can one translate the following code
while ((readInteger = fileInputStream.read()) != -1) {
.....
}
in clojure ? I need the value of readInteger in further parts of the code but also the '!= -1' needs to take place inside the while conditional.
some general patterns for adapting things to the Clojure syntax
move the ( to the left of the function or opperator.
move opperators to the left of the things they work on and surround with ( )
so you could start like this:
(while (not= (.read fileInputStream) -1 ... and so on.
then, since you need to use the readInteger value later in the code let's talk about naming values and looping. If you just wanted to read a value once and give it a name you could do it like this:
(let [readInteger (.read fileInputStream)]
... your code here)
Since you want to do it in a loop, then let's use loop instead of let:
(loop [readInteger (.read fileInputStream)]
... your code here
(if (not= readInteger -1)
(recur (.read fileInputStream))))
or for (which is not the "for loop" from other languages)
(for [readInteger (repeatedly #(.read fileInputStream))
:while (not= readInteger -1)]
... do somethign with readInteger ...)
For generates sequences of results rather than just looping like it does in other languages.
Then the next step in clojuring is to think about how to split the reading the data from processing it. We can:
make a sequence of all the data
process each data
something like this:
(let [data (line-seq fileInputStream)]
(map #(Integer/parseInt %) data)
...)
There are functions in the standard library for converting a great many things into sequences, and a bunch of functions for doing a great many things with sequences.
Don't solve this problem with while, which requires you to do your test at the beginning of the loop. Instead, think about a recursive function, which can decide at any part of its body whether to make the recursive call or not. Any iterative loop can be converted into a tail-recursive function using loop/recur; here's an example of how to do it with your loop.
(loop []
(let [read-integer (.read file-input-stream)]
(when (not= read-integer -1)
(...)
(recur))))
Here are two similar examples like amalloy suggested:
(ns xyz...
(:require [clojure.java.io :as io] )
(:import [java.io StringReader] ))
(newline) (newline)
(let [reader-2 (io/reader (StringReader. "first")) ]
(loop []
(let [curr-char-int (.read reader-2)]
(when (not= -1 curr-char-int)
(print (char curr-char-int) " ")
(recur)))))
(newline) (newline)
(let [reader-2 (io/reader (StringReader. "second")) ]
(loop [curr-char-int (.read reader-2)]
(when (not= -1 curr-char-int)
(print (char curr-char-int) " ")
(recur (.read reader-2)))))
With result:
> lein run
f i r s t
s e c o n d
In the first case it takes an extra let statement, but doesn't duplicate the part (.read reader-2) like the 2nd case does.
Using threading macro:
(->> (repeatedly #(.read fs))
(take-while (partial not= -1))
(map str))
Replace (map str) with whatever function you want to operate
on the stream. For example, to calculate the sum:
(->> (repeatedly #(.read fs))
(take-while (partial not= -1))
(reduce +))

Clojure macros: quoting and syntax quoting

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.

Clojure - sum up a bunch of numbers

Hey I'm doing a Project Euler question, and I'm looking to sum up all the numbers under 1000 that are multiplies of 3 or 5.
But being a clojure noob, my code just keeps returning zero.. and I'm not sure why.
(defn sum-of-multiples [max]
(let [result (atom 0)]
(for [i (range max)]
(if (or (= (rem i 3) 0) (= (rem i 5) 0))
(swap! result (+ #result i)))
)
#result))
(sum-of-multiples 1000)
Also the line (swap! result (+ #result i))) bugs me.. In C# I could do result += i, but I'm guessing there must be a better way to this in Clojure?
In Clojure - and at large in functional programming - we avoid assignment as it destroys state history and makes writing concurrent programs a whole lot harder. In fact, Clojure doesn't even support assignment. An atom is a reference type that is thread safe.
Another common trait of functional programming is that we try to solve problems as a series of data transformations. In your case you case some data, a list of numbers from 0 to 1000 exclusive, and you need to obtain the sum of all numbers that match a predicate. This can certainly be done by applying data transformations and completely removing the need for assignment. One such implementation is this:
(->> (range 1000)
(filter #(or (= (rem % 3) 0) (= (rem % 5) 0)))
(reduce +))
Please understand that a function such as the one you wrote isn't considered idiomatic code. Having said that, in the interest of learning, it can be made to work like so:
(defn sum-of-multiples [max]
(let [result (atom 0)]
(doseq [i (range max)]
(if (or (= (rem i 3) 0) (= (rem i 5) 0))
(swap! result #(+ % i)))
)
#result))
(sum-of-multiples 1000)
for returns a lazy sequence but since you're simply interested in the side-effects caused by swap! you need to use doseq to force the sequence. The other problem is that the second argument to swap! is a function, so you don't need to deref result again.
for is a list comprehension that return a lazy sequence, you have to traverse it for your code to work:
(defn sum-of-multiples [max]
(let [result (atom 0)]
(dorun
(for [i (range max)]
(if (or (= (rem i 3) 0) (= (rem i 5) 0))
(swap! result + i))))
#result))
An equivalent, more idiomatic implementation using for:
(defn sum-of-multiples [max]
(reduce +
(for [i (range max)
:when (or (zero? (rem i 3))
(zero? (rem i 5)))]
i)))
The other answers are good examples of what I alluded to in my comment. For the sake of completeness, here's a solution that uses loop/recur, so it may be easier to understand for someone who's still not comfortable with concepts like filter, map or reduce. It also happens to be about 30-40% faster, not that it really matters in this case.
(defn sum-of-multiples [max]
(loop [i 0
sum 0]
(if (> max i)
(recur (inc i)
(if (or (zero? (rem i 3)) (zero? (rem i 5)))
(+ sum i)
sum))
sum)))

defmacro to generate another defmacro

I have run into this problem... I have two macros that look very similar
(import java.lang.management.ManagementFactory)
(defmacro with-thread-manager [tm & body]
{:pre [(and (vector? tm) (= 1 (count tm)))]}
`(let [~(first tm) (ManagementFactory/getThreadMXBean)]
~#body))
(defmacro with-os-manager [tm & body]
{:pre [(and (vector? tm) (= 1 (count tm)))]}
`(let [~(first tm) (ManagementFactory/getOperatingSystemMXBean)]
~#body))
they are used as follows:
(defn thread-count []
(with-thread-manager [tm] (.getThreadCount tm)))
(thread-count)
;; => 12
(defn application-cpu-time []
(with-os-manager [osm] (.getProcessCpuTime osm)))
(application-cpu-time)
;; => 71260000000
I wish to generalise the two with-*-manager into another macro so that I can simpify them like this:
(defmanagementblock with-thread-manager (ManagementFactory/getThreadMXBean))
(defmanagementblock with-os-manager (ManagementFactory/getOperatingSystemMXBean))
so the easiest way I knew was to change the macro a little bit
(defmacro with-thread-manager [tm & body]
{:pre [(and (vector? tm) (= 1 (count tm)))]}
(apply list 'let [(first tm) '(ManagementFactory/getThreadMXBean)]
body))
and to write the block:
(defmacro defmanageblock [name MANAGER]
(list 'defmacro name '[tm & body]
'{:pre [(and (vector? tm) (= 1 (count tm)))]}
(list 'apply 'list ''let (vector '(first tm) 'MANAGER)
'body)))
everything goes well except the MANAGER does not quote properly. I've tried a bunch of quoting and unquoting option like ' , ` , ~' and many other variations of it. but it does not give the right value.
One reasonable solution, if you don't mind keeping track of a few scopes in your head:
(defmacro defmanagedblock [name mgr]
`(defmacro ~name [tm# & body#]
{:pre [(and (vector? tm#)) (= 1 (count tm#))]}
`(let [~(first tm#) ~'~mgr]
~#body#)))
If you define defmanageblock to be a function that takes a symbol describing the factory to use which returns the s-expression as a list then you would have two macros that call functions instead of nested macros . In most cases doing the real code generation work in functions rather than macros makes the code easier to reason about and test