How can one use named parameters when running queries using Yesql? For instance, given the following query
-- name: example
select * from table1 where col1=:value1 and col2=:value2
i'd like to use the following code:
(defquery q "query.sql")
(q db {:value1 "A" :value2 "B"})
Right now, Yesql treats the map as a single positional parameter.
Thanks!
The current version of Yesql - 0.4.0 - does not support easily this. The named parameters are only for documentation. You can see them if you do (doc q), but you can't use them to run the query. The author of Yesql has mentioned that they're planning exactly what you want for Yesql 0.5.
What I've done in the same situation is to just manually wrap the query into another function:
(defn q1 [db {:keys [value1 value2]}] (q db value1 value2))
It's a bit cumbersome, but it works.
It is possible to do this automatically even without improving Yesql, but... this is going to be a bit of a hack. You probably do not want to do this.
We can define a function similar to apply that uses the query function's metadata to get the arguments in the right order from the map of named parameters.
(defn apply-with-arglist-fn [f arglist & args]
(let [nargs (butlast args)
kwargs (last args)]
(apply f (concat nargs (map #(get kwargs (keyword %))
(drop (count nargs) arglist))))))
;; Let's define a macro to make calling this a bit easier.
(defmacro apply-with-arglist [f & args]
"Applies fn f to the arguments in a map by matching them with f's
arglist. Works like apply, except that the last parameter should be
a map of keyword arguments. For example:
(defn f [a b c] ...)
(apply-with-arglist f 1 {:b 2 :c 3})
This is equivalent to calling (f 1 2 3)."
`(apply-with-arglist-fn ~f (first (:arglists (meta (var ~f)))) ~#args))
You can use this to run the query:
(apply-with-arglist q db {:value1 "A" :value2 "B"})
Really, though, there should be error handling and dealing with corner cases. A better approach would be to see if you can help the Yesql author to get Yesql 0.5 ready.
Related
I'm building a datomic schema and have the following at the foot of my clj file which defines and transacts schema and initial data. The functions being called below each call d/transact.
(defn recreate-database []
"To recreate db after running delete-database in bin/repl"
(pt1-transact-schema)
(pt1-transact-data)
(pt2-transact-schema)
(pt2-transact-data)
(pt3-transact-schema)
(pt3-transact-data))
By default we only see the return value of the last form, but I'd like to see, or save, the result of each of the six function calls.
Wondering what a nice way to do this is.
Thought of something like (map (comp println eval) [functions]), but that's not right.
there is also a nice functional composition function called juxt:
user> ((juxt + - * /) 1 2)
;;=> [3 -1 2 1/2]
user> ((juxt (constantly 1) (constantly 2) (constantly 3)))
;;=> [1 2 3]
or in your case:
(def recreate-database (juxt pt1-transact-schema
pt1-transact-data
pt2-transact-schema
pt2-transact-data
pt3-transact-schema
pt3-transact-data))
You could try this:
(defn recreate-database []
"To recreate db after running delete-database in bin/repl"
(mapv #(%) [pt1-transact-schema
pt1-transact-data
pt2-transact-schema
pt2-transact-data
pt3-transact-schema
pt3-transact-data]))
The expression #(%) is a shorthand notation for a lambda function that takes one argument, representing a function, and calls that function. If you find it more readable, you can replace that expression by (fn [f] (f)).
With datomic, all you need is a connection and a list of tx-data. Then you can use map to return the transact result on each step (i.e. each tx-data):
(defn recreate-database [conn & tx-data]
(->> tx-data
(map (partial d/transact conn))
doall))
This Clojure code on GitHub refers to the Unified Update Model.
Could you explain how the fixing function works well with the Unified Update Model?
(defn fixing
"A version of fix that fits better with the unified update model: instead of multiple clauses,
additional args to the transform function are permitted. For example,
(swap! my-atom fixing map? update-in [k] inc)"
[x pred transform & args]
(if ((as-fn pred) x)
(apply (as-fn transform) x args)
x))
The unified update model is the API convention whereby objects of various reference types can be updated in a consistent way, albeit with specialized functions:
;; Atoms
(swap! the-atom f …)
;; Agents
(send the-agent f …)
(send-off the-agent f …)
;; send-via takes an additional initial argument, but otherwise
;; follows the same convention (and of course it's an exact match
;; when partially applied – (partial send-via some-executor))
(send-via executor the-agent f …)
;; Refs
(dosync
(alter the-ref f …)
(commute the-ref f…))
In each case f is the function that should be used to update the value held by the Atom / Agent / Ref, … are additional arguments, if any (e.g. (swap! the-atom f 1 2 3)), and the result of the call is that the reference will atomically assume the value (f old-value …) – although exactly when that will happen with respect to the swap! / alter / send / … call depends on the reference type in question and the update function used.
Here's an example:
(def a (atom 0))
(swap! a - 5)
#a
;= -5
Vars are generally not meant to be used for the same purposes that one might use the above-mentioned reference types for, but they also have an update function with the same contract:
(alter-var-root #'the-var f …)
Finally, the update and update-in functions are worth mentioning in this connection; in effect, they extend the unified update model convention to values – now of course, values are immutable, so calling update or update-in does not result in any object being visibly changed, but the return value is produced similarly as the result of applying an update function to a preexisting value and possibly some extra arguments:
(update {:foo 1} :foo inc)
;= {:foo 2}
The fixing function quoted in the question works better than fix (defined in the same namespace) in the context of UUM update calls, because it can be passed multiple arguments in a way that meshes well with how UUM update functions like swap! work, whereas with fix you'd have to use an anonymous function:
;; the example from the docstring of fixing
(swap! my-atom fixing map? update-in [k] inc)
;; modified to use fix
(swap! my-atom fix map? #(update-in % [k] inc))
The more I think about this problem, the more wrong it seems...
I have defined in my program something like a 'map constructor'. The idea behind this is that I have a generic map structure to handle some 'items' but I want to enforce some defaults for specific kind of items.
The problem that I have is that this 'map constructor' has a k-v pair, and that pair's value should be determined by the function that consumes this map (it might get clearer in the following example).
My first idea was to quote an expression in the value and then do an eval on it in the said function. The second idea was to replace the value with a fn, but this seems to return something similar to the quoted expression.
Let me try to depict the problem:
The model resulting map should be something like {:a 1 :b 2 :c 3}
The constructor is something like
(defn cons-field [b]
{:a (fn [name] (str name "!"))
:b b
:c "default"})
The item is created (def a-field (cons-field 5))
The calling function that consumes the map is something like
(defn the-function [name field]
(str (get-in field [:a])))
Now what I need is this :a's value to be a function of the parameter name in 'the-function'. Of course the last function is not working and I'm not sure if it's the correct approach anyway. The ':a' key is not always a fn; sometimes it's just a string literal. Any ideas?
Cheers!
So this is how I solved this problem after the comments of A. Webb and Jeremy Heiler.
The initial constructor was changed to this:
(defn cons-field [b]
{:a nil ; either delete completely or comment that
; the case will be handled by the caller
:flag xx ; true or :case-qualifier
:b b
:c "default"})
The calling func was changed to this:
(defn the-function [name field]
(let [case-q (:flag field)]
(cond
(= case-q :case-qualifier) (get-name name) ; you can have many different cases
; conciser using constants for these qualifiers
(...) ()))) ; else as normal
Then the logic initially put in the map goes in a different func:
(defn get-name [name] (str name "!"))
Hope this helps someone else :)
It is not really possible to understand your problem based on what you have posted. All I can do for you is tell you what your provided code does and guess what you would want it to do.
(def r (cons-field 5)) creates a hash-map r with (r :b) = 5, (r :c) = "default" and (r :a) = (fn [name] (str name "!")). As you can see, neither the result of (r :a) nor the result of (r :c) is related to r or 5.
If the results described above is what you want, it would be only logical to do some refactoring:
(def default-field {:a (fn [name] (str name "!"))
:c "default"})
(def cons-field (partial assoc default-field :b))
Regarding the-function: A call to (get-in field [:a]) is the same as (field :a) and will return the function (fn [name] ...). the-function will stringify this fn using str and most likely return something like "user.fn$23092...."
If you want the-function to return the result of calling (fn [name] ...) with name as passed to the function, you need to change your the-function as follows:
(defn the-function
[name field]
(str ((field :a) name)))
If you want the function to return something else based on the actual value of :a, you could check if it is a function and invoke it with name, otherwise return the value.
(defn the-function
[name field]
(when-let [v (field :a)]
(or (when (fn? v)
(v name))
v)))
Reading from your own answer now I am even more confused what actual problem you are trying to solve, but I hope that this answer could provide help.
I am working my way through labrepl and I saw some code that follows this pattern:
;; Pattern
(apply #(apply f %&) coll)
;; Concrete example
user=> (apply #(apply + %&) [1 2 3 4])
10
This seems to be equivalent to this pattern:
;; Pattern
(apply f coll)
;; Concrete example
user=> (apply + [1 2 3 4])
10
Are these patterns equivalent? If not, what's the difference and when would you use one over the other?
I took the former pattern from the step function in the cellular-automata lab of labrepl:
(defn step
"Advance the automation by one step, updating all cells."
[board]
(doall
(map (fn [window]
(apply #(apply map brians-brain-rules %&)
(doall (map torus-window window))))
(torus-window board))))
Update: I added a concrete example of each pattern to help make the question clearer.
No, there is no difference. There is no reason to write the longer form; I can only assume it was arrived at by gradual changes to code that made sense at one time.
Essentially, both forms accomplish the same thing and are more or less the same. Each provides a way to introduce an anonymous function.
Using #(... is a Clojure reader shorthand for an anonymous function. It is kind of equivalent to (fn [arg1 & args]... , but you cannot embed one #(... anonymous function inside another, and arguments are expressed as % %2... or %1 %2... rather than with vector binding (fn [arg & args].
Both are methods to express an anonymous function. #(... is used for simpler functions, and (fn... is used for more detailed functions.
#(... tends to make things look a little neater.
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#))))