Fork me on GitHub
#clojure
<
2019-12-04
>
sasho.popov14:12:51

Does anyone know why ##NaN (not a number) is a non-negative number? 🙂

sasho.popov14:12:51

Does anyone know why ##NaN (not a number) is a non-negative number? 🙂

manutter5114:12:14

What's the definition for non-negative?? It's not a built-in.

manutter5114:12:50

I'm actually more surprised that NaNs return true for number? and float?.

andy.fingerhut14:12:08

I don't know what non-negative? is, either, but its definition would probably make it clear, once you know how ##NaN behaves in basic comparisons in Java: https://github.com/jafingerhut/batman

andy.fingerhut14:12:37

Probably a spec predicate?

andy.fingerhut14:12:39

There are generators that avoid generating NaN "values", in case they are causing you problems in generative/property-based testing, specifically because they are not = to themselves.

gerome.bochmann14:12:04

Well, is it a negative? No, it's not a negative.

gerome.bochmann14:12:20

So, it's a non-negative.

sasho.popov14:12:37

Yes, excuse me, non-negative indeed comes from the project that I work on. But the most surprising thing to me is the first one (number? ##NaN) .

andy.fingerhut14:12:20

Agreed that sounds weird in English, but both 1.0 and NaN have type java.lang.Double in Java, and number? 's return value is based upon the type of the argument.

manutter5115:12:16

I suppose if you can wrap your head around “NaN is not equal to itself,” you can do the same with “Not-A-Number is a number”.

dmarjenburgh14:12:52

I remember there was a library that takes a regexp and returns a generator that matches that regexp. Does anyone know what I’m talking about?

qythium14:12:15

Sometimes in the middle of a REPL session my exception stacktraces will suddenly stop working - any idea why that could be?

qythium14:12:37

(try (+ 1 nil) (catch Exception e e))
;; => #error {
;;     :cause nil
;;     :via
;;     [{:type java.lang.NullPointerException
;;       :message nil}]
;;     :trace
;;     []}

andy.fingerhut15:12:32

Very likely you are not using this command line option when starting your JVM: -XX:-OmitStackTraceInFastThrow Without that option, sometimes the JVM optimizes out stack traces.

qythium15:12:04

Thanks! Will try adding that and see if the behaviour pops up again

qythium15:12:38

Would it be a good idea for tools like Cider to enable that option by default?

qythium15:12:35

as a dev-time REPL you probably want full stacktraces all the time

andy.fingerhut15:12:22

Personally, I think it would be a good idea for the JVM to enable that option by default 🙂 But defaults are hard to change when you maintain a system with strong backwards compatibility. You will have to ask on the #cider channel what they recommend. It is pretty easy to copy and paste Leiningen project.clj file templates and clj/clojure deps.edn template files that contain those options.

qythium15:12:32

Aha, I should have tried googling it before asking here 😅 Seems like it's a pretty common problem

andy.fingerhut15:12:03

I have heard from people running JVM's in production that just about everybody turns it on

andy.fingerhut15:12:20

i.e. uses that or a similarly effective command line option when starting production JVMs

restenb16:12:33

does cheshire https://github.com/dakrone/cheshire have a maven target?

vemv16:12:17

why not ask over github issues?

holyjak17:12:25

Any tips why could this > Exception in thread "Clojure Server repl" http://java.net.SocketTimeoutException: Accept timed out [at server.clj:111 in (.accept socket)] be happening when asking Clojure to start a socket REPL server? (via -Dclojure.server.repl="{:port 55555 :accept clojure.core.server/repl}") It works locally but throws these exceptions on AWS Fargate. What does it mean that (.accept socket) times out? I am not even trying to connect yet... (Clojure 1.10.1 on OpenJDK JRE 11 on Linux) From JavaDoc: > SocketTimeoutException - if a timeout was previously set with setSoTimeout and the timeout has been reached. Does it mean that somewhere in the code (though I do not see that) I set a timeout and the server waits max this time for a conn to be made instead of "forever"?

alexmiller17:12:49

Clojure's socket server does not set a socket timeout

holyjak17:12:00

Indeed. So how is it possible I am getting this exception?!

alexmiller17:12:42

there may be some setting that you can specify in Java as a system property or even at os level that dominates when run in this env

alexmiller17:12:29

In standard JDK, there is .client.defaultConnectTimeout for example, not sure if you're using OpenJDK or Amazon's Corretto or if that has different properties

alexmiller17:12:51

it could also be that what you are trying to do needs additional config in the networking setup in aws

holyjak17:12:38

I am also running jetty on another port - which I assume also uses ServerSocket - and it doesn't throw exceptions so I do not think there is a system-level property, but will try to verify anyway. Yes, it is possible it is some AWS / Docker weirdness...

alexmiller17:12:34

you might need to set address on the server options

alexmiller17:12:01

it defaults to loopback

alexmiller17:12:37

might need an ipv6 address for example, etc

holyjak17:12:33

I have to compare to what Jetty is doing because that works. I can try address "0.0.0.0" I guess to star with... Thank you!!!

carocad17:12:35

is this a valid keyword : ? clojure reader seems to accept it but cursive doesnt and from my understanding of the keyword/symbols reference it should not be valid right ?

mark54017:12:44

My understanding is that several chars disallowed in keywords according to the clojure doc, are actually allowed currently. Cursive may be trying to do you a favor by honoring the doc. I suggest asking in #cursive .

carocad17:12:51

@ maybe my question was not properly formulated. I meant “is this a valid literal keyword …” ?

carocad17:12:43

I can input it on a repl, I am not trying to programmatically create it

andy.fingerhut17:12:04

It is not supported according to the Clojure reference docs, but the Clojure reader accepts things that are not supported, anyway.

manutter5118:12:30

“Supported” might be a better word than “valid,” as in “the current reader will accept it, but there’s no guarantee that future versions will.”

hiredman18:12:33

you definitely should not use it as a literal keyword, regardless of if the reader accepts it, because the reader will interpret it as a namespaced keyword, which is almost certainly not what you want

hiredman18:12:24

user=> (namespace :)
"http:"
user=>

carocad18:12:53

ok, seems like I am opening a pandora box 😅

carocad18:12:21

since I am trying to create a grammar for clojure I am running into all these edge cases 😕 https://github.com/carocad/parcera

andy.fingerhut18:12:44

You definitely have some choices to make on whether you want to try to be compatible with some version of Clojure's built-in reader (it has changed only very slowly over different versions, if at all), or use some other behavior/documentation as your reference you are trying to conform to.

mark54018:12:22

There are definitely some chars that are commonly used in keywords for Hiccup syntax, but are disallowed in the docs/spec. For example, "." (period) is not allowed in the keyword name according to the docs, but is very commonly used. So it seems very likely that it will be supported by the reader forever.

rgm18:12:09

Can anyone recommend me either a lib or sample code to get my head around how to structure a background job queue in Clojure? I presume most people roll their own with core.async or similar. I'm coming from using Sidekiq in Ruby and got about 1/3 through inventing my own thing before realizing it's probably simpler than I think it is. (Same-ish use case: return a web request super quick with a 202 Accepted, and spin off a long processing job for the browser to come pick up later).

dj94219:12:35

I'd consider an agent. They have fallen somewhat out of fashion with the advent of core.async but they're still around and working perfectly well. 🙂

rgm19:12:11

huh, no kidding. Hadn't even considered that.

lukaszkorecki19:12:13

Why not use something like Sidekiq then? Carmine ships with a redis-based message queue https://github.com/ptaoussanis/carmine/blob/master/src/taoensso/carmine/message_queue.clj

contact90419:12:07

How can I terminate a clojure program if an exception is met?

manutter5119:12:14

(System/exit 0) or whatever error code number you want to return.

contact90419:12:22

(.System/exit)?

ghadi19:12:31

No need to be fancy. Write one function that takes an event (as a data structure, not wire format) and processes it. Then write the glue code (a glorified polling loop) to process all the events, passing in the desired handler

contact90419:12:44

nevermind, it is (System/exit 1)

ghadi19:12:04

Do not interleave glue with event specifics

ghadi19:12:41

You don’t need core.async or agents for this

rgm19:12:31

and that's off on its own thread, and we're done?

ghadi19:12:24

Sure. The whole worker loop is in a thread

ghadi19:12:49

Keep it dumb and then refine. Don’t reach to libraries too early

rgm19:12:34

Well. That does meet my growing expectation that 5 lines of clojure takes over from huge swathes of library code in my old life.

ghadi19:12:40

Consider retry policies, etc.

rgm19:12:15

yeah, here in the first iteration shrugging and making the user try again is OK.

contact90419:12:47

Howdy! I am catching an Exception inside a try/catch. I want to display the exception with (timbe/warn (ex-data e)) but it is not being displayed

hiredman19:12:33

what do you mean by empty and not being displayed?

alexmiller19:12:53

ex-data is just the map of data, not the message. It can be empty.

hiredman19:12:00

if ex-data is empty, you will still get a log line for it

contact90419:12:59

it is displayed as nil

hiredman19:12:03

if you are not getting a log line, that means you are not catching an exception, either because one is not being thrown, or it is being thrown outside of the scope of your try/catch

contact90419:12:13

19-12-04 19:18:36 Tardis WARN [flowers.stuff:152] - nil

hiredman19:12:36

that is a valid return value from ex-data

hiredman19:12:48

user=> (ex-data (Exception.))
nil
user=>

tvalerio19:12:58

Hi How could I connect to a Postgres database using tunnel with a bastion in AWS? I’m trying to do something like this using clj-commons/clj-ssh but I get timeout connection to the database

(ns app.migrations
  (:require [ragtime.jdbc :as jdbc]
            [ragtime.repl :as repl]
            [clj-ssh.ssh :as ssh]))

(def connection { :ip "0.0.0.0" ;ip of ec2 bastion
                  :port "22"
                  :username "ec2-user"
                  :private-key-path "ec2-key.key" ;ec2 bastion key
                  })

(def db-spec "jdbc:")

(defn load-config
  []
  {:datastore  (jdbc/sql-database db-spec)
   :migrations (jdbc/load-resources "migrations")})

(defn migrate-implantation
  []
  (let [agent (ssh/ssh-agent {:use-system-ssh-agent false})]
    (ssh/add-identity agent {:private-key-path (:private-key-path connection)})
    (let [session (ssh/session
                    agent
                    (:ip connection)
                    {:username (:username connection) :strict-host-key-checking :no})]
      (ssh/with-connection session
        (repl/migrate (load-config))))))

borkdude19:12:48

how do I implement AFn in clojure for a deftype?

borkdude19:12:24

(deftype Foo []
  clojure.lang.AFn
  (throwArity [this n]
    ...
didn't work

hiredman19:12:01

You can do protocols or interfaces like that

alexmiller19:12:05

you can either implement IFn or use a proxy

slipset20:12:41

So a somewhat stylistic question:

slipset20:12:01

Say I have a couple of sideeffecting functions, eg

slipset20:12:08

(defn store! [db entity] ...)
(defn publish! [queue entity] ...)
(defn send-email! [srvr entity] ...)

slipset20:12:31

My goto approach for coding up this would be

slipset20:12:53

(->> entity (store db) (publish! queue) (send-email! srvr))

slipset20:12:23

But it feels kind’a wrong, since these sidefeffecting functions should really be returning void.

dpassen120:12:22

(doto entity
  (store db)
  (publish! queue)
  (send-email! srvr))

slipset20:12:27

what’s the idiomatic way to do this? doto

borkdude20:12:16

yeah, or just do 😛

noisesmith20:12:46

doto gets the arg order wrong for the example above, but that's easy to fix by rewriting the functions

slipset20:12:08

doto-last 🙂

borkdude20:12:56

(doto entity ((flip store!) db)).. blegh... just do would do it for me 😉

noisesmith20:12:53

there's a solid idiom of a function that acts like a method taking its object first, and to me those functions are trying to be methods on entity

slipset20:12:52

it’s akin to db.store(entity), queue.publish(entity) etc

slipset20:12:21

so with doto this would be entity.store(db), entity.publish(queue) etc.

slipset20:12:48

That would be like programming with mixins or some such.

borkdude20:12:54

or in other programming paradigms it could be an IO Entity state m-word thing

andy.fingerhut21:12:05

In typing up the transcript of Rich Hickey's "Clojure Concurrency" talk, and then looking for, finding, and running the code he demonstrated and described during that talk, that was pre-Clojure 1.0 release when he wrote it, and it still runs perfectly with Clojure 1.10.1.

andy.fingerhut21:12:25

No big news there -- just kind of surprises me, despite already knowing the value Clojure implementers place on backwards compatibility.

markbastian22:12:40

Does anyone recall a Clojure talk that discussed debugging the Deep Space 1 mission using a Lisp REPL? I've looked at the conj talks for the last 5 years and I can't seem to find it. Perhaps it was at a different conference or it's just in my head that this talk actually happened.

alexmiller22:12:15

I don't remember a talk about that, but I have heard the anecdote

markbastian22:12:20

Yeah, that's the reference I have for the description of the incident. Perhaps I heard it described in a talk and misattributed it to a Clojure-related conference talk.

hiredman22:12:39

that might be from the component talk

markbastian22:12:29

Might also be this (not a Clojure talk), but describes the incident https://www.youtube.com/watch?v=_gZK0tW8EhQ

markbastian22:12:18

That's it! Glad to know I am not hallucinating (at least in this case). Thanks!

ognivo22:12:49

Do we know any Clojure flavoured terraformers like Ansible / Docker-Compose so that I could terraform a dedicated Linux machine to my taste and have this configuration working for the nearest 10 years? I’ll be migrating a legacy project to a new server, will have to install MySQL, Redis, certbot and would like to preserve upstart/systemd init scripts.

hiredman23:12:33

I can't imagine any of the tools I've seen for that kind of thing (clojure based or not) being stable across 10 years. I think your best bet is to write a shell script

ognivo23:12:56

I know, right? I’m quite leaning to Ansible though

hiredman23:12:18

yaml is gross

ognivo23:12:54

yeah, I know, I know

p-himik12:12:33

If you deploy the tool yourself and don't change its version, it won't become unstable. Otherwise, there are potential problems even with bash , at least when you suddenly have to deal with an older version.

ognivo14:12:56

@ sure! thanks for the input mate!

ag23:12:32

Sorry folks, I got another “stupid” question. Is it possible to “pass” data from defmulti to defmethod? It’s somewhat hard to explain, this is what I mean:

;; I have a defmulti that dispatches on the 'type' of a thing,
;; the 'type' can be determined only by
;; fetching data from the db

(defmulti foo [id]
  (let [{:keys [type] :db-ctx}] (db/get-from-db {:id id})
       (keyword type)))

(defmethod foo :bar-type []
  ;; now the question is:
  ;; can I re-use the data fetched from the DB (db-ctx) in the defmethod?
  ;; so I don't have to send another request
  )

noisesmith23:12:37

doing IO inside a multimethod dispatch seems weird to me

hiredman23:12:05

make a function that takes an id, looks it up in the db, then calls the multimethod on the result

noisesmith23:12:24

I mean technically you could have a memoized function from object to fetched id, but it's still a weird interaction

hiredman23:12:42

and there is no reason to call keyword on the type from the database

ag23:12:51

I mean what you’re saying makes sense about IO and stuff. As I said “it’s a stupid question”. I just needed to illustrate the problem.

ag23:12:56

Thank you guys.

ag23:12:49

so I can dispatch on “db data” but defmulti would return (:type db-data) then defmethod will have access to it. Makes sense. Thank you @hiredman