This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-02-09
Channels
- # announcements (19)
- # babashka (26)
- # beginners (157)
- # calva (54)
- # cider (12)
- # clj-kondo (18)
- # cljdoc (3)
- # clojure (65)
- # clojure-australia (3)
- # clojure-europe (28)
- # clojure-germany (14)
- # clojure-greece (1)
- # clojure-italy (8)
- # clojure-nl (10)
- # clojure-uk (81)
- # clojuredesign-podcast (2)
- # clojurescript (20)
- # clr (1)
- # conjure (1)
- # cursive (1)
- # data-science (29)
- # datascript (2)
- # datomic (19)
- # depstar (4)
- # fulcro (24)
- # graalvm (6)
- # helix (26)
- # jobs (2)
- # jobs-discuss (2)
- # kaocha (12)
- # leiningen (1)
- # malli (17)
- # off-topic (18)
- # pathom (34)
- # polylith (23)
- # re-frame (10)
- # reagent (8)
- # releases (1)
- # remote-jobs (1)
- # reveal (5)
- # shadow-cljs (49)
- # spacemacs (1)
- # startup-in-a-month (6)
- # vim (4)
Hi, How to get the key of Enum instead of the value when converting Java object to Clojure map using bean or javadata/from-java?
I don't think I understand your question. If I call bean
on a Java object, it returns a value that acts like a Clojure map, and its keys are all keywords, e.g.:
user=> (def m1 (bean (atom 5)))
#'user/m1
user=> m1
{:class clojure.lang.Atom, :validator nil, :watches {}}
user=> (keys m1)
(:class :validator :watches)
user=> (map class (keys m1))
(clojure.lang.Keyword clojure.lang.Keyword clojure.lang.Keyword)
All of the keys are Clojure keywords. You want a map where the keys are some other non-keyword values?
Sorry, I don't describe it clearly. The problem is I have an Enum in Java like this:
public enum Test {
A("a", ""),
B("b", "")
}
So, I want to get the key of Enum when converting Java objects to Clojure maps. Now is get the name of Enum.Can you give an example of something you have tried in a REPL with such an enum, showing the return value that you get (but wish it were different), and what return value you wish to get? I still do not understand what you are after.
public class Test {
private QueryTypeEnum type;
public enum QueryTypeEnum {
A("a", ""),
B("b", "");
private String key;
private String desc;
}
}
(bean test instance) or (from-java test instance)
My except map is like this: {":type" "a"}, But it will take the name of Enum, so the result will be like this: {":type" "A"}.
Now, I found a way to solve it. I rewrite defmethod from-java [Enum] inside the java.data like this:
(defmethod j/from-java Enum [enum] (.getKey enum))
@rextruong what if input is like this
["A1 B1 C1"
"A2 B2 C2"
"A3 B3 C3"]
@popeyepwr (map #(clojure.string/split % #" ") input)
will be close to what you want...
user=> (def input ["A1 B1 C1"
"A2 B2 C2"
"A3 B3 C3"])
#'user/input
user=> (map #(clojure.string/split % #" ") input)
(["A1" "B1" "C1"] ["A2" "B2" "C2"] ["A3" "B3" "C3"])
user=>
ahhh... i forgot that clojure.string/split functions! gonna take note again.
mapv
if you really want a vector back instead of a (lazy) sequence.
Do you want to turn a vector of strings into a vector of vectors of strings?
(mapv vector ["A1 B1 C1" "A2 B2 C2" "A3 B3 C3"]) ; [["A1 B1 C1"] ["A2 B2 C2"] ["A3 B3 C3"]]
your solution yields a vector who's elements are single item vectors. ["A1 B1 C1"]
. The desired shape is a vector of 3 item vectors [["A1" "B1" C1"] ...]
Interesting how the brain works, I looked at the question from one hour ago and then I did not even see the quotes in the revised question
I assume that if I create a channel with a distinct
transducer, eg
(async/chan 10 (distinct))
that this will not be thread safe, i.e. it is not safe for multiple threads to read/write from the channel?It is a bad idea because distinct will hold a copy of every message that passes through the channel in a set
@hiredman thank you. This is a short lived tree traversal, multi threaded yes, but accumulation is not an issue. Hmm…I read about the volatile
used in distinct
and came out thinking it would not be safe. Care to elaborate a bit?
The main thing is every channel has a lock inside it, and when you add or remove things from the channel (which is when the transducer operates) you hold the lock
ok got it, so distinct by itself outside a channel is not thread safe, but used as a transducer for a channel we get safety
The usage of volatile inside a lot of the mutable transducers is there to make them safe for use with core.async
The volatile makes sure mutations propagate between threads, the channel lock says one thread at a time
Damn, I realized I didn't know how to pass a java property using -J
(Clojure CLI). I tried many ways of prefixing it without any luck, an example in the reference guide would be welcome
All right, it was about the order of args... -J
must figure before -M
. Kinda makes sense but my coffee wasn't strong enough this morning...
Hi, I using Java class to representing Clojure dataset like this:
{
"query": {
"source-table": 2,
"aggregation": [
[
"distinct",
[
"field-id",
5
]
],
[
"sum",
[
"field-id",
8
]
]
}
}
Now, I have classes here:
public class QueryReq {
private Query query;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Query {
private String sourceTable;
private List<Aggregation> aggregation;
}
@Data
public class Aggregation {
private AggregationEnum aggregation;
private AggregationColumn aggregationColumn;
@Data
public class AggregationColumn {
private KeywordEnum column;
private Integer id;
}
}
So, my question is how to convert AggregationColumn which nested in the Aggregation to Clojure vector? Is here have some convenient ways to do converting datastructure between Java and Clojure?Java classes pretty much all have custom APIs defined by their methods, so I cannot imagine any general technique to convert between Java object values and Clojure values. If you use Java classes that implement interfaces like List, Map, and Set, Clojure collections implement those interfaces, so at least in some cases no conversion is necesary -- they already satisfy those interfaces.
I'm having some trouble with a reflection warning. I have a library, with a defrecord
in it that extends a defprotocol
. E.g.. (defrecord SomeThing [name type] myProtocol ...)
.
This protocol has a release-props
method. When I make a call to this method, like so:
(.release-props my-thing)
I'm getting a reflection warning call to method release_props can't be resolved (target class is unknown)
. I'm trying to resolve it like (.release-props ^mylib/SomeThing my-thing)
, but that's not working. I get Unable to resolve classname.
What am I doing wrong?Maybe I'm missing something on the library side? I admit to having no clue about what (:gen-class)
does...
even a fully qualified name like ^my.lib.SomeThing
doesn't work. I still get a ClassNotFoundException
.
I guess the most basic question is: how do I refer to a record in a library? I just get No such var
Java method names can’t have a - in them
Doh! Showing my Java ignorance again.
So the . call with the - doesn’t seem right
It works, though. Just gets a reflection warning.
Yeah, it might be getting munged
Ah, right. I'll give these methods more JavaLikeNames, then. Thank you!
The names are fine now
It’s just that calling via java interop requires java naming
Excuse the extreme ignorance, but is there another way to call a protocol method here?
If you have a protocol, why are you not invoking the protocol method?
(release-prop my-thing)
Because this is the very first time I have used protocols and thought that was how they work.
Ok, they’re just like regular functions when you invoke them
And protocol functions exist in the namespace where they’re declared so you require/refer them just like any other function
Bingo, that did it. Thank you!
I have not tried it before, but do not know of any reason why it shouldn't work, either. Inner classes named from Clojure have names like OuterClass$InnerClass -- did you try naming the inner class that way?
If so, what did you try, and what unexpected result did you get?
The example code is the same as the previous question, I defined Inner class defmethod like this:
(defmethod j/from-java QueryReq$Aggregation [agg]
(println "ac:"))
But "ac:" don't print, so that makes me feel that my defined function don't be called.Hi everybody! From this map:
(def homes [{:name "Home 1",
:wifi "y",
:shower "y",
:laundry "y",
:metro "n",
:balcony "y",
:fireplace "n",
:pool "y"},
{:name "Home 2",
:wifi "n",
:shower "y",
:laundry "y",
:metro "n",
:balcony "n",
:fireplace "n",
:pool "n"}
{:name "Home 3",
:wifi "y",
:shower "y",
:laundry "y",
:metro "n",
:balcony "y",
:fireplace "y",
:pool "n"}
{:name "Home 4",
:wifi "y",
:shower "y",
:laundry "n",
:metro "n",
:balcony "n",
:fireplace "n",
:pool "n"}]);
I want to only keep/filter houses meeting the following needs (def needs [:wifi :shower :laundry])
Is my solution a decent one? (filter #(every? #{"y"} (vals (select-keys % needs))) homes)
Did you have suggestions?
(filter #(every? #{"y"} (vals (select-keys % needs))) homes)
({:name "Home 1",
:wifi "y",
:shower "y",
:laundry "y",
:metro "n",
:balcony "y",
:fireplace "n",
:pool "y"}
{:name "Home 3",
:wifi "y",
:shower "y",
:laundry "y",
:metro "n",
:balcony "y",
:fireplace "y",
:pool "n"})
i might consider modeling like this:
(def homes' [{:name "Home 1",
:amenities #{:wifi :shower :laundry :pool}},
{:name "Home 2",
:amenities #{:shower :laundry}}
{:name "Home 3",
:amenities #{:wifi :shower :laundry :balcony :fireplace}}
{:name "Home 4",
:amenities #{:wifi :shower}}])
(def needs' #{:wifi :shower :laundry})
then to filter:
(filter
(fn [home] (clojure.set/subset? needs' (:amenities home) ))
homes')
;; => ({:name "Home 1", :amenities #{:pool :shower :laundry :wifi}}
;; {:name "Home 3", :amenities #{:shower :laundry :balcony :wifi :fireplace}})
Thx for your suggestion. Concerning the modeling, let's assume that it can be changed because it comes from a converted JSON.
I think your solution is good, although you could simplify it by changing (vals (select-keys % needs))
to (map % needs)
.
Perfect @UCW9TUDNK! I suspected that there was a way to simplify. Thank you, that was exactly the advice sought. 👍
Maps as functions ... it's really powerful!
Yes, sets as function too 🙂
is there any possibility to do java interop from source files instead of compiling first? Or is there a way to use deps to build local java libs first before starting the repl?
no to the first question. the latter is possible but probably depends on lots of things
are there any reference apps or starter kits that include this workflow for reference?
are these local java libs things that are yours or external libs? the latter is nearly always built and published to a maven repo somewhere and you should just include the lib that way.
are you looking at java-only or java/clojure mix?
so, my use-case is running the terraform CDK (`cdktf`). It ships with a java flavor (but also typescript, python, and dotnet-core as well), and when you add provider dependencies (ie: docker
), you run cdktf get
and it pulls down some typescript and generates java source to be consumed by your project. For a java project, it then is accessible by the code you've written yourself, but for clojure -- it's not yet compiled. Usually cdktf get
code is not checked into the repo, it goes in a .gen
directory.
but my use-case is to only write clojure with java interop
if you don't need to recompile very often, I was able to use this one liner to compile java files:
find javasrc -name '*.java' -print0 | xargs -0 javac -d classes -cp `clj -Spath
`
make sure the directory classes
exists and add it to the paths in your deps.edn
which should have a key like:
:paths ["src" "resources" "classes"]
OH! That's interesting
Hey, I’m coming from Haskell and excited about clojure! I’m working through 4clojure and some basic problems right now just getting the hang of it. Are there any recommended intro projects out there? Would like to dig into something but I’m not sure what’s reasonable in this language.
While I can solve easy 4clojure puzzles, I am curious about the best learning strategy when stuck. Obviously I can use a search engine for some public gist where other users would share their solution and revert engineer it, but is there a more obvious path to learn ?
is there anyway to avoid it? I wanted to use one of the function from another namespaces, which already I imported the file in another
@popeyepwr Imho, this is usually a sign that you need a namespace restructuring. In other words, think again whether you really need a relationship like ns a -> ns b -> ns c -> ns a
(read ->
as requires
).
Usually the part of a
that requires b
is higher level than the part that c
is using.
So, assuming that all of the affected namespaces are under your control, it might make sense, depending on the case, to either:
• further break them down (to split the higher from the lower level stuff of a
) or
• merge the interconnected parts into a single namespace
extract out the shared code into a new namespace
There's also a technique by which stuff is moved at runtime ((resolve 'my.nsp/f) arg1 arg2)
generally not good practice.
Of interest, there is also Timothy Baldridge's answer here (use interfaces and implementations): https://groups.google.com/g/clojure/c/-PvQvVmmLQg
I'm trying to do a reduction (or something else.... catamorphic? lots into 1) but I'm having trouble figuring out exactly how to shape it. The first def is an example from the docs of a library I'm trying out, and the second is the way that my data is shaped.
(def g1 (-> (dep/graph)
(dep/depend :b :a) ; "B depends on A"
(dep/depend :c :b) ; "C depends on B"
(dep/depend :c :a) ; "C depends on A"
(dep/depend :d :c))) ; "D depends on C"
(def my-data {:a #{:b :c}
:b #{:d :c}
:d #{}})
There's a sort of double higher order fn going on: for every key, I want to put all its dependents into this growing dependency graph
You have basically two options 1. Reduce over the map, reducing over each map entry 2. Transform your map into a more linear structure, then reduce over that
i'm getting thrown by f should be a function of 2 arguments
in reduce's docs. This is a 3 argument function. At first I thought, use partial, but the first argument of dep/depend is that graph that's accumulating
so the linearized version of what i started with would be something more like
[{:depends :a, :depends-on :b}
{:depends :a, :depends-on :c}
{:depends :b, :depends-on :d}
{:depends :b, :depends-on :c}
{:depends :d}]
?or even just a bunch of pairs like [:a :b], the relationship implied by the context
![nice](https://emoji.slack-edge.com/T03RZGPFR/nice/63cf3e49b6826eb0.png)
when "linearizing"(normalizing? it is connected in some way to normalizing data for a rdms) your structure like that you have two choices in how to do it, via seqs or via transducers
using a for like in my example produces a lazy seq, lazy seqs are sort of a habitual thing to grab for, but transducers are often faster, use less memory, and behave nicer when mixed with io/side effects
when i finally run this function, i anticipate running it approximately once. so i'll skip the transduction
so where you have that empty map in your db def, i would have (dep/graph), which is the empty val for my case
cool, it was not hard to linearize this, and that does make it easier to think about
(defn linearize [[component references ]]
(for [ref references]
[component ref]))
(def normalized (mapcat linearize adjacency-list))
(def dependency-graph
(reduce (fn [g entry] (dep/depend g (first entry) (second entry))) (dep/graph) normalized))
Piece of 🍰 , thanks hm!var is 1. a really bad name to use because it conflicts with the var special form 2. a vector of maps
(def var {:a "a1":b "b1" :c "c1"})
=> #'user/var
(mapv #(get var %) [:a :b :c])
=> ["a1" "b1" "c1"]
hi, I'm struggling with hyphens in clojure.java.jdbc. I'm using SQLITE and have a column user_id
. I'm doing a simple insert like this:
(jdbc/insert! db :user {:user-id 555} {:identifiers #(.replace % \- \_)})
Getting the error: SQL error or missing database (near "-": syntax error)
:identifiers
deals with names coming back from SQL to Clojure; :entities
is what you want for names going from Clojure to SQL.
would love to use next.jdbc but due to circumstances out of my control I need to target JDK7
I try to keep an eye out for SQL-related Qs here in #beginners -- posting in #sql is certain to get my attention more quickly tho'... 🙂
tried using that :identifiers key to fix the hyphens but it seems too have no effect
So the issue is that for each of the keys [:a :b :c]
you need to call (get)
on each of your maps. so its a nested iteration
you need to do it the inner fn that youre passing to mapv for each of your keys
see if using https://clojuredocs.org/clojure.core/for in the mapping function helps?
get looks some thing up by a key in the immediate thing you give it, it will not reach down through other collections to look for something with a key
Looks nice, you might want to use mapcat, and again, don't use the name "var" it conflicts with the var special form, and will act really odd in some situations
Hello, am currently trying to prototype a simple clojure backend with Ring. Am using https://github.com/lispcast/listronica/tree/1.17 as a template. Are there any resources I might want to look at?
How do I best create an API to transmit edn from a clojurescript webapp to ring backend? Can I just put edn in the :body
of a route? That gives me some errors. Do I wrap it in a string like "{:test [\"test\"]}"
I'm reading Web development with Clojure (3rd ed.) and I noticed that the book starts off with what I would consider traditional web development, then introduces AJAX with ClojureScript, before adding reagent and eventually re-frame. I love the book, but this seems like a lot of additional complexity to me, and I'm wondering if I need that additional complexity. I want to make simple and fast websites with text fields for inputting some data, and some buttons and checkboxes for filtering said data. If I need fancy animations I can use CSS. I don't think I need reactivity, but maybe I would be missing something else? Is the workflow of using reagent (with reframe?) somehow more productive than just writing Clojure on the server and producing HTML? Asked in another way, what are some good use cases for ClojureScript with reagent?
"Modern" web apps these days are SPAs (single page applications) that communicate with a REST-like backend -- and that's what the book is aiming at. It's why I don't recommend that book -- or the Luminus template -- for people who are brand new to Clojure: it's just too many moving parts. Take a look at the Practicalli stuff for web development and start simple with just Ring and a few small, simple libraries. Then as you understand that process, you can add complexity as you need it.
https://practicalli.github.io/blog/posts/clojure-web-server-cli-tools-deps-edn/ (at https://practicalli.github.io/ -- lots of great beginners content there).
I will take a look, @seancorfield. Thanks for the suggestion! I think my question could be asked as "How do you decide if an SPA is the right fit?", if anyone has input on that instead 🙂
I think you've answered your own question there @endrejoh -- if you want to make simple/fast websites with forms for capturing data and storing it somewhere, then SSR (server-side rendered) HTML is going to be just fine and Ring + Compojure + maybe Selmer + next.jdbc
is about all you'll need (assuming a database for storage). Take a look at https://github.com/seancorfield/usermanager-example (or the Reitit-based variant linked in the README).
Thank you so much, @seancorfield!