Defining a function from an expression stored in a var - clojure

I asked a similar question yesterday but it seemed I had to change my approach, so I did, but now I'm sort of stuck again.
Anyway, what I want to do is something along the line of
(def bar '(* 2 %))
(#(bar) 2) ;this line doesn't work.
(#(* 2 %) 2) ;this is what I want the line that doesn't work to do.
Thing is, I want the expression stored in a var so I could do something like
(def bar2 (list (first bar) 3 (nth bar 2)))
(#(bar2) 2) ;this line obviously doesn't work either.
Maybe there's another approach than the # anonymous function reader macro.
I'm doing a project in genetic programming for uni so what I need to do is have an expression that I can change and make into a function.

(def bar '(* 2 %))
((eval (read-string (str "#" bar))) 3)
=> 6
If you used named parameter(s) in expression it would look cleaner:
(def bar '(* 2 p))
(def f-expr (concat '(fn [p]) [bar]))
((eval f-expr) 3)
=> 6

If you want to evaluate quoted expressions at run time (as opposed to compile time, à la macros), you can just use eval:
(eval '(* 10 12))
;=> 120
(def arg 12)
(def bar '(* 10 arg))
(eval bar)
;=> 120
Normally one steers clear of eval (macros will perform better, for one thing), but it might be what you want for playing with genetic algorithms.

Related

Why the difference in anonymous function definition syntax?

We can define and use an anonymous function like this:
repl=> (#(+ 10 %) 1)
11
But -> macro won't accept such anonymous functions. Say I want to add 10 and then multiply by 2. I'd try to write:
(-> 5 #(+ 10 %) #(* 2 %))
But that is not the correct code for some reason, the correct code is
(-> 5 (+ 10) (* 2))
What is the difference between (+ 10) and #(+ 10 %), and why won't -> macro accept anonymous functions defined with #()?
Here's my attempt at an explanation. There are two parts.
First, the anonymous literal syntax. When you write #(+ 10 %), it gets expanded into something that is functionally similar to the following:
(fn [x] (+ 10 x))
For ex.
=> (macroexpand '(#(+ 10 %))
Would return something like:
(fn* [p1__7230#] (+ 10 p1__7230#))
The second part. When you use the threading macro, as the docs say, the macro expands by inserting the first argument as the second item into the first form. And if there are more forms, inserts the first form as the second item in second form, and so on.
The key term here is second item. It doesn't care about what forms you are providing as arguments, it will just do an expansion using that rule.
So, to combine both the points, when you use
(-> 5 #(+ 10 %) #(* 2 %))
following the rules, it gets expanded into something that is functionally similar to this
(fn (fn 5 [x] (+ 10 x)) [y] (* 2 y))
which doesn't compile.
Also, as a side note, the form (+ 10) is not an anonymous function. It is a partial function call that gets updated with arguments during macro expansion. And by 'partial', I mean in the literal sense, not in the functional programming sense.
Update
To explain why it works when you enclose the anonymous literal within parentheses (as a comment on the question says), you can infer the results from these two rules. For ex.
=> (macroexpand '(#(+ 10 %)))
would result in the functional equivalent of
((fn [x] (+ 10 x)))
So, when an item is inserted in its second place, it would look like
((fn [x] (+ 10 x)) 5)
Which is equivalent to
(#(+ 10 %) 5)

Clojure caret as a symbol?

So I thought it would be a nice idea to name a function that calculates the exponential ^, but it seems like the caret actually does something special, as the Clojure REPL generates an error when evaluating '^. Googling mostly gave me this, so I was wondering what the actualy use for the caret in Clojure is.
(Also, would it be possible after all to name a function ^?)
^ is "the meta character" it tells the reader to add the symbol starting with ^ as metadata to the next symbol (provided it is something that implements IMetas)
user=> (def x ^:IamMeta [1 2 3])
#'user/x
user=> x
[1 2 3]
user=> (meta x)
{:tag :IamMeta}
user=>
You can learn a lot about how clojure works under the hood by looking at the meta of things, for instance functions:
user=> (meta foo)
{:ns #<Namespace user>,
:name foo, :file "NO_SOURCE_PATH",
:line 5, :arglists ([s])}
this is very often used for type hints
(defn foo [^String s] (.charAt s 1))
it is generally a good idea to turn on reflection warnings (set! *warn-on-reflection* true) and then add type hints until the warnings go away. without these Clojure will look up the type of the function operands at run-time, which saves you the trouble of fussing with types though at a slight cost.
PS: My next favorite reader character is the "dispatch" character #, it is well worth learning about it next :)
PPS: this is different in clojure 1.2.x vs clojure 1.3.x
in Clojure 1.2.1 metadata does not compose when you use the meta-character:
user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:tag :foo}
and in 1.3 it "does the right thing" and also keywords are options instead of "tags":
user=> (def foo ^:foo ^:bar [1 2 3])
#'user/foo
user=> (meta foo)
{:foo true, :bar true}
It seems to me that the answer to your question is, unfortunately, no. In Clojure, you cannot name a function ^.
I tried the following in the REPL:
user=> (println \^)
^
nil
This seems to imply that you can escape the carat (^) with a backslash. However, if I try to declare a function using \^ as a name then I get an error message:
user=> (defn \^ [n e] (cond (= e 0) 1 :else (* n (\^ n (- e 1)))))
IllegalArgumentException First argument to defn must be a symbol
clojure.core/defn (core.clj:277)
The same code works with a regular text name:
user=> (defn exp [n e] (cond (= e 0) 1 :else (* n (exp n (- e 1)))))
#'user/exp
user=> (exp 3 3)
27
I would be delighted if someone with better Clojure-fu than mine could prove me wrong! :)

How to pass optional macro args to a function

Clojure macro noob here. I have a function with some optional parameters, e.g.
(defn mk-foo [name & opt]
(vec (list* name opt)))
giving this:
user> (mk-foo "bar" 1 2 3)
["bar" 1 2 3]
I'm trying to write a macro which takes the same optional arguments and passes them transparently to an invocation of mk-foo. So far I have this:
(defmacro deffoo [name & opt]
`(def ~name ~(apply mk-foo (str name) opt)))
which has the desired effect:
user> (macroexpand '(deffoo bar 1 2 3))
(def bar ["bar" 1 2 3])
The use of apply to flatten the list opt feels clumsy. Is there an idiomatic way to do this? I'm guessing ~# is needed, but I can't get the quoting right. Many thanks.
Your intuition about using apply served you well in this case. When you have a quoted form ` and then unqote all of them it can help to think about moving the un-quoting down to the smallest part or the list. This avoids using code to generate forms that could be simply written.
user=> (defmacro deffoo [name & opt] `(def ~name [~(str name) ~#opt]))
#'user/deffoo
user=> (macroexpand '(deffoo "bar" 1 2 3))
(def "bar" ["bar" 1 2 3])
and here it is with the call to mk-foo:
(defmacro deffoo [name & opt] `(def ~name (mk-foo ~(str name) ~#opt)))
#'user/deffoo
user=> (macroexpand '(deffoo "bar" 1 2 3))
(def "bar" (user/mk-foo "bar" 1 2 3))
in this second case we move the ~ in one level and let the call to mk-foo stay quoted and only unquote the args required to build the parameter list (using splicing-unquote as you suspected)

How To Define Function From Closure

This question is related to one I asked recently.
If I rewrite (fn [n] (fn [x] (apply * (repeat n x)))) as
(defn power [n] (fn [x] (apply * (repeat n x))))`
it works just fine when used like this
((power 2) 16)
I can substitute 2 with another power, but I'd like to make a function just for squares, cubed, and so on. What is the best way to do that? I've been fiddling with it in the REPL, but no luck so far.
Using a macro for this goes entirely around his question, which was "I have a function that generates closures, how do I give those closures names?" The simple solution is:
(letfn [(power [n]
(fn [x]
(apply * (repeat n x))))]
(def square (power 2))
(def cube (power 3)))
If you really truly hate repeating def and power a few times, then and only then is it time to get macros involved. But the amount of effort you'll spend on even the simplest macro will be wasted unless you're defining functions up to at least the tenth power, compared to the simplicity of doing it with functions.
Not quite sure if this is what you're searching for, but macro templates might be it. Here's how I would write your code:
(use 'clojure.template)
(do-template [name n]
(defn name [x] (apply * (repeat n x)))
square 2
cube 3)
user> (cube 3)
;=> 27
For more complex type of similar tasks, you could write a macro that wrap do-template to perform some transformation on its arguments, e.g.:
(defmacro def-powers-of [& ns]
(let [->name #(->> % (str "power") symbol)]
`(do-template [~'name ~'n]
(defn ~'name [~'x] (apply * (repeat ~'n ~'x)))
~#(->> ns
(map #(vector (->name %) %))
flatten))))
(def-powers-of 2 3 4 5)
user> (power3 3)
;=> 27
user> (power5 3)
;=> 243
P.S.: That macro might look awkward if you're just starting with Clojure though, don't give up because of it! ;-)

Make a namespace qualified function name in a macro

I have a bunch of functions that map to and from some codes defined by an external system:
(defn translate-from-ib-size-tick-field-code [val]
(condp = val
0 :bid-size
3 :ask-size
5 :last-size
8 :volume))
(defn translate-to-ib-size-tick-field-code [val]
(condp = val
:bid-size 0
:ask-size 3
:last-size 5
:volume 8))
I'd like to make a macro to remove the duplication:
#_ (translation-table size-tick-field-code
{:bid-size 0
:ask-size 3
:last-size 5
:volume 8})
I started the macro like this:
(defmacro translation-table [name & vals]
`(defn ~(symbol (str "translate-to-ib-" name)) [val#]
(get ~#vals val#)))
The resulting function body seems right, but the function name is wrong:
re-actor.conversions> (macroexpand `(translation-table monkey {:a 1 :b 2}))
(def translate-to-ib-re-actor.conversions/monkey
(.withMeta (clojure.core/fn translate-to-ib-re-actor.conversions/monkey
([val__10589__auto__]
(clojure.core/get {:a 1, :b 2} val__10589__auto__))) (.meta ...
I'd like the "translate-to-ib-" to appear as part of the function name, instead of a prefix to the namespace, as it turned out.
How can I do this with clojure macros? If I am just doing it wrong and shouldn't use macros for this for some reason, please do let me know, but I would also like to know how to create function names like this to just improve my understanding of clojure and macros in general. Thanks!
The macro issue is twofold:
1) You're using a backtick when quoting the form passed to macroexpand, which namespace-qualifies the symbols within:
`(translation-table monkey {:a 1 :b 2})
=> (foo.bar/translation-table foo.bar/monkey {:a 1, :b 2})
where foo.bar is whatever namespace you're in.
2) You're constructing the name of the defn item using the symbol name, which, when it is namespace-qualified, will stringify to "foo.bar/monkey". Here's a version that will work:
(defmacro translation-table [tname & vals]
`(defn ~(symbol (str "translate-to-ib-" (name tname))) [val#]
(get ~#vals val#)))
Notice that we're getting the name of tname without the namespace part, using the name function.
As for whether a macro is the right solution here, probably not :-) For a simple case like this, I might just use maps:
(def translate-from-ib-size-tick-field-code
{0 :bid-size
3 :ask-size
5 :last-size
8 :volume})
;; swap keys & vals
(def translate-to-ib-size-tick-field-code
(zipmap (vals translate-from-ib-size-tick-field-code)
(keys translate-from-ib-size-tick-field-code)))
(translate-from-ib-size-tick-field-code 0)
=> :bid-size
(translate-to-ib-size-tick-field-code :bid-size)
=> 0
If speed is of the essence, check out case.
Some unsolicited advice on a different point: (get ~#vals val#) is extremely suspicious. Your macro alleges to take any number of arguments, but if it gets more than two it will just do something that doesn't make any sense. Eg,
(translation-table metric {:feet :meters}
{:miles :kilometers}
{:pounds :kilograms})
aside from being a terrible translation table, expands to code that always throws an exception:
(defn translate-to-ib-metric [val]
(get {:feet :meters}
{:miles :kilometers}
{:pounds :kilograms}
val)))
get doesn't take that many arguments, of course, and it's not really what you meant anyway. The simplest fix would be to only permit two arguments:
(defmacro translation-table [name vals]
(... (get ~vals val#)))
But note that this means the value map gets reconstructed every time the function is called - problematic if it's expensive to compute, or has side effects. So if I were writing this as a macro (though see Justin's answer - why would you?), I would do it as:
(defmacro translation-table [name vals]
`(let [vals# ~vals]
(defn ~(symbol (str "translate-to-ib-" name)) [val#]
(get vals# val#))))