Fork me on GitHub
#clojure
<
2019-06-05
>
ag00:06:24

is there a short syntax for selecting namespaced keys of off map? e.g.: {:foo/one 1 :foo/two 2 :three 3} I want to do (select-keys m [:foo/one :foo/two]) but without having to repeat :foo

ag00:06:34

or even better, select all keys that start with :foo/ without even listing them one by one

mfikes00:06:42

@ag Not exactly what you are asking, but in the context of destructuring:

user=> (def m {:foo/one 1 :foo/two 2 :three 3})
#'user/m
user=> (let [{:foo/keys [one two]} m] [one two])
[1 2]

โž• 12
ag00:06:50

I know you can do that

mfikes00:06:51

But, presumably you are looking for a shorter version of

(select-keys m (filter #(= "foo" (namespace %)) (keys m)))

ag00:06:47

yeah, something like that, but I was hoping thereโ€™s some magical trick with #:foo maybe

souenzzo00:06:47

no magic, just functions ๐Ÿ™‚

ag00:06:26

I hate typing. I dunno how people even deal with semicolons and commas and all that crazy garbage in other languages

andy.fingerhut01:06:40

Type one namespaced keyword, then copy/paste for the others?

noisesmith02:06:11

I guess with data-readers you could define #foo[:x :y :z] to become [:x/y :x/z] or whatever

Alex Miller (Clojure team)02:06:32

we've talked about extending the namespaced map literal syntax to vectors #:foo[:x :y :z] but then the question is what about sets #:foo#{:x :y} ? gross.

didibus04:06:14

Hum, not the prettiest for sets, but it's not that bad either.

didibus04:06:54

Especially if you put a space in it #:foo #{:x :y}

โž• 4
fenton02:06:11

deps.edn and private git repositories... any advice? getting: com.jcraft.jsch.agentproxy.AgentProxyException: connector is not available:

p4ulcristian10:06:35

Hello, how can I stream System.out.println() to the Clojure REPL? I am using a java class compiled with leiningen, and I want to see its log when calling it in the REPL.

vlaaad10:06:10

(System/setOut (java.io.PrintStream. (org.apache.commons.io.output.WriterOutputStream. *out*) true))

(.println System/out "hi")

๐Ÿ‘ 4
dangercoder13:06:42

Is everyone using Integrant together with Duct or are you also running it standalone?

dominicm15:06:26

I'm using it without

๐Ÿ‘ 8
rickmoynihan16:06:04

both with duct and standalone here

๐Ÿ‘ 4
roklenarcic14:06:47

If I have clj and cljc file for same namespace, in what order are they compiled? Same for cljc/cljs.

Alex Miller (Clojure team)14:06:25

platform specific is always preferred

Alex Miller (Clojure team)14:06:44

so for clojure usage, I don't think you would get cljc compiled/loaded at all

Alex Miller (Clojure team)14:06:49

cljs is more complicated as prob different stories for macro and non-macro

roklenarcic14:06:06

ah, so it only compiles one

Alex Miller (Clojure team)14:06:31

yeah - they are alternate versions of the same namespace

Alex Miller (Clojure team)14:06:57

in clojure, it will look for a .class first (if newer than clj or cljc), then .clj, then .cljc

roklenarcic14:06:16

thank you for that info

p4ulcristian16:06:13

hello guys, I have a reservation system which works with agent, so people can't reserve at the same time. But sometimes it stops working, it gives me no exception, and it doesn't restart. how is this possible?

hiredman16:06:25

what evidence do you have that it stops working?

Alex Miller (Clojure team)16:06:21

agents can fail and won't restart

p4ulcristian16:06:25

well, on my client-side, when people are reserving the server responds that the agent needs restart, like I wouldn't have setup the error handler.

Alex Miller (Clojure team)16:06:34

there are lots of options for how errors and restarts are handled

hiredman16:06:05

but presumably you have a whole stack of code between the client and the agent, how do you know the failure isn't in there somewhere?

p4ulcristian16:06:31

so, the error-handler! doesn't handle everything? @alexmiller

Alex Miller (Clojure team)16:06:59

I don't have any of it in my head atm, I just know there's lot of stuff there that I use so infrequently that I have to re-read the source

p4ulcristian16:06:14

@hiredman because the error is specific to the agent, and because I log the errors and the restarts, and sometimes restarts doesnt happen, only the error

Alex Miller (Clojure team)16:06:17

and honestly, approx 0% of users use this stuff so it wouldn't surprise me if there were unsurfaced bugs

hiredman16:06:06

I thought you said you don't get an error?

hiredman16:06:20

what is the error that is specific to the agent?

Alex Miller (Clojure team)16:06:21

how are you configuring the agent wrt error-handler and error-mode?

p4ulcristian16:06:50

@hiredman, I log in the database for certain functions. like restarting the agent. And when agent restarts I put the error in my logs. In the case when restarting doesn't happen, my error is logged, but is an empty string

p4ulcristian16:06:54

@alexmiller, well it is in my snippet, I set-error-handler! after defining it

Alex Miller (Clojure team)16:06:10

the default error-mode of an agent is :fail, not :continue (unless there's an error handler)

Alex Miller (Clojure team)16:06:22

not sure how that changes if you set the error-handler after the fact

hiredman16:06:49

so it sounds like you do get an error

hiredman16:06:37

it is hard to say since you deleted the logging bits from your example

p4ulcristian16:06:59

I put it back, i didnt want chaos

hiredman16:06:01

but it sounds like you are getting an error (the error handler is running) and something is going wrong in your error handler

p4ulcristian16:06:03

that's the code without modification

Alex Miller (Clojure team)16:06:03

exceptions thrown in the error handler itself are ignored and lost

hiredman16:06:33

yeah, you are running the error handler in a future

hiredman16:06:39

so they are racing to handle the error

Alex Miller (Clojure team)16:06:45

you've introduced a race here by restarting in the future - restarts are ignored if the agent is not in a failed state

hiredman16:06:57

so the error is already cleared by the time you try to get it with agent-error

Alex Miller (Clojure team)16:06:24

I would have to study all that code more closely to really think about the concurrency aspects of this

p4ulcristian16:06:34

so, I take out future and it should be fine?

hiredman16:06:58

it may or may not be fine, depending, but it will take care of the empty string thing

Alex Miller (Clojure team)16:06:00

it would take me a lot more time to answer that question, and I don't have it atm

p4ulcristian16:06:10

I never did concurrency before, this is my first approach on this topic.

p4ulcristian16:06:36

But it will restart then, that's what matters, I guess.

Alex Miller (Clojure team)16:06:45

why not just use error-mode :continue?

Alex Miller (Clojure team)16:06:01

then the agent will automatically restart?

hiredman16:06:24

in general (depending on the database) you will be much better off using your database features to keep things consistent in the face of multiple writers

Alex Miller (Clojure team)16:06:35

(set-error-mode! reservation-queue :continue)

hiredman16:06:53

presumably at some point you want this running on multiple machines, at which point the serialization you get from agents doesn't exist

p4ulcristian16:06:16

@alexmillerdidn't know such thing existed, thank you very much

Alex Miller (Clojure team)16:06:44

if you read the docstring for agent and some of the other functions around it, I think that might help

p4ulcristian16:06:50

@hiredman No, this project will stay with 22 shops, so I guess I won't need nothing more sophisticated. But I am trying to learn more about the topic, I also enjoy it more than the frontend. ๐Ÿ™‚

p4ulcristian16:06:09

@alexmiller Thank you, duly noted. If it weren't for a stackoverflow topic, I wouldn't even used future, so yes, next time I start with the docstring.

kenny18:06:13

Is there a way to have (edn/read-string "{:foo 1}") read 1 as an Integer?

kenny18:06:36

Maybe a custom data reader?

Alex Miller (Clojure team)18:06:46

The string above will not trigger any custom data readers

andy.fingerhut18:06:04

If I understand correctly, a custom data reader could cause a string like {:foo #my-tag 1 } to read #my-tag 1 as an Integer, but that is a different string.

kenny18:06:17

Yeah but could easily be written as (edn/read-string "{:foo #int 1}")

Alex Miller (Clojure team)18:06:28

Even that would read 1 as a Long first

Alex Miller (Clojure team)18:06:48

And your data reader could convert it to whatever

kenny18:06:52

That's fine. I just want the output to be an int.

andy.fingerhut18:06:14

Warning: most kinds of Clojure arithmetic done on an Integer will not return an Integer.

kenny18:06:20

That's ok. Our app has config files in EDN. Some of those config maps need to be passed via a Properties map to a Java library. Java libraries typically have methods declared that take an int and not long.

noisesmith18:06:21

if you use Clojure to call those methods, it usually does the right thing

noisesmith18:06:47

isn't Properties always string->string?

kenny18:06:10

Hmm, lemme see. I definitely get an exception due to a Long being passed instead of an int.

Alex Miller (Clojure team)18:06:29

Properties extends Hashtable so you can abuse it by using the parent class methods to put other stuff in it

kenny18:06:45

I do this (doto (Properties.) (.putAll kafka-config)) and pass it to a Java method.

Alex Miller (Clojure team)18:06:52

It is one of the worst APIs in Java

๐Ÿšฎ 4
noisesmith18:06:54

right, but it's not going to be via Properties... at least not via standard methods https://docs.oracle.com/javase/7/docs/api/java/util/Properties.html#getProperty(java.lang.String)

noisesmith18:06:05

@kenny all the kafka configs are strings

noisesmith18:06:12

I know that one specifically

noisesmith18:06:56

I'm not doubting something wants an int and gets a long, but it's not kafka via properties

kenny18:06:04

I passed {"" 20000} as part of the kafka config and it threw the cannot pass a Long exception. This fixed it {"" (int 20000)}

noisesmith18:06:24

{"" "20000"} is canonical

noisesmith18:06:27

int happens to work

kenny18:06:37

Oh cool. I'll do that, much cleaner.

noisesmith18:06:28

@kenny usually I have a function that turns a clojure hash-map into string/string pairs then puts it into a Properties map

kenny18:06:08

Yeah, should probably add helper function for that, especially now that I know it's a nasty api.

Ludwig20:06:57

hi, is it possible to require two different versions of a library and use it at the same time?

noisesmith20:06:44

not in any simple way, no

Ludwig20:06:06

@noisesmith what would be the trick then?

noisesmith20:06:48

isolated classloaders iirc

Ludwig20:06:24

thanks! I will search about it

noisesmith20:06:54

everything I've tried or heard about it makes it seem frustrating

the2bears20:06:23

A classloader hierarchy along the lines of the one OSGi uses, where peer classloaders do not delegate to their parents when looking for a loaded class. Been a long time since I did this, so the details are very fuzzy.

noisesmith20:06:24

and making it work with Clojure iirc requires a pretty intimate understanding of how clojure extends the runtime classloader - my knowledge of this stuff is not very deep, maybe someone else can offer more detail

noisesmith20:06:02

I know there was at least one fork of clojure for the express purpose of working with isolated classloaders

the2bears20:06:03

That allowed OSGi services to use different versions of classes IIRC

noisesmith20:06:18

right - the fork I mentioned was for usage with OSGi

noisesmith20:06:28

because clojure as is wasn't compatible

the2bears20:06:31

but mixing that with Clojure? No idea how ๐Ÿ™‚

noisesmith20:06:47

I think it's less about not delegating to parents, and more about creating two (or more) inheritance trees

the2bears20:06:09

Delegation might be the wrong word. I remember that it allowed a "child" classloader, instantiated for a service, to access classes "sideways" from other peers, without first looking in the parent. Or something like that ๐Ÿ˜›

the2bears20:06:48

That allowed for an additional security layer, whether a class was exposed outside its service, etc

the2bears20:06:07

but this is younger me from ~10 years ago!

noisesmith20:06:20

oh, that's more than I know about it

the2bears20:06:09

It was strange stuff in a way, I ported 2 implementations to a "java on the chip" box my company at the time made.

Alex Miller (Clojure team)21:06:21

you can achieve this isolation in Java by using a post delegation classloader. however, clojure's dynamic classloader explicitly shares a class cache with all other dynamic classloaders

Ludwig21:06:34

thanks guys, quite interesting, I also heard that it is possible to have clojure repl running along with a pure java application running under Tomcat and invoke commands from the repl, so , in theory we could write java code, compile it and call from clojure repl without restarting the embeded tomcat server, am I correct?

Alex Miller (Clojure team)21:06:11

not exactly - depends what you're doing

Alex Miller (Clojure team)21:06:36

that's not really a clojure question

Alex Miller (Clojure team)21:06:13

depends if you're making new classes (then you need a classloader that knows how to load them) or redefining (there are paths to this in the jvm but it's not trivial to do in general)

Alex Miller (Clojure team)21:06:44

in general, I'd say you should not do any of that. there are probably better ways to accomplish whatever goals you have

Ludwig21:06:54

thanks Alex!

Alex Miller (Clojure team)21:06:32

like, don't write code, just make new instances using existing classes. and make more flexible frameworks if you need more dynamicity (clojure is great for that via its var system)

CyberSapiens9721:06:12

Hey guys, there is any Microservices example in Clojure? But I want something full fledged and mostly ready to production. I want to see some real project of a medium size or bigger. Not really interested in small examples, but I guess I wonโ€™t find this...

CyberSapiens9721:06:55

Small projects are fine to understand stuff, but it really doesnโ€™t teach anything about how a ready to production code is working and should be

Ludwig21:06:52

the idea is, I'm currently working with an old java framework that requires too much time to build, and also, its too coupled so , you never knows how it will behave xD , so I was looking for a solution for faster feedback

Ludwig21:06:46

I guess that the only option for that is jRebel or hotSwap agent

Ludwig21:06:29

but anyway, I'm learning clojure now, to leave this crazy java world ๐Ÿ˜›

noisesmith21:06:37

@vachichng why not make a small set of stubs that call into clojure from the framemwork, then redefine the clojure stuff as needed while developing?

noisesmith21:06:12

the stub should only need to change if you have a major architectural design, and the clojure stuff it calls is freely redefinable without a restart

Ludwig21:06:29

uhmm interesting

noisesmith21:06:29

I've used this pattern for jsvc for example https://github.com/noisesmith/clj-jsvc-adapter

๐Ÿ‘ 4
Ludwig21:06:33

thanks @noisesmith I will have a look at it!

noisesmith21:06:55

the code is very small - it just makes a tiny implementation of every method needed, that uses the clojure API to look up a var with a "magic" name and call it https://github.com/noisesmith/clj-jsvc-adapter/blob/master/src/java/org/noisesmith/Cljsvc.java

noisesmith21:06:32

it expects an ns with start, init etc. as vars, then loads the ns and attempts to call them

Ludwig21:06:00

yeah, its quite intuitive

noisesmith21:06:53

so my hunch is you can do the same with your old java framework - give it methods (probably easier to just do in java), and just make sure everything those methods do can be freely redefined in a repl

noisesmith21:06:04

then no more restarting the framework for code changes