This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-10-27
Channels
- # aws (3)
- # aws-lambda (8)
- # bangalore-clj (1)
- # beginners (155)
- # boot (13)
- # cider (88)
- # cljs-dev (3)
- # cljsrn (9)
- # clojure (120)
- # clojure-india (1)
- # clojure-italy (2)
- # clojure-norway (1)
- # clojure-romania (2)
- # clojure-russia (41)
- # clojure-spec (4)
- # clojure-uk (34)
- # clojurescript (68)
- # core-logic (16)
- # cursive (11)
- # data-science (9)
- # datomic (19)
- # dirac (6)
- # duct (20)
- # emacs (7)
- # events (2)
- # figwheel (4)
- # fulcro (12)
- # graphql (1)
- # hoplon (68)
- # klipse (1)
- # leiningen (7)
- # lumo (11)
- # off-topic (9)
- # onyx (114)
- # pedestal (4)
- # protorepl (15)
- # re-frame (60)
- # reagent (3)
- # ring (18)
- # shadow-cljs (15)
- # spacemacs (82)
Hello, How do I write a function/macro where I can call another function (not mine) with a quoted structure as an argument. For example:
(another-fun '[:someconfig :val :anotherkey :constkey :myvalue :dynamicvalue])
Where I get the value for :myvalue
through some var. I have to construct this quoted expression with most of them as is, but one value evaluated.I tried something like:
(defn my-fn [mval] (another-fun `[:someconfig :val :anotherkey :constkey :myvalue ~mval]))
but the syntax quote qualifies those keywords!@neupsh Why does another-fun
need a quoted value and not just a regular value?
@seancorfield it is what the function takes as argument
Are you sure?
A quoted vector evaluates to just the vector so this ought to work:
(defn my-fn [mval] (another-fun [:someconfig :val :anotherkey :constkey :myvalue mval]))
Unless another-fun
is doing something very weird and non-idiomatic...?
@seancorfield hmm, I never thought of checking without the quotes.. I will try it and see how it goes
boot.user=> (defn another-fun [v] (reduce + 0 v))
#'boot.user/another-fun
boot.user=> (another-fun [1 2 3 4])
10
boot.user=> (another-fun '[1 2 3 4])
10
boot.user=> (defn my-fun [my-val] (another-fun [1 2 3 my-val]))
#'boot.user/my-fun
boot.user=> (my-fun 4)
10
boot.user=> (my-fun '4)
10
See how '4
evaluates to just 4
and how quoting the vector (in the second call) makes no difference.
On the other hand, you do need a quote for a list but you can construct it dynamically with list
:
boot.user=> (another-fun (1 2 3 4))
java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.IFn
boot.user=> (another-fun '(1 2 3 4))
10
boot.user=> (defn my-fun [my-val] (another-fun (list 1 2 3 my-val)))
#'boot.user/my-fun
boot.user=> (my-fun 4)
10
boot.user=> (my-fun '4)
10
Hope that helps @neupsh
@seancorfield actually using it directly did not work. let me try to write an actual similar function. I think I may be approaching the problem in wrong way!
I am writing a small function which can query datomic db for entities using various attributes
(defn find-user-by[conn attrkw value]
(let [user (d/q '[:find ?e
:in $ ?attr
:where [?e attrkw ?attr]]
(d/db conn) value)]
(touch conn user)))
@seancorfield my function looks something like above
Instead of writing a different function for querying user entity using :user/first-name
or :email
etc, I thought of writing one and passing :user/first-name
dynamically to the datomic q
function
Ah, and you need the ?e
to not resolve, right?
(defn find-user-by[conn attrkw value]
(let [user (d/q [:find '?e
:in '$ '?attr
:where ['?e attrkw '?attr]]
(d/db conn) value)]
(touch conn user)))
Quote the symbols you don't want evaluated instead of the whole vector.
@seancorfield Thanks a lot, it worked! I was trying it wrong 😛 Instead of quoting the ones that should be quoted, I was tyring to quote the whole thing and unquote only the attrkw
If it gets too frustrating, to keep quoting bits of it, remember that you can do stuff like
(conj '[:find ?e
:in $ ?attr
:where] (assoc '[?e _ ?attr] 1 attrkw))
(a vector is associative on its indices so you can just swap in a new value for the _
)
Awesome, I was wondering if I can construct expressions like this. I was not sure if it works when I need everything quoted
"It's just data" 🙂
Thanks again @seancorfield I am calling it a day now
boot.user=> (let [query '[:find ?e
#_=> :in $ ?attr
#_=> :where [?e _ ?attr]]]
#_=> (assoc-in query [(dec (count query)) 1] :user/name))
[:find ?e :in $ ?attr :where [?e :user/name ?attr]]
^ @neupsh(although that's a bit horrible really)
You'll need to be a bit more specific, otherwise the answer will just be "no"...
Do you have an example of it "acting funny" @fedreg?
Sorry.... shot in the dark. Have gotten some null pointer exceptions randomly when I'm definitely just feeding it a string and the function is working just fine in the repl. (clojure.string/replace "123-456-asdf" #"[^0-9]+" "")
I think you'll only get NPEs from it if you pass it a nil
as the string argument...
Thanks @seancorfield I just can't seem to replicate that so thought i'd check in the remote chance there was some known issue. There never is but it makes me hopeful none the less.
@fedreg I bet if you add an assert on the value you're passing to replace
you'll get an assertion failure
If you're on Clojure 1.9, you could spec
(with s/fdef
) the function that calls replace
and instrument
it and see if you can trap the nil
value going in...
i see clojure.java.time has used ztellman's import vars macro from potemkin so you don't have to remember all of the sub namespaces
why don't you like that. i haven't run into any pain from that so i'm wondering what to be on the lookout for
it is bad technically because then the aot compiled clojure code would end up in the default package, and it is unneighborly because you are inviting name clashes
unsurpisingly, the people with "contributor" and "owner" badges for that style guide are in the wrong
why "unsurprisingly"? Generally I've found the style guide to be a good rough description of Clojure idiom.
Hi, I've got some core.logic question, i've posted it in core.logic chan but no responses, so I'm trying here: i'm doing something wrong here but cannot find what:
(defn zipwitho [rel l1 l2 l3]
(conde
[(== () l1) (== () l2) (== () l3) l/succeed]
[(fresh [fl1 rl1 fl2 rl2 fl3 rl3]
(l/conso fl1 rl1 l1)
(l/conso fl2 rl2 l2)
(l/conso fl3 rl3 l3)
(rel fl1 fl2 fl3)
(zipwitho rel rl1 rl2 rl3))]))
(run 1000 [q]
(fresh [a b]
(== q [a b])
(zipwitho
(fn [x y z]
(l/all
(fd/in x y z (fd/interval 10))
(fd/+ x y z)))
a
b
[10 10])))
;=>
([(0 0) (10 10)]
[(1 0) (9 10)]
[(2 0) (8 10)]
[(3 0) (7 10)]
[(4 0) (6 10)]
[(5 0) (5 10)]
[(6 0) (4 10)]
[(7 0) (3 10)]
[(8 0) (2 10)]
[(9 0) (1 10)]
[(10 0) (0 10)])
with java interop when instantiating a templated java class is it necessary to pass the template type?
Java erases generics at the JVM level to raw collection types and that’s what you’re using via Clojure’s java interop
so I end up with the following error then which I cannot interpret:
java.lang.NoSuchMethodError: com.badlogic.gdx.graphics.g2d.Animation.getKeyFrame(FZ)Lcom/badlogic/gdx/graphics/g2d/TextureRegion;
at play_clj.g2d$animation__GT_texture.invoke(g2d.clj:257)
With libgdx 1.9.4 this code worked. With 1.9.5 change it no longer does and the API change was:
> - API Change: g2d.Animation is now generic so it can support Drawables, PolygonRegions, NinePatches, etc. To fix existing code, specify the TextureRegion type in animation declarations (and instantiations in Java 6), i.e. Animation<TextureRegion> myAnimation = new Animation<TextureRegion>(...);
That API I believe changed from TextureRegion getKeyFrame(float x, b boolean)
to T getKeyFrame(float x, b boolean)
so its not clear what is causing this error.that generic is on the return type, which is not even used when selecting an arity for interop (that’s all on the arguments)
what is the call you’re making?
I filed the stack trace here if that helps. https://github.com/oakes/play-clj/issues/112
I don’t understand why anything there is different or shouldn’t work
yeah, it doesn’t make sense to me why it’s looking for the old one - didn’t look like play-clj was aot’ed
@mnewhook is your project AOT’ed? and if so, have you cleaned?
@mnewhook usually when you're seeing LinkageError/NoSuchMethodError/VerifyError in clojure, it's caused by AOT compilation
Short, probably stupid question:
(partition 5 5 [\space] "cseerntiofarmit on")
Why does this not fill the last partition up to 5 elements? Wouldn’t it be supposed to do that when given a pad?
>>>In case there are not enough padding elements, return a partition with less than n items.
Must have overseen that. Thanks. Is there no simple way to always keep exactly 5 elements and fill the rest with a given pad?
this might be a silly question, but is there a way to wipe clean all unknown derivations? something like an (underive)
that takes no parameters?
@joshkh there’s global-heirarchy
or maybe i should be working with a hierarchy object, store it somewhere, and wipe it when necessary
yeah - that’s much cleaner
@hiredman derive, underive, and defmulti all use them - they just default to the global
so I am just saying, advice and best practices on using hierarchies(born out from experience) is going to be thin on the ground
in my scenario i've built a mock file system in the browser from a tabular data source where each row only knows its parent id. when i read in the rows i derive its id with its parent id, and then i can easily grab all descendants without having to mapify or recursively iterate through the rows.
(a hierarchy is just a map in a ref, so not all that different implementation wise, but semantics I guess)
gotcha. it was just an experiment / lazy way to not build and manage a tree myself. in that regards, success. 😉
Is there a way for us to override a protocol implementation on a type coming from a transitive library namespace?. Lets say I am consuming a library and it defined to look at a specific field on a Avro type and I want myself to override that lookup for my own usecase.
extend-protocol
is just a macro around extend
which is just a function
so if you have the protocol, the type you would like to override, and the implementation, you should be able to just pass that to extend at runtime
@smith.adriane The library already has a extend protocol on the type and I want to make sure for my project my own extend protocol on the same type overrides the implementation coming from the library and moreover the protocol itself is defined in the library.
when you say for your own project, does that mean your code will use one implementation and in the same program, the library’s code will use a different implementation for the same protocol?
protocols are not locally bindable like that - there’s only one implementation possible per concrete class
if your implementation is defined later, it replaces a previous definition for that specific class (if it existed)
I want to completely replace the definition. how do I ensure that my implementation is the one that is picked up at runtime?
I just tried a dummy example and it looks like you get IllegalArgumentException class MyType already directly implements interface MyProtocol for protocol
when you try to replace the implementation
(defprotocol MyProtocol
(f1 [_]))
(defrecord MyType []
MyProtocol
(f1 [_]
1))
(clojure.core/extend MyType
MyProtocol
{:f1 (fn [_]
2)})
but
(defprotocol MyProtocol
(f1 [_]))
(defrecord MyType []
)
(clojure.core/extend MyType
MyProtocol
{:f1 (fn [_]
1)})
(clojure.core/extend MyType
MyProtocol
{:f1 (fn [_]
2)})
yea, in the above example, lets say the first extend is in namespace1 and second extend(override) is in namespace2 and a third namespace uses namespace1, namespace2. I don't know if I can guarantee that namespace2 extend is always picked over namespace1. May be there is nothing I can do here but want some input for my usecase.
if you wrap your extend in a function, then you can just call it at the top of your -main
;; namespace 2
(defn do-my-extend! []
(extend MyType
MyProtocol
{:f1 (fn [_]
2)}))
;; main namespace
(defn -main [& args]
(do-my-extend!))
the -main will probably run after all the top level code
alternatively, if you have access to the source of the library you’re consuming, it might be worth considering just creating your own fork
I want to read and write XML but I see there are clojure.xml
, clojure.data.xml
and clojure.data.zip
to choose from. Does anyone have experience with these? Do they complement each other?
I had to do some xml parsing at some point and ended up using clojure.data.xml. clojure.data.xml can parse lazily. I’m not sure if clojure.xml can also parse lazily and without loading the xml document into memory
seems like clojure.data.xml is a better than clojure.xml option unless you really only need very basic xml parsing functionality
@smith.adriane thanks, I’ll give that a spin 😎
Does programming shape the way you think? A research project: https://twitter.com/leraboroditsky/status/924006274852892672 Comments to #off-topic , please.