I have a clojure list
("mykey:1" "mykey:2" "mykey:3")
I want to use redis mget to fetch values of all keys
(mget mykey:1 mykey:2 mykey:3)
I'm using the wonderful Carmine library.. I don't have any problem with it at all but when I try to use the list in a function
(defn get-keys
[k]
(mget k))
The key k actually includes the brackets too, since it's a list. Doing:
(mget (map #(%) k))
gets me nowhere either.
How do I now split them into individual keys so I can pass it to mget? is that possible?
Thanks
When you have a collection that contains values you want to use as the arguments to a function, you should use apply.
(def args '("mykey:1" "mykey:2" "mykey:3"))
(apply mget args)
; is equivalent to the call
(mget "mykey:1" "mykey:2" "mykey:3")
Related
I want to create helper function that modifies output returned by higher-order function.
Example of higher-order function:
(def use-meta-sub (make-app-fn (make-sub :meta)))
The problem is that when using this in let like this:
(let [meta-sub (use-meta-sub props :get-me-meta-of-this)])
returns map of key-value pairs like this:
{:key-we-almost-never-need-1 nil
:key-we-almost-never-need-2 nil
:key-we-almost-never-need-3 nil
:key-we-almost-never-need-4 nil
:meta-data {:something-useful "foo"
:more-usefull "bar"
:and-so-on "baz"}}
I would like to target only this :meta-data key
I tried this and some other variations:
(defn use-meta-data-sub [props ctrl]
(:meta-data (use-meta-sub props ctrl))) ;; both with get
It does not work because (I think, that returns lazy sequence and I do not know how to actually firs evaluate it and then extract the key from output).
Is this possible without editing 1st higher-order function, and other two it contains?
(I read all documentation on clojure site and clojure-unraveled, either I do not understand them, or they do not cover this)
I have following EDN
{
:test #xyz/getXyz #abc/getAbc #fgh/getFgh "sampleString"
}
In Clojure, I have defined implementation for each of the tagged element which internally calls java functions. I have a requirement in which I need to pass return values of both #abc/getAbc and #fgh/getFgh to #xyz/getXyz as separate parameters.
In my current implementation #fgh/getFgh gets called with "sampleString". And with the output of #fgh/getFgh, #abc/getAbc gets called. And with its output #xyz/getXyz gets called.
My requirement is #xyz/getXyz should get called with return value of both #abc/getAbc and #fgh/getFgh as individual parameters.
Clojure implementation
(defn getXyz [sampleString]
(.getXyz xyzBuilder sampleString)
)
(defn getAbc [sampleString]
(.getAbc abcBuilder sampleString)
)
(defn getFgh [sampleString]
(.getFgh fghBuilder sampleString)
)
(defn custom-readers []
{
'xyz/getXyz getXyz
'xyz/getAbc getAbc
'xyz/getFgh getFgh
}
)
I want to modify getXyz to
(defn getXyz [abcReturnValue fghReturnValue]
(.getXyz xyzBuilder abcReturnValue fghReturnValue)
)
You can't do exactly what you are asking. The tag can only process the following form. That said, you can alter the syntax for your Xyz EDN so that it can support taking a vector of [Abc Fgh] pair.
{:test #xyz/getXyz [#abc/getAbc "sampleString" #fgh/getFgh "sampleString"]}
I'm not sure if you meant that getAbc still needed to take getFgh as input or not. If so, it would be more like:
{:test #xyz/getXyz [#abc/getAbc #fgh/getFgh "sampleString" #fgh/getFgh "sampleString"]}
Now your getXyz tagged reader will receive a vector of Abc and Fgh. So you'll need to change your code to grab the elements from inside the vector, something like that:
(defn getXyz [[abcReturnValue fghReturnValue]]
(.getXyz xyzBuilder abcReturnValue fghReturnValue))
This uses destructuring syntax (notice that the arguments are wrapped in an extra pair of bracket), but you could use first and second if you wanted instead, or any other way.
I have a following EDN file
:abc #request/builder/abc {
"def" #request/builder/def {
"someVector" ["sample1", "sample2"]
}
}
I have defined custom tag reader in Clojure, which internally calls java code
(defn custom-readers []
{
#request/builder/def defBuilder
#request/builder/abc abcBuilder
}
)
(defn defBuilder [params]
(.defBuilder (someJavaUtilityClass.) params)
)
(defn abcBuilder [params]
(.abcBuilder (someJavaUtilityClass.) params)
)
When I read EDN using edn/read-string, defBuilder executes first and its value gets passed to abcBuilder.
I want to reverse the order of execution without modifying EDN. I want to modify abcBuilder code such that if java call in abcBuilder returns some value then only execute defBuilder. How can I achieve this.
I tried by modifying code as below
(defn defBuilder [params]
'(.defBuilder (someJavaUtilityClass.) params)
)
(defn abcBuilder [params]
if((.abcBuilder (someJavaUtilityClass.) params)
(eval (get params "def"))
)
)
But this throws error like it "Unable to resolve someJavaUtilityClass and params". Is there a better way to solve this?
I'm afraid that's not possible. That isn't how EDN's tagged literals work. The tag handler is called after reading the form, which includes calling the tag handlers for any tagged literals in the form. In other words, the tag handlers are called inside-out.
If this weren't the case, then what a tag means will depend on where that tagged literal is situated, which is needlessly context dependent.
Check out: https://github.com/edn-format/edn#tagged-elements
Here's the relevant part:
Upon encountering a tag, the reader will first read the next element (which may itself be or comprise other tagged elements), then pass the result to the corresponding handler for further interpretation, and the result of the handler will be the data value yielded by the tag + tagged element, i.e. reading a tag and tagged element yields one value.
Also check out: https://clojure.org/reference/reader#tagged_literals
This is about the Clojure reader. And again, here is the relevant bit:
by invoking the Var #'my.project.foo/bar on the vector [1 2 3]. The data reader function is invoked on the form AFTER it has been read as a normal Clojure data structure by the reader.
Also, symbols can only contain one /, delimiting the namespace and the name. Check out: https://github.com/edn-format/edn#symbols
How do I get openid.claimed_id or any other field in a map like this?
:openid.claimed_id won't work.
{"openid.response_nonce" "2015-07-25T09:31:45ZXrcrR0Lk35St5ESZQ0tg40PbBXU=", "openid.identity" "http://steamcommunity.com/openid/id/xxx", "openid.ns" "http://specs.openid.net/auth/2.0", "openid.op_endpoint" "https://steamcommunity.com/openid/login", "openid.mode" "id_res", "openid.sig" "zuiyNzf/QLP9Ci/czElIo1Z3nE0=", "openid.signed" "signed,op_endpoint,claimed_id,identity,return_to,response_nonce,assoc_handle", "openid.assoc_handle" "1234567890", "openid.claimed_id" "http://steamcommunity.com/openid/id/xxx", "openid.return_to" "http://localhost:3000/resp"}
The keys in your map are Strings and not Keywords.
You can either use:
(get m "openid.claimed_id")
or you can first convert the String keys to Keywords and then lookup based on a Keyword:
(:openid.claimed_id (clojure.walk/keywordize-keys m))
Since a map is also a function that can do lookup on itself, the simplest way to do this is
(m "openid.claimed_id")
with m being your map.
Say I have a set like this:
#{#{"a"} #{"b"} #{"c"}}
Say I wanted to updated the middle set to make s become:
#{#{"a"} #{"be"} #{"c"}}
How would I achieve this?
(-> #{#{"a"} #{"b"} #{"c"}} (disj #{"b"}) (conj #{"be"}))
=> #{#{"a"} #{"be"} #{"c"}}
(of course there's no ordering in sets, it could well be shown in any order).