Fork me on GitHub
#clojure
<
2019-10-18
>
JanisOlex10:10:50

hey people, is there some lib or out-of-box function besides (bean obj) which would dump the java object into clojure map of maps... Bean does not work, as it won't walk the tree and won't be able to convert inner data objects And my case is the most extreme... I would like to have object which has inside java original HashMaps which also can contain maps and objects... only real restriction is that maps are always strings as keys

dominicm10:10:44

There's one in clojure toolbox which I think is recursive.

noisesmith17:10:32

(cmd)user=> (import (java.util Map HashMap))
java.util.HashMap
(cmd)user=> (require '[clojure.walk :as w])
nil
(cmd)user=> (def input (let [m0 (HashMap.) m1 (HashMap.)] (.put m0 "a" m1) (.put m1 "b" 2) (.put m1 "c" 3) m0))
#'user/input
(ins)user=> input
{"a" {"b" 2, "c" 3}}
(ins)user=> (w/prewalk (fn [x] (if (instance? java.util.Map x) (into {} x) x)) input)
{"a" {"b" 2, "c" 3}}
- this will convert, also it exposes the fact that native hashmaps are already good enough for many clojure functions (including the printing ones)

noisesmith17:10:38

get also works on native Map instances (but assoc / dissoc don't iirc)

dominicm18:10:14

wouldn't work on beans though?

noisesmith18:10:55

a prewalk can handle beans as long as F handles them

dominicm18:10:13

ah ๐Ÿ™‚

noisesmith18:10:11

(cmd)user=> (def input (let [m0 (HashMap.) m1 (HashMap.)] (.put m0 "a" m1) (.put m1 "b" 2) (.put m1 "c" (java.util.Date.)) m0))
#'user/input
(ins)user=> (w/prewalk (fn [x] (cond (instance? java.util.Map x) (into {} x) (instance? java.util.Date x) (into {} (bean x)) :else x)) input)
{"a" {"b" 2, "c" {:day 5, :date 18, :time 1571421916321, :month 9, :seconds 16, :year 119, :class java.util.Date, :timezoneOffset 420, :hours 11, :minutes 5}}}
gotcha: it doesn't work unless you call into on the bean, because prewalk calls empty on the map and that fails for beans

JanisOlex10:10:30

and in addition -> turn all the keys into keywords

mloughlin10:10:53

does anyone have any experience writing OO-style builder/"fluent interface" with clojure maps?

borkdude12:10:50

I wrote a Java API to create a Clojure options map for a library recently. I could show you the code if you're interested. Not sure if it was the best approach, but it works

mloughlin13:10:44

I mainly see the pattern in Java/C#, I am interested in alternative solutions in idiomatic Clojure for example, I saw the example code for FFmpegBuilder (https://github.com/bramp/ffmpeg-cli-wrapper) and wondered how you would write the equivalent in Clojure. (API, not underlying implementation)

mloughlin13:10:27

I guess I'm about to facepalm, you'd just define a map :man-facepalming:

borkdude13:10:40

@michael.e.loughlin yeah ๐Ÿ™‚

๐Ÿ˜… 1
borkdude13:10:42

"fluent interface" can be achieved using threading macros basically

mloughlin13:10:41

that's interesting, thanks for sharing it.

mloughlin13:10:11

I find it jarring to see the Java type system's representation of nested maps ๐Ÿ™‚

borkdude13:10:19

I should probably create the Clojure map from Java in Sci.java instead of doing it the other way around

borkdude13:10:40

but that's an implementation detail I can get rid of later

borkdude13:10:17

creating a JS interface was much easier, because it maps better to how you do it in Clojure

borkdude13:10:35

can someone show me a practical use of &env and &form in a Clojure macro? are these mostly used by Clojure itself?

vlaaad13:10:12

capturing let bindings IIRC

alexmiller13:10:20

^^ prob most common

vlaaad13:10:14

(defmacro lets []
  `[[email protected](map (fn [sym] `(symbol ~(name sym))) (keys &env))])

(let [x 1]
  (when-let [y 2]
    (lets)))
;; => [x temp__4657__auto__ y]

bronsa13:10:41

&form is mostly used for either error reporting or capturing form metadata

borkdude13:10:24

@vlaaad are the vals of &env used for something practical as well?

vlaaad13:10:58

not sure, never used them

bronsa13:10:13

here's the vals being used

bronsa13:10:18

to retrieve the type information

bronsa13:10:40

(`crossing-env` there is &env)

borkdude13:10:46

(defmacro lets []
  (zipmap (map (fn [sym]
                 (list 'quote sym)) (keys &env)) (keys &env)))

(println
 (let [x 1 y 2]
   (lets))) ;;=> {x 1, y 2}
cool. not sure when I would use this, but cool ๐Ÿ˜‰

bronsa13:10:23

quite useful for debugging crazy macros

vlaaad14:10:59

I sometimes use scope-capture for debugging, which captures local variables and stores them for later retrieval

vlaaad14:10:21

although recently I switched to tap> since it doesn't require a dependency

borkdude14:10:50

I just use inline defs for this, it works since clojure 1.0.0 and before ๐Ÿ˜‰

vlaaad14:10:53

and is more intentful: I just put there stuff I'm interested in instead of saving everything in scope

vlaaad14:10:08

oh yeah, that as well

bronsa14:10:16

@borkdude &env predates vars tho ;)

๐Ÿ˜‚ 1
bronsa14:10:05

but I agree inline defs/tap are much simpler for this sort of debugging

borkdude14:10:43

if you despise inline defs you can use atoms or whatever

borkdude14:10:04

and add-watch .. oh boy ๐Ÿ™‚

borkdude14:10:28

I guess that's kind of what you get with tap> but I haven't tried that yet. hard keeping up with all these new features ๐Ÿ˜‰

sogaiu22:10:42

don't know if you're trying rebl, but what you tap> ends up there (in the tap tab) -- this is convenient, but i found it to not work so well for very large things

alexmiller14:10:18

tap> has the benefit of both being in core and getting tunneled over things like prepl

๐Ÿ’ฏ 2
sogaiu02:10:25

for not-so-large data, being able to use tap> and have the results end up in rebl is very convenient. for somewhat largish data i'm finding it doesn't appear to work so well -- i think rebl has hung sometimes. then i kill its window after a while and then the project's jvm process goes away too, iirc. has that been your experience? the same data shows up quite nicely in rebl when i use submit, fwiw.

Eduardo Mata14:10:02

I have a parallel synchronous processor in my clojure app. After sending a high amount of messages for processing. I use async core. My channels size are 65536. I am getting the following message

java.lang.OutOfMemoryError: unable to create new native thread

unbalanced14:10:53

Heya, okay general question about Clojure further self-education. We're in an interesting pickle in that there's a small number of us (relative to devs as a whole) and yet our language and ecosystem is evolving rapidly. I feel like OO languages are able to proliferate best practices by proliferating libraries (no thinking required), whereas we tend to proliferate best practices by... learning best practices. Now, personally, if I come up with a good idea -- or what I think is a good idea -- I wouldn't even know the right forum in which to share it. I also certainly don't know how to find out what everyone else is doing. We have a few excellent resources, but they're quite finite, and seem to go out of date almost as soon as they're written. i.e., I've yet to see a comprehensive treatment of transducers, core.async, or spec -- and I KNOW folks are doing some incredible stuff with them. So I'd love to hear about how y'all are keeping sharp?

dpsutton14:10:48

what does "proliferate best practices by proliferating libraries" mean

unbalanced14:10:47

Rhetorical question: If you think of ruby web development, what's the next word that comes to your mind? Rails. With Python, typically Flask or Django. Each of those comes with it a set of fairly well established best-practices.

unbalanced14:10:05

Flask, for instance, comes with a ton of plugins.

unbalanced14:10:43

Now, I'm not saying we should do it that way... one of the things I love about Clojure is that it encourages you to think through your own domain problems and it gives you all the tools to do so (IMHO)

unbalanced14:10:29

What I'm saying more generically is that in a lot of other languages, there's a pretty tight mapping between best techinque <-> best object/class

unbalanced15:10:04

BUT I don't want the point to get lost, I'm not trying to debate how other languages learn, you may agree with me on that point or not -- all I'm asking is how does everyone keep up on best practices for clj?

uosl16:10:00

I think most people only migrate libraries when they hit a wall with what they're currently using, and switch to something newer with the features they now need. So I don't think it's necessary to keep up, as it's enough to catch up when you need to.

seancorfield17:10:56

It definitely takes work. I follow Clojure topics on StackOverflow, Reddit, Hacker News -- and http://ask.clojure.org and ClojureVerse, in addition to watching for announcements here and on the Google Groups. I follow a bunch of high-profile Clojure people on Twitter too (but that's often too noisy to be very useful these days).

seancorfield17:10:57

I find myself much more immersed in the Clojure community than I have been in previous communities -- and part of that is to keep track of all the cool stuff folks are working on.

seancorfield17:10:30

Watching conference talks when they are posted to YouTube/Vimeo is also a good way of "keeping up".

seancorfield17:10:44

And it's certainly true that "best practices" in Clojure evolve over time, as new features appear in Clojure itself and its immediate adjacent ecosystem (`clj` / tools.deps.alpha being a great example, with Spec, and Transducers before that).

alza15:10:46

Hi folks, I just tried to login to the Clojure Jira for the first time after the recent migration, however it seems my account didn't get migrated ๐Ÿ™

alza15:10:12

When I login to Atlassian, I get "<my-email-address> doesn't have access to Jira on http://clojure.atlassian.net"

alza15:10:50

This sort of makes sense, as I already have an Atlassian account.. But how do I gain access to the Clojure Jira?

alza15:10:07

I googled for some steps/procedure, but I couldn't find anything..

andy.fingerhut15:10:40

Pinging @alexmiller as one of the few (or only) person who can grant access on the new Clojure JIRA, I think. At least for new issues, creating it on http://ask.clojure.org is recommended now, but if you want to comment or add a patch to an existing issue I think you would need a Clojure JIRA account.

alza15:10:35

Ah thanks @U0CMVHBL2 ๐Ÿ™‚ I do indeed wish to comment on an existing issue, so for that I would need an account. I'll ping Alex.

alza15:10:13

As an aside, I feel for newcomers who wish to raise issues.. I just Googled "create clojure issue", and no mention of http://ask.clojure.org on the first page of results ๐Ÿ™

alza15:10:36

Although Googling for "ask clojure question" brings it up ๐Ÿ™‚

alexmiller15:10:05

googleosity is largely based on inbound links. as a new-ish site, accumulating inbound links and thus search status is something that just takes time. I've done all the necessary things on the google search side for the site that I can do.

alexmiller15:10:44

https://clojure.org/community/contributing is probably the best page describing the state of the world

alexmiller15:10:27

which has links to other useful pages

alza15:10:49

Ah cool I will check it out ๐Ÿ™‚

alexmiller15:10:11

if you are looking only to comment on an issue, the preferred process is to comment on the http://ask.clojure.org page for the ticket

alexmiller15:10:25

we are reserving jira accounts for people providing patches

jjttjj15:10:05

Letโ€™s say i have an api service which I implement as a map which contains all the state i need to interact with that service:

(def service1 (api1/client โ€œlocalhostโ€)) ;;=> {::api1/connection โ€œโ€ฆโ€}
(api1/query service1 query-str)
Letโ€™s say i later want to build an additional layer on top of that api that requires more of itโ€™s own state. (for example, an atom to cache results of queiries). Is the following a legitimate/good pattern: have a second client initializer function which takes the first as an arguemnt and just merges itโ€™s own state that it needs:
(def service2  (api2/client service1)) ;;=> {::api1/connection โ€œโ€ฆโ€, ::api2/cache (atom {})}
So now both api1 functions and api2 functions can be used on the same map:
(api1/query service2 query-str)
(api2/cached-query service2 query-str)
So this is kind of like using reify to implement protocols on objects, but just on plain maps. Is it preferable to instead build up a map thatโ€™s more like:
{:api1-service service1-map
 :api2-service service2-map}
Or is the first way what is kind of the whole point of open maps (+ qualified keys)?

emccue18:10:59

Has anyone used quil to make a gui?

emccue18:10:03

is that a supported use case

bfabry18:10:08

Itโ€™s been probably 7 years since I used quil, but I would really really advise against trying that

emccue18:10:05

Well, its more in the realm of a "game" sort of thing

emccue18:10:11

less swing-ey buttons

emccue18:10:20

does that change your assessment at all?

sogaiu22:10:30

i tried with quil using clojure on android years ago, and i agree that if things haven't changed much to not try the gui thing with it.

sogaiu22:10:44

perhaps things have changed though ๐Ÿ™‚

Arto Kalishian19:10:45

Good evening Community, Does anyone use CouchDB ?

Eduardo Mata19:10:07

How could I increase the total of 8 threads in core async?

noisesmith19:10:13

@contact904 go blocks are not meant for blocking, CPU or IO intensive work, the coorrect thing is to use the thread macro which returns a channel, you can interact with the result on that channel in a go block

๐Ÿ‘ 1