Fork me on GitHub
#clojure
<
2017-04-10
>
noisesmith00:04:43

On the jvm methods aren't functions, they can't exist without some object owning them; on the other hand fields on a class hold values that can stand alone.

noisesmith00:04:43

I like the . / .- distinction and it would have been nice if it were invented for jvm clojure

bronsa07:04:22

noisesmith: it does exist in jvm clojure

noisesmith16:04:31

I meant if it had been invented for the jvm first, and had been mandatory rather than optional...

john00:04:58

Yeah, it wouldn't have been so annoying I wasn't already used to it 🙂 But in cljs it's a requirement, right? Because you can't otherwise differentiate between the two?

noisesmith00:04:39

because in js you can have a method and a field with the same name

noisesmith00:04:57

so you need some way to differentiate

sova-soars-the-sora02:04:57

I'm trying to figure out how to use update-in for a recursive atom of blurbs and comments( comments can be recursive..)

john02:04:30

@sova so like (atom {:resp1 {:content "woot!"} :resp2 {:content "I disagree..." :resp1 {:content "why?"}}}) ...or something like that?

john02:04:58

and it can be potentially infinitely deep?

john02:04:00

If so, you might want to check out specter, by @nathanmarz https://github.com/nathanmarz/specter

matan07:04:03

Question about interface implementations: Why do we have to include this as the first argument to every implemnted method?

pesterhazy07:04:18

@matan, in a defrecord you mean?

matan07:04:47

ummm, in reify actually

matan07:04:54

Example code:

matan07:04:13

(def driver
  "a driver for our test bot"
  (reify ApiInterface
    (sendToBot [this message]
      (println "sample driver sending message" message))
    (receiveFromBot [this message]
      (println "message received from bot" message)
    )))

pesterhazy07:04:31

well it's Java, i.e. OOP, after all

pesterhazy07:04:12

so the messages are sent to an object, and Clojure chooses to make this an explicit argument to fns (like python, but unlike javascript or java)

matan07:04:22

but a simple macro could have added the this

matan07:04:47

rather than user code being responsible for including it

pesterhazy07:04:13

that would have introduced a special symbol, which is not very lisp-y

matan07:04:22

not sure I get it

pesterhazy07:04:51

in clojure you almost always choose your own binding names

matan07:04:52

why does Clojure choose to make this an explicit argument

matan07:04:04

what are the benefits of that?

pesterhazy07:04:15

I can't speak for the language designer

pesterhazy07:04:28

but one benefit is that the scoping rules are obvious

pesterhazy07:04:40

(compare javascript, with unclear scoping!)

matan07:04:56

Sure but how would you possibly leverage that explicit argument in user code, as a developer?

pesterhazy07:04:17

how do you mean?

matan07:04:46

Without some user leverage, this is pure boilerplate, unless a developer can leverage this argument in some way to get some behavior they can't get without it being explicit in the code

matan07:04:02

Can you think of any leverage?

pesterhazy07:04:19

the leverage is that you can access the object 🙂

matan07:04:58

Right, doh

pesterhazy07:04:21

btw feel free to replace this with _ if you don't need it

matan07:04:41

nice idea

matan07:04:00

thanks guys!

pesterhazy07:04:16

you're welcome 🙂

matan07:04:44

I like this forum ✨

triss10:04:48

hey all, what’s the most common means of handling errors with -> and ->>?

triss10:04:05

i’d like my pipelines to stop execting when one of the functions fails

triss10:04:21

should I be throwing catching/exceptions?

mariusz_jachimowicz10:04:16

I am curious who is against columnar alignment in let statements, require statements, declarations,....Is it only due to manual fixing all lines after changes?

wiseman17:04:42

Yes, it’s that it too much additional work/thought for the benefits that i see.

triss11:04:43

thanks @sveri I’ll take a look

borkdude11:04:11

Using the expectations library, how can I wrap two expectations in a let where I perform a request only one time? E.g.

(e/expect #"^text/html" (e/in (content-type (home-httpkit))))
(e/expect #"<body" (get (home-httpkit) :body))
I want something like (let [resp (home-httpkit)] ...), but not want to perform the side effect at the top level

schmee11:04:00

@triss some-> and some->> can come in handy as well, http://clojuredocs.org/clojure.core/some-%3E

rovanion11:04:56

The macro clojure.spec/keys and clojure.spec/keys* expects a seq of keys as the value of its named arguments :req and :opt. I want to use the same list of keys for two different specs, one using keys and one using keys*. But the macros get passed the quoted symbol for the variable and not the value of it. Is it possible to unpack the value pointed to by a symbol at read time like the common lisp #. syntax?

triss11:04:47

@schmee I knew I’d seen something like that before! brilliant thanks

schmee11:04:34

@rovanion I think you’ll have better luck with that question in #clojure-spec

rovanion11:04:34

I've gone ahead and asked in there too. But the question itself is Clojure generic even though the specific macro is from spec.

mpenet12:04:20

@rovanion you can use eval or write a macro (only the latter with cljs I think)

mpenet12:04:41

but I know: yuk

mpenet12:04:27

(let [keys [...]] (eval `(s/def ::foo (s/keys :req-un ~keys))))

mpenet12:04:38

if we ever get spec form conforming we could manipulate actual data and unform the specs at runtime

mpenet12:04:19

but it's taking dust in JIRA atm (CLJ-2112)

bronsa12:04:42

I seem to recall alex saying that that ticket is definitely going to happen

bronsa12:04:56

is it's not if but when :)

mpenet12:04:04

that's what I meant 🙂

rovanion12:04:23

Thank you mpenet, even though it's ugly it actually works unlike all I've tried thus far.

mpenet12:04:32

it might take a while or be done tomorrow, but I wouldn't hold my breath

rovanion12:04:09

Want to write the SO answer and get those sweet imaginary internet points or should I fill it out?

mpenet12:04:24

feel free to do it, I don't really do SO

rovanion12:04:04

Cool. Writing issues down help me reason about them. And when I'm already doing that I might as well post it to SO.

h.elmougy13:04:19

is it possible to destructure based on the value of an element e.g. (let [{[{ v "a" "val" 1}] :y} {"x" 1 :y [{"a" 3 "val" 2} {"a" 2 "val" 1}]}] (println v)) ;; need to have the value of v -> 2

dpsutton13:04:23

(let [x {:a 1 :b 1}]
  (match [x]
    [{:a _ :b 2}] :a0
    [{:a 1 :b 1}] :a1
    [{:c 3 :d _ :e 4}] :a2
    :else nil))
;=> :a1

h.elmougy13:04:39

it is not possible without core.match, isn't it?

souenzzo13:04:00

(defn my-get [x k] (let [{v k} x] v)) @h.elmougy ??

mpenet13:04:41

@h.elmougy no pattern matching out of the box in clojure, you can always write a cascade of cond to get there (that's basically what core.match does)

carter.andrewj14:04:00

Anyone know how to get the size (in bytes) of an object?

carter.andrewj14:04:17

I want to be able to log how much data is being processed by a pipeline I'm working on

carter.andrewj14:04:53

Would (count (byte-array x)) give me what I need? And is it in any way efficient?

carter.andrewj14:04:02

Or am I better looking at java for a solution here?

blane17:04:11

hey guys, I keep getting the following error

Uberjar aborting because jar failed: Could not resolve dependencies
when trying to
lein uberjar
. I'm trying to build within a container for a CI system. There may be an issue with auth, is it possible to
:mirrors {
    "central" {
      :name "Nexus-Central"
      :url "https://../repository/maven-public/"
      :repo-manager true }
    #"clojars" {
      :name "Nexus-Clojars"
      :url "https://.../repository/clojars/"
      :repo-manager true }}
is it possible to add username and password of nexus within this block? or any other suggestions?

benzap18:04:33

Hey guys, i'm trying to use yesql, but it only accepts a 'db-spec' when connecting to my database. However, I want to use a connection uri string, and there doesn't appear to be a way to turn a connection uri string into a db-spec map. Any idea on how to go about converting a connection uri string into a db-spec map?

pesterhazy18:04:14

{:connection-uri "postgresql://"}

benzap18:04:11

@pesterhazy that seems to work, but i'm running into unrelated issues. Thanks!

qqq20:04:22

Anyone know what happened to http://cloxp.github.io/ (seems like no activity after 2015) -- the idea of "bringing smalltalk liveness to clojure" seems brilliant

dealy22:04:51

Hello all, I'm curious about using the functionality of a timer in clojure. In my app I have several go-loops that run forever validating that their database connections can still return data. When the test fails the old connection is closed and a new one is opened. I didn't find any canonical example of how to do this in clojure. Instead of just using Java's scheduledExecutorService I rolled my own using the go-loop, timeout and a channel. Things seemed ok during development on my local box, but on moving this out to AWS and having the DB on a different machine than my clojure service I find that my periodic-task logic fails to continue after a few days. So far I haven't been able to replicate these failure on my local dev box. Is there a suggested way of doing this type of thing in Clojure or do most just use something like Java's scheduledExecutorService?

noisesmith22:04:56

@dealy I’v efound scheduledExecutorService reliable and easy to use, but there are other options - eg. quasar

dealy22:04:31

yea, quasar/pulsar does look pretty interesting, but it would be a bit much to bring in just for this type of task

tanzoniteblack22:04:49

@dealy any particular reason you don’t just want to use a proper connection pool like hikariCP, bonecp, or c3p0?

dealy22:04:01

There is some advanced JDBC features I'm using that aren't supported well in hikariCP which is what I use for regular DB connections, so I've found that I have to manage this stuff on my own for JDBC driver (impossibl) that I'm using so I can make use of Postgres notifications.

tanzoniteblack22:04:12

That’s a good reason not to use a connection pool 🙂

tanzoniteblack22:04:22

Do you get any errors with your core.async version, or does it just fail to run eventually? And when I’ve done things like this in the past, I’ve generally just run a thread in daemon mode with a function that calls Thread/sleep for the required period of time (a la http://stackoverflow.com/questions/4560594/how-can-i-create-a-constantly-running-background-process-in-clojure ). Which is probably not as elegant or as nice as just using ScheduledExecutorService, but as generally been reliable for me in the rare cases when I need something like this

dealy22:04:01

no errors, its been a real pain trying to debug this. Since it just stops working after a few days (not all of them of course) it feels like either something is blocking or some resource is being exhausted.

tanzoniteblack22:04:14

core.async, since it’s macro-magic™, tends to have some edge cases where things get wonky, especially around resource starvation. Therefore, I tend to only use it when actually doing async I/O, and instead using threadpools/executorservice/raw threads for anything that I need to have reliably running in the background at (semi-)regular intervals

tanzoniteblack22:04:51

at least then what’s happening is obvious and generally debugabble (ok, jstack, what’s the status of thread X?)

tanzoniteblack22:04:22

pulsar is going to have similar problems of not being able to figure out what’s going wrong if it randomly stops working

dealy22:04:09

hmm, ok that is interesting to hear. My implementation doesn't make any use of thread/sleep or future. Just a go loop that creates a new channel via timeout on each iteration. If there is a possibility of odd behavior with core.async then that could explain why things are so weird here.

noisesmith22:04:54

sure - for example you could leak core.async threads via doing blocking ops in go blocks that don’t finish

noisesmith22:04:09

eventually nothing at all would run

noisesmith22:04:24

(nothing in go blocks that is)

tanzoniteblack22:04:04

or it could be that only your specific go block doing the jdbc stuff gets tied up somehow, so that other go blocks are still able to run…just there’s 1 less available thread in the pool.

tanzoniteblack22:04:34

In general core.async is great, and if you understand it well enough you can avoid pitfalls like this, but it’s not really meant to be a scheduling service.

tanzoniteblack22:04:01

(that’s not to say you can’t use it as one: https://github.com/jarohen/chime )

dealy22:04:52

is there any reason to think that I could be exhausting something by creating a new channel every few seconds? Nothing ever holds a reference to these channels. I suppose it is possible that there is eventually some case where my call to postgres doesn't return and then that would block the thread in the go block. Ok, I think you've convinced me to just dump this idea and use the scheduledExecutorService.

dealy22:04:04

I'll take a look at chime

tanzoniteblack22:04:33

for the note: I actually recommend just using scheduledExecutorService, not chime. Just pointing out that it can be done

tanzoniteblack22:04:53

since your calls to postgres are likely blocking anyways, core.async is not really a great fit for this, and chime works on top of core.async like what you've been trying to solve

john23:04:11

certainly not a solution, but until you find one, can you just restart the service every hour? Might clear out any issues that are building up in the core.async process.

dealy23:04:20

Sometimes the sledgehammer is appropriate. I hope that I can get my system working without having to use one though

tanzoniteblack23:04:05

^^^ I have sadly done this 😢 . Once had a legacy service that somehow developed a bug that caused it to randomly freeze up every once in a while. It wasn’t in active development, but was critical for the company’s data…so instead of fixing it, we ended up just writing a job on jenkins that ssh’d into the machine, kill -9 the java process which allowed the supervisor to restart it…

tanzoniteblack23:04:04

A year or two later, the service stopped freezing up anymore…we left the jenkins job anyways because I stopped trusting it

tanzoniteblack23:04:33

Not one of my proudest moments as an engineer 😄

john23:04:38

Probably not the best practice in Clojure, but Erlang embraces failure, right? Might not be a bad idea to try for both goals, correctness and robustness in the case of failure.

noisesmith23:04:10

Even if you don’t use an ExecutorService, I think this would be simpler with a thread instead of core.async without losing capability. Thread/sleep, ensure connection, repeat. For bonus points have something else that kickstarts that one if it is no longer running. You have a top level handle to the process itself, so you can always see what its specific status is, even see it’s current stack.