beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
zach 2020-12-01T01:44:19.063100Z

Hi, i was wondering if anyone had experience using clj-http’s async requests? I am trying to make a request to an endpoint that is cancelled after 2 seconds. If it succeeds, it returns the response body, if it is cancelled or fails it returns nil.

zach 2020-12-01T01:45:20.063800Z

in the [clj-http readme](https://github.com/dakrone/clj-http) there’s a nice example of an async request with cancellation;

(import '(java.util.concurrent TimeoutException TimeUnit))

(let [future (client/get "<http://example.com/slow-url>"
                         {:async true :oncancel #(println "request was cancelled")}
                         #(println :got %) #(println :err %))]
  (try
    (.get future 1 TimeUnit/SECONDS)
    (catch TimeoutException e
      ;; Cancel the request, it's taken too long
      (.cancel future true))))

zach 2020-12-01T01:46:13.065Z

but the functions do a println, and I want the response body. When I try to just return the response (by switching out #(println :got %) with (fn [res] res)` I only get an apache.http.BasicHTTPResponse, which doesn’t include the body.

zach 2020-12-01T01:47:02.065900Z

My issue seems similar to the issue raised in clj-http here: https://github.com/dakrone/clj-http/issues/512, but the function offered as a solution doesn’t seem to be correct…or like valid clojure: `

zach 2020-12-01T01:49:09.067800Z

I hesitated on asking this in the clj-http github repo just cos this ticket and its pr are over a year old, and figured I may not get too quick a response, and is likely an issue with my understanding more than the library itself…So I wanted to see if any folk here had experience with this. Thank you!

st3fan 2020-12-01T02:11:45.068500Z

Can anyone recommend a scheduler library (cron-like) that is not abandoned 8 years ago? 😕

walterl 2020-12-01T21:37:16.151800Z

For Integrant systems there's https://github.com/troy-west/cronut

st3fan 2020-12-01T02:12:18.069200Z

I'm browsing through projects on Clojars and so far I mostly see projects without releases, broken documentation and last change 6+ years ago

phronmophobic 2020-12-01T02:15:24.069600Z

have you looked at quartzite? https://github.com/michaelklishin/quartzite

st3fan 2020-12-01T02:23:25.070100Z

I think I just saw a fork that someone picked up again

st3fan 2020-12-01T02:24:24.070300Z

https://github.com/daniel-zamora/quartzite maybe

st3fan 2020-12-01T02:45:16.071Z

I’m thinking I should just build something around java.util.concurrent.ScheduledExecutorService

1✅
seancorfield 2020-12-01T03:29:55.071100Z

@webmaster601 I'm pretty sure your callback functions have to return their argument (or a modified version of it). Yours return nil (because println returns nil). You want #(do (println :got %) %) #(do (println :err %) %) -- which is what that issue is suggesting: (fn [_} _) returns its argument.

seancorfield 2020-12-01T03:34:36.071600Z

@st3fan Or just use Quartz itself via interop?

st3fan 2020-12-01T03:38:04.072300Z

I settled on quartzite .. it it not really a pretty api but it works

seancorfield 2020-12-01T03:56:51.074Z

@st3fan I noticed that the fork you mention has posted a single snapshot to Clojars under Daniel's personal group and then switched to gov.nasa.earthdata and posted another snapshot, but I didn't see any non-snapshot releases from that fork yet. Just FYI.

zach 2020-12-01T04:04:38.074100Z

Ah, right! I shall try it! I tried something similar to your do function above, but it returned a condensed apache http response, with no response body. I’ll try it again though with some fresh eyes!

st3fan 2020-12-01T04:13:30.074400Z

yeah messy

st3fan 2020-12-01T04:13:47.074600Z

I just grabbed clojurewerkz/quartzite instead

yubrshen 2020-12-01T04:32:16.076200Z

I'm learning to use jdbc.next, it seems to me that the following code segment caused the error below:

(let [datasource (jdbc/get-datasource (:db env))]
    (jdbc/execute! datasource ["SELECT 1"])
  ...)
The error:
Execution error (ConnectException) at java.net.PlainSocketImpl/socketConnect (PlainSocketImpl.java:-2).
Connection refused (Connection refused)
I'm supposed to use postgres database with the driver and wrapper in deps.edn
seancorfield/next.jdbc {:mvn/version "1.1.613"}
org.postgresql/postgresql {:mvn/version "42.2.11"}
Here is the configuration of the expected database:
:db {:dbtype "postgres"
      :subprotocol "postgresql"
      :subname "postgres"
      :user "postgres"
      :password "scrapsafe"}
I realized that I have not start the postgres database program (server), I guess that that might be the cause of the error. Could you point me to a tutorial of how to install and start the database server and all the required setup/configuration for the database to get the above code working? I'm following the excellent live coding of https://www.youtube.com/watch?v=J4ggrmvnTIY ( Functional Friday 4 - Building a Web App with Clojure ) Thanks!

seancorfield 2020-12-01T04:58:39.077Z

@yubrshen For dev work, I use Docker to stand up a local PostgreSQL instance.

seancorfield 2020-12-01T05:00:39.077400Z

Here's what I use for testing clojure.java.jdbc against PG

docker run -p 5432:5432 --name clojure_test -e POSTGRES_PASSWORD=clojure_test -e POSTGRES_USER=clojure_test -d postgres

seancorfield 2020-12-01T05:04:15.079Z

For testing next.jdbc, I use an Embedded PostgreSQL library (which needs special startup in the application) but the same org.postgresql/postgresql driver (version 42.2.10 right now, against the 12.2.0 embedded database).

seancorfield 2020-12-01T05:05:32.080200Z

If you don't want to use Docker, you'll have to follow the documentation on the PostgreSQL website. I've never installed PG locally tho', I've always used Docker or the embedded server.

yubrshen 2020-12-01T05:30:02.081500Z

@seancorfield Thanks for the prompt help. I'll try the docker first hoping it would work for the purpose of practice of web server application.

yubrshen 2020-12-01T20:18:01.150600Z

@seancorfield Thanks for the generous help! I'll try them.

yubrshen 2020-12-02T06:12:30.197600Z

@seancorfield Following your advice, adding the following dependencies to deps.edn:

seancorfield/next.jdbc {:mvn/version "1.1.613"}
        org.postgresql/postgresql {:mvn/version "42.2.10"}
        io.zonky.test/embedded-postgres {:mvn/version "1.2.6"}
        io.zonky.test.postgres/embedded-postgres-binaries-linux-amd64 {:mvn/version "12.2.0"}
        io.zonky.test.postgres/embedded-postgres-binaries-windows-amd64 {:mvn/version "12.2.0"}
With the following code:
(ns yubrshen.friendwall
  (:require [ring.adapter.jetty :refer [run-jetty]]
            [compojure.core :refer :all]
            [compojure.route :as route]
            [ring.middleware.defaults :refer [wrap-defaults site-defaults]]
            [rum.core :refer [defc render-static-markup]]
            [config.core :refer [env]]
            [next.jdbc :as jdbc])
  (:import (io.zonky.test.db.postgres.embedded EmbeddedPostgres))
  (:gen-class))

(defonce embedded-pg (EmbeddedPostgres/start)) ;; &lt;- line 12
When I ran it as an application:
sudo clojure -M -m yubrshen.friendwall
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See <http://www.slf4j.org/codes.html#StaticLoggerBinder> for further details.
Syntax error (IllegalStateException) compiling at (yubrshen/friendwall.clj:12:1).
Process [/tmp/embedded-pg/PG-4cfbcaeb13da88ab2f0c925cea29854b/bin/initdb, -A, trust, -U, postgres, -D, /tmp/epg61605004942586187, -E, UTF-8] failed
However, when I execute the code of line 12 in REPL, I got the following error:
1. Caused by java.io.IOException
   error=13, Permission denied

          ProcessImpl.java:   -2  java.lang.ProcessImpl/forkAndExec
          ProcessImpl.java:  340  java.lang.ProcessImpl/&lt;init&gt;
          ProcessImpl.java:  271  java.lang.ProcessImpl/start
       ProcessBuilder.java: 1107  java.lang.ProcessBuilder/start
       ProcessBuilder.java: 1071  java.lang.ProcessBuilder/start
     EmbeddedPostgres.java:  624  io.zonky.test.db.postgres.embedded.EmbeddedPostgres/system
     EmbeddedPostgres.java:  249  io.zonky.test.db.postgres.embedded.EmbeddedPostgres/initdb
     EmbeddedPostgres.java:  156  io.zonky.test.db.postgres.embedded.EmbeddedPostgres/&lt;init&gt;
     EmbeddedPostgres.java:  584  io.zonky.test.db.postgres.embedded.EmbeddedPostgres$Builder/start
     EmbeddedPostgres.java:  478  io.zonky.test.db.postgres.embedded.EmbeddedPostgres/start
                      REPL:   12  yubrshen.friendwall/eval20241
                      REPL:   12  yubrshen.friendwall/eval20241
             Compiler.java: 7177  clojure.lang.Compiler/eval
             Compiler.java: 7132  clojure.lang.Compiler/eval
                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  clojure.core/eval
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj: 1973  clojure.core/with-bindings*
                  core.clj: 1973  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  437  clojure.main/repl/read-eval-print/fn
                  main.clj:  437  clojure.main/repl/read-eval-print
                  main.clj:  458  clojure.main/repl/fn
                  main.clj:  458  clojure.main/repl
                  main.clj:  368  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj:  660  clojure.core/apply
                regrow.clj:   20  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  152  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  202  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  201  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  834  java.lang.Thread/run
It seems indeed some kind of access permission problem, as I manually checked:
ls /tmp/embedded-pg/PG-4cfbcaeb13da88ab2f0c925cea29854b/bin/initdb
-rwxr--r-- 1 root root 129K Dec  1 21:10 /tmp/embedded-pg/PG-4cfbcaeb13da88ab2f0c925cea29854b/bin/initdb*
only accessible to root! Really appreciate your help again! (I had to use sudo to run the app, as I found that as web server, without sudo, the web server could be started.) I tried to run manually:
sudo /tmp/embedded-pg/PG-4cfbcaeb13da88ab2f0c925cea29854b/bin/initdb -A trust -U postgres -D /tmp/epg61605004942586187 -E UTF-8
[sudo] password for yshen:
initdb: error: cannot be run as root
Please log in (using, e.g., "su") as the (unprivileged) user that will
own the server process.
It seems that the above might be the clue. I need to learn how to run the app properly. My environment is Ubuntu 18.04 in WSL1 (My Windows 10 is too old for WSL2.)

seancorfield 2020-12-02T18:05:09.233800Z

Could be a WSL1 issue. I've never needed to run a separate process -- just start my Clojure app up -- using a non-privileged user. Never seen the problem you're seeing. Like I said earlier, you might be better off just running PG via Docker, using that command I pasted in -- but I suspect you won't be able to with WSL1. I've been running Insider builds of Windows for years (Fast Ring which is now the Dev Channel) so I always have the latest prerelease of Windows and so it's easy for me to run WSL2 etc.

yubrshen 2020-12-02T18:57:11.252400Z

@seancorfield Thanks! It's my fault of having run the app by sudo, which caused initdb executable not accessible. The problem has been resolved by not running by sudo.

yubrshen 2020-12-02T19:09:11.252700Z

Now, this problem would be really tough for me to figure out. Here is the code where the last line caused the error:.

(ns yubrshen.friendwall
  (:require [ring.adapter.jetty :refer [run-jetty]]
            [compojure.core :refer :all]
            [compojure.route :as route]
            [ring.middleware.defaults :refer [wrap-defaults site-defaults]]
            [rum.core :refer [defc render-static-markup]]
            [config.core :refer [env]]
            [next.jdbc :as jdbc])
  (:import (io.zonky.test.db.postgres.embedded EmbeddedPostgres))
  (:gen-class))

(defonce embedded-pg (future (EmbeddedPostgres/start)))
(def ^:private datasource (atom nil))
(reset! datasource
        (.getPostgresDatabase ^EmbeddedPostgres @embedded-pg)) ; &lt;- failure here
In the REPL, when evaluating the last expression, I got:
1. Unhandled java.lang.ClassCastException
   class io.zonky.test.db.postgres.embedded.EmbeddedPostgres cannot be cast to
   class java.util.concurrent.Future
   (io.zonky.test.db.postgres.embedded.EmbeddedPostgres is in unnamed module of
   loader 'app'; java.util.concurrent.Future is in module java.base of loader
   'bootstrap')

                  core.clj: 2298  clojure.core/deref-future
                  core.clj: 2320  clojure.core/deref
                  core.clj: 2306  clojure.core/deref
                      REPL:   15  yubrshen.friendwall/eval20660
                      REPL:   14  yubrshen.friendwall/eval20660
             Compiler.java: 7177  clojure.lang.Compiler/eval
             Compiler.java: 7132  clojure.lang.Compiler/eval
                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  clojure.core/eval
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj: 1973  clojure.core/with-bindings*
                  core.clj: 1973  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  437  clojure.main/repl/read-eval-print/fn
                  main.clj:  437  clojure.main/repl/read-eval-print
                  main.clj:  458  clojure.main/repl/fn
                  main.clj:  458  clojure.main/repl
                  main.clj:  368  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj:  660  clojure.core/apply
                regrow.clj:   20  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  152  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  202  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  201  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  834  java.lang.Thread/run
While running from command line, I only got the following error trace:
{:clojure.main/message
 "Execution error (NullPointerException) at clojure.main/main (main.java:40).\nnull\n",
 :clojure.main/triage
 {:clojure.error/class java.lang.NullPointerException,
  :clojure.error/line 40,
  :clojure.error/symbol clojure.main/main,
  :clojure.error/source "main.java",
  :clojure.error/phase :execution},
 :clojure.main/trace
 {:via
  [{:type java.lang.NullPointerException,
    :at [clojure.core$apply invokeStatic "core.clj" 665]}],
  :trace
  [[clojure.core$apply invokeStatic "core.clj" 665]
   [clojure.main$main_opt invokeStatic "main.clj" 514]
   [clojure.main$main_opt invoke "main.clj" 510]
   [clojure.main$main invokeStatic "main.clj" 664]
   [clojure.main$main doInvoke "main.clj" 616]
   [clojure.lang.RestFn applyTo "RestFn.java" 137]
   [clojure.lang.Var applyTo "Var.java" 705]
   [clojure.main main "main.java" 40]]}}

/tmp/clojure-18342691853881556298.edn (END)
Really appreciate your help!

yubrshen 2020-12-02T19:40:21.254Z

It seems that I'm still missing something for starting the embedded PG, after evaluating (defonce embedded-pg (future (EmbeddedPostgres/start))) I evaluated

(realized? embedded-pg)
Got the similar error:
1. Unhandled java.lang.ClassCastException
   class io.zonky.test.db.postgres.embedded.EmbeddedPostgres cannot be cast to
   class clojure.lang.IPending
   (io.zonky.test.db.postgres.embedded.EmbeddedPostgres and
   clojure.lang.IPending are in unnamed module of loader 'app')

                  core.clj: 7533  clojure.core/realized?
                  core.clj: 7533  clojure.core/realized?
                      REPL:   14  yubrshen.friendwall/eval20703
                      REPL:   14  yubrshen.friendwall/eval20703
             Compiler.java: 7177  clojure.lang.Compiler/eval
             Compiler.java: 7132  clojure.lang.Compiler/eval
                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  clojure.core/eval
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj: 1973  clojure.core/with-bindings*
                  core.clj: 1973  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  437  clojure.main/repl/read-eval-print/fn
                  main.clj:  437  clojure.main/repl/read-eval-print
                  main.clj:  458  clojure.main/repl/fn
                  main.clj:  458  clojure.main/repl
                  main.clj:  368  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj:  660  clojure.core/apply
                regrow.clj:   20  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  152  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  202  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  201  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  834  java.lang.Thread/run
evaluating @embedded-pg got similar error.
1. Unhandled java.lang.ClassCastException
   class io.zonky.test.db.postgres.embedded.EmbeddedPostgres cannot be cast to
   class java.util.concurrent.Future
   (io.zonky.test.db.postgres.embedded.EmbeddedPostgres is in unnamed module of
   loader 'app'; java.util.concurrent.Future is in module java.base of loader
   'bootstrap')

                  core.clj: 2298  clojure.core/deref-future
                  core.clj: 2320  clojure.core/deref
                  core.clj: 2306  clojure.core/deref
                      REPL:    0  yubrshen.friendwall/eval20709
                      REPL:   -1  yubrshen.friendwall/eval20709
             Compiler.java: 7177  clojure.lang.Compiler/eval
             Compiler.java: 7132  clojure.lang.Compiler/eval
                  core.clj: 3214  clojure.core/eval
                  core.clj: 3210  clojure.core/eval
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn/fn
                  AFn.java:  152  clojure.lang.AFn/applyToHelper
                  AFn.java:  144  clojure.lang.AFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj: 1973  clojure.core/with-bindings*
                  core.clj: 1973  clojure.core/with-bindings*
               RestFn.java:  425  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   87  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  437  clojure.main/repl/read-eval-print/fn
                  main.clj:  437  clojure.main/repl/read-eval-print
                  main.clj:  458  clojure.main/repl/fn
                  main.clj:  458  clojure.main/repl
                  main.clj:  368  clojure.main/repl
               RestFn.java:  137  clojure.lang.RestFn/applyTo
                  core.clj:  665  clojure.core/apply
                  core.clj:  660  clojure.core/apply
                regrow.clj:   20  refactor-nrepl.ns.slam.hound.regrow/wrap-clojure-repl/fn
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  152  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  202  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  201  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  834  java.lang.Thread/run

yubrshen 2020-12-02T20:08:03.255600Z

The following seems working:

(def embedded-pg (EmbeddedPostgres/start))
;; =&gt; #'yubrshen.friendwall/embedded-pg
(def datasource (.getPostgresDatabase ^EmbeddedPostgres embedded-pg))
;; =&gt; #'yubrshen.friendwall/datasource
(jdbc/execute! datasource ["SELECT 1"])
;; =&gt; [{:?column? 1}]

seancorfield 2020-12-02T20:26:52.268600Z

That's what I pointed you to in next.jdbc's code. Glad you have it working.

yubrshen 2020-12-02T20:38:51.287700Z

I was following the test code, which uses future that seems not working as expected in my environment. Thanks again!

yubrshen 2020-12-01T06:44:45.081800Z

@seancorfield Unfortunately, with my Ubuntu in WSL1, docker is quite complicated. I may have to try the "Embedded PostgreSQL library" Could you confirm if this is the link to the library, https://github.com/Bigsy/pg-embedded-clj ? If this is the one, the documentation is very sketchy. If it's possible to show the sample code for setup? Thanks!

seancorfield 2020-12-01T07:22:16.082100Z

Switch to WSL2. It's worth the effort of starting over and creating a new dev env. I run all my Clojure stuff on WSL2. I have Docker for Redis, PostgreSQL, and ElasticSearch. I use VS Code with the remote-wsl2 extension (so it lets you have all your code and processes on WSL2 but you still run the editor itself on Windows). Then I use Xlaunch (VcXsrv) so I can run X11 GUI stuff like Reveal from WSL2.

seancorfield 2020-12-01T07:23:41.082300Z

As for Embedded PG, look in the next.jdbc repo -- the deps.edn file has the deps for the embedded pg library (NOT the one you linked) and the test fixtures code has the startup code for it.

seancorfield 2020-12-01T07:24:31.082500Z

https://github.com/seancorfield/next-jdbc/blob/develop/test/next/jdbc/test_fixtures.clj#L28 (see also the :import at the top of that file)

seancorfield 2020-12-01T07:25:59.082800Z

This is the data source setup for it: https://github.com/seancorfield/next-jdbc/blob/develop/test/next/jdbc/test_fixtures.clj#L130-L132

seancorfield 2020-12-01T07:26:46.083100Z

(if you're using a real PG DB, you'd want to create a pooled datasource instead from the db-spec, using HikariCP or c3p0)

Schmoho 2020-12-01T08:06:16.087800Z

I have a really hard time understanding basic JNI interaction, I really hope someone can give me a hint here: I'm trying to load a native library with System/loadLibrary on an Ubuntu 20.04 system, the lib very much appears to be on the library path, but the JVM stubbornly claims it can't find it. I've made sure the JVM has read and execution access.

phronmophobic 2020-12-01T08:10:17.088200Z

try (System/loadLibrary "lapack")

zackteo 2020-12-01T09:27:12.090Z

Am doing advent of code but am just wondering why are the first 2 elements produced vectors? Am using {clojure.math.combinatorics]

(take 5 (combo/permuted-combinations data 2))
=&gt; ([1757 1890] [1890 1757] (1757 1750) (1750 1757) (1757 1440))

mbjarland 2020-12-01T10:49:58.092200Z

A question about (ns … (:gen-class …, how would you create a “singleton pattern” where you have a static method which returns an instance of the gen-classed class? Specifically I have failed to figure out a working way of actually instantiating the gen-classed class within the file where the class is defined

mbjarland 2020-12-03T11:56:36.384500Z

ah!! :factory x - had totally missed that in the docs. Thank you for that. Sanity restored.

mbjarland 2020-12-01T10:58:58.092900Z

ok the above is still of academic interest, but I think I will solve this by moving the relevant functionality to a java class

juniusfree 2020-12-01T11:06:25.093300Z

Anyone else here who's doing #AdventOfCode 2020? https://twitter.com/juniusfree/status/1333727365357207555

juniusfree 2020-12-01T11:08:30.094Z

I complted the Day1 challenge but I want to know if there's a better approach. https://twitter.com/juniusfree/status/1333727767658053632

1
zackteo 2020-12-01T11:09:37.094400Z

There is #adventofcode btw

juniusfree 2020-12-01T11:23:47.095500Z

@zackteo Thanks!

0xclj 2020-12-01T11:29:24.100500Z

What is the best way to differentiate only the latest content of the email from the context-content(the previous emails auto-added that make up the thread)? Example:

"text" : "On 1\r\nOn 2\r\n\r\nOn 3\r\n\r\n\r\nOn 4\r\n\r\n\r\nOn 6\r\n\r\nOn Tue, Dec 1, 2020 at 4:41 PM Author &lt;x.y@z.com&gt;\r\nwrote:\r\n\r\n&gt; L\r\n&gt; M\r\n&gt;\r\n&gt; N\r\n&gt; where O&gt;P&gt;Q!\r\n&gt;\r\n&gt; Onyx is a pokemon\r\n&gt; On\r\n&gt; yx\r\n&gt;\r\n&gt; On Tue, Dec 1, 2020 at 4:39 PM Author &lt;x.y@z.com&gt;\r\n&gt; wrote:\r\n&gt;\r\n&gt;&gt; L\r\n&gt;&gt; M\r\n&gt;&gt;\r\n&gt;&gt; N\r\n&gt;&gt; where O&gt;P&gt;Q!\r\n&gt;&gt;\r\n&gt;&gt; Onyx is a pokemon\r\n"
If I respond to an email, it adds the previous email content as a context that is expanded when you click [...] on gmail. I want to extract only the latest email content. One pattern I see that can work is using:
(-&gt; notification-text
                                      (str/split #"\r\n\r\nOn ")
                                      (as-&gt; raw (raw 0)))
But this will break anytime the email contains a line starting with On . Perhaps parsing it based on the email-content isn’t the best way. What is the recommended way to go about it?

evocatus 2020-12-01T12:57:39.102100Z

could you please explain how namespace name depends on directory structure?

evocatus 2020-12-01T12:57:52.102600Z

I'm absolutely lost

2020-12-01T13:15:51.107400Z

Tools like Leiningen and the Clojure CLI tools have the notion of a class path. I believe both of them by default have the directory named "src" in the class path.

2020-12-01T13:16:13.107900Z

(ns my-app.some.lib.util ,,,)

my-project/
  - src/
    - clj/
      - my_app/
        - some/
          - lib/
            util.clj
It’s pretty straightforward, inside your project directory, you have a source directory src and inside the source directory you have nested directories corresponding to the parts of your namespace. If your project has both clj and cljs files, your src directory will have a clj and cljs subdirectory, but if you’re only working with either clj OR cljs files, then you can put your top level dir my-app directly in the src directory. (EDIT: ignore that last bit if it’s confusing, and just put your .clj files in the clj directory--it works fine and its one less thing to worry about.)

2👍
2020-12-01T13:16:31.108100Z

but they can be configured to have a different directory, or a list of directories, in the class path, e.g. src/main/clojure, although that is uncommon.

2020-12-01T13:17:35.109Z

Some characters that are allowed to be in a namespace, like -, must be turned into _ in the corresponding file name. . separators between parts of a namespace must be another level of directory in the file system.

1👍
2020-12-01T13:17:55.109500Z

The only other wrinkle is that any dashes in your namespace get mapped to underscores in the directory structure, so my-app in the namespace gets mapped to my_app in the directory name.

joetague 2020-12-01T15:01:32.110Z

I had a go too:

(ns joetague.aoc2020
  (:require [<http://clojure.java.io|clojure.java.io> :as io]
            [clojure.math.combinatorics :as combo]))

(def expense-report (with-open [rdr (io/reader (io/resource "expense_report.txt"))]
                      (doall (mapv #(Integer/parseInt %) (line-seq rdr)))))

(defn line-item-group-matching-sum [col groupsize sum]
  (filter #(= sum (reduce + %)) (combo/combinations col groupsize)))

;; First star
(reduce * (first (line-item-group-matching-sum expense-report 2 2020)))
;; Second star
(reduce * (first (line-item-group-matching-sum expense-report 3 2020)))

joetague 2020-12-01T15:02:54.110300Z

I'm not quite sure about my filter because it returns a list (list ()) so thats why I have to do first before my reduce - will see if I can get rid of that

2020-12-01T15:57:55.110700Z

@lkottmann have a look at tick - it uses Java-time and you can use it in both clj and cljs https://github.com/juxt/tick

Louis Kottmann 2020-12-01T16:34:28.111200Z

looks interesting, don't know why I went past it, thanks

2020-12-01T16:51:55.111400Z

usually all class statics would be put into an atom inside a def in the namespace, that can include an instance of the class itself - every def is executed when the namespace itself is loaded

Louis Kottmann 2020-12-01T16:53:22.111600Z

it doesn't seem to support humanizing a time "ago" (i.e: "5 days ago")

Louis Kottmann 2020-12-01T16:53:31.111800Z

but it's definitely more complete than java-time

2020-12-01T17:20:25.112Z

Oh @lkottmann I'm sorry I completely missed the point of your initial message. Try this https://duckling.wit.ai/

Louis Kottmann 2020-12-01T17:37:42.112300Z

actually I replaced my code with and it's much better already

Louis Kottmann 2020-12-01T17:38:35.112500Z

that duckling lib looks awesome

Louis Kottmann 2020-12-01T17:38:40.112700Z

I never saw it before!

Louis Kottmann 2020-12-01T17:47:44.113200Z

I'm trying to see if it can handle the reverse (a duration to a humanized representation)

Louis Kottmann 2020-12-01T17:59:36.113400Z

mmh it doesn't seem to do that, and it has been deprecated in favor of an haskell version from facebook 😕

2020-12-01T18:28:18.113900Z

@lkottmann sorry I can't help much. I don't think it would be too hard to implement one, though. And at the end you can publish that as a lib 🙂

Louis Kottmann 2020-12-01T18:41:47.114300Z

well, I did but I didn't make into a library

1👏
Louis Kottmann 2020-12-01T18:42:05.114500Z

Louis Kottmann 2020-12-01T18:42:16.114900Z

(uses tick)

1👏
Schmoho 2020-12-01T19:04:45.115600Z

can I somehow inspect the jvm-opts of my running jvm in the repl?

alexmiller 2020-12-01T19:12:31.116300Z

(System/getProperties) can show you all of the JVM system properties (but not just the ones that were set externally)

1👍
Schmoho 2020-12-01T19:17:22.118400Z

seems like my next question then is something like is there a way to set :jvm-opts in deps.edn regardless of an alias?

{:path     ["src"],
 :deps
 {org.clojure/clojure #:mvn{:version "1.10.1"}}
 :jvm-opts ["--some-option=some-value"]}
I've been trying this, which doesn't work and been reading this https://clojure.org/reference/deps_and_cli#_prepare_jvm_environment but this seems to only refer to using jvm-opts for an alias

alexmiller 2020-12-01T19:20:19.118600Z

not currently

alexmiller 2020-12-01T19:21:17.119400Z

you can only include them as part of an alias right now (or on the command line with -J)

alexmiller 2020-12-01T19:21:50.120Z

as an aside, for a jvm opt, you'd want that to be ["-Dsome-option=some-value"]

1👍
Schmoho 2020-12-01T19:22:49.120900Z

thanks for the info. sucks for me, seems like I'll have to figure out how to configure cider to start a repl in a project using command line tools with an alias then or something

alexmiller 2020-12-01T19:23:56.121600Z

you are certainly not the first to walk this path, not sure if this channel is the best place for the question - maybe #cider or #clojure would be better

Schmoho 2020-12-01T19:25:11.122700Z

seems like it thanks a lot 🙂

Schmoho 2020-12-01T19:28:41.122800Z

in case anyone cares: https://github.com/clojure-emacs/cider/issues/2396

dpsutton 2020-12-01T19:31:00.123600Z

That issue is closed with two solutions listed. What problems are you having?

Schmoho 2020-12-01T19:31:54.123800Z

none so far, just thought I'd document this for some reason - not that it's likely someone would be stumbling across this here instead of by googling

dpsutton 2020-12-01T19:38:57.124Z

yeah and this will disappear in five days or so

dpsutton 2020-12-01T19:39:32.124200Z

@d.eltzner why do you need an alias though? CIDER does a pretty good job of being able to start up automatically

Schmoho 2020-12-01T19:41:43.124400Z

to specify :jvm-opts (see above, apparently that is only possible via aliases)

dpsutton 2020-12-01T19:42:24.125300Z

ah i see

Alex 2020-12-01T19:43:06.126900Z

Do folks have any general tips for handling large csvs in clojure? Is it worthwhile to force evaluation of the rows and store in a binding of some kind to access later? Or is it better/more ergonomic to simply read/access the file each time and you can lazily evaluate?

2020-12-01T19:43:59.127800Z

well, i'm not sure how i got here, but i'm starting to feel squeamish about returning functions. because they're not data. i can't "see" what they are - eg #function[workflow.server/eval51723/fn--51726]

2020-12-01T19:44:25.128100Z

is that the right one? lol idk

2020-12-01T19:45:05.128800Z

I always thought it would be cool if functions printed their source code rather than that sort of memory reference

2020-12-01T19:45:16.129200Z

i guess i could return a quoted expression

2020-12-01T19:45:18.129500Z

They’re still data. It’s just not rendered in an easily readable way

2020-12-01T19:45:42.129900Z

Down that path lies madness. Then you have to keep track of quoting and unquoting and evaluating and skipping evaluation

1🙏
Schmoho 2020-12-01T19:46:09.130500Z

sorry to keep bothering, but I now am using an alias

{:path     ["src"],
 :deps
 {org.clojure/clojure #:mvn{:version "1.10.1"}}
 :aliases
 {:bonkers
  {:jvm-opts []}}}
and I'm trying to have the jvm use this option "-Dadd-opens=java.base/jdk.internal.ref=ALL-UNNAMED" but this apparently has no effect - nothing visible in the Properties and the IllegalAccess that causes this shenanigans is still illegal - runtime version 14 here, if that's relevant

2020-12-01T19:46:28.130600Z

Also, macros: just functions that run at read-time rather than run-time

seancorfield 2020-12-01T19:46:35.130800Z

You can put a name between fn and the argument list, which will make that output a little clearer.

2020-12-01T19:46:53.131Z

ooh

seancorfield 2020-12-01T19:47:09.131200Z

user=&gt; (defn foo [n] (fn [x] (* n x)))
#'user/foo
user=&gt; (foo 2)
#object[user$foo$fn__20417 0xb666366 "user$foo$fn__20417@b666366"]
user=&gt; (defn foo [n] (fn times-n [x] (* n x)))
#'user/foo
user=&gt; (foo 2)
#object[user$foo$times_n__20422 0x3113595e "user$foo$times_n__20422@3113595e"]
user=&gt; 

2020-12-01T19:47:34.131600Z

yeah, that's better

2020-12-01T19:48:24.132200Z

It depends a lot on what you’re trying to accomplish in a broader sense. Is it a relatively small CSV that you’ll have to use many times? May as well read it all into memory. Is it a huge CSV that’s too big to read into memory? Maybe process lazily.

seancorfield 2020-12-01T19:48:55.133Z

@d.eltzner How are you invoking the CLI for that? (and presumably you mean :jvm-opts ["-Dadd-opens=java.base/jdk.internal.ref=ALL-UNNAMED"])

alexmiller 2020-12-01T19:49:39.133900Z

that's not the right syntax for add-opens

alexmiller 2020-12-01T19:49:55.134300Z

--add-opens is a jvm flag (not a jvm system property)

alexmiller 2020-12-01T19:50:20.135100Z

so you'd want something like :jvm-opts ["--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED"]

alexmiller 2020-12-01T19:51:01.135900Z

sorry if I misled you above, I thought you were actually talking about Java system properties

alexmiller 2020-12-01T19:51:32.136300Z

you won't see that in Java system properties - it's used by the jvm itself as it checks module visibility

Schmoho 2020-12-01T19:52:49.137500Z

/usr/local/bin/clojure -Sdeps '{:deps {nrepl {:mvn/version "0.8.3"} refactor-nrepl {:mvn/version "2.5.0"} cider/cider-nrepl {:mvn/version "0.25.5"}}}' -m nrepl.cmdline --middleware '["refactor-nrepl.middleware/wrap-refactor","cider.nrepl/cider-middleware"]' -A:bonkers

Schmoho 2020-12-01T19:53:52.138300Z

I see - still helped a lot in that it helped me along with the jvm-opts so can I see these at runtime? because apparently this still didn't do what I hoped it would

seancorfield 2020-12-01T19:55:01.138700Z

@d.eltzner -A:bonkers needs to be before the "main opts", i.e., before -m nrepl.cmdline etc.

alexmiller 2020-12-01T19:55:08.139Z

there may be some way via reflection or the module api to introspect those flags, but I don't know

2020-12-01T19:55:10.139100Z

If you like the idea of directly manipulating functions-as-data, quoted expressions and trees of symbols, that’s macros.

seancorfield 2020-12-01T19:55:19.139300Z

Otherwise it will be read as a command-line argument to nrepl.cmdline itself.

Schmoho 2020-12-01T19:55:45.139700Z

😄 yup, I just figured that out. thanks!

seancorfield 2020-12-01T19:56:06.140500Z

See the thread above -- @d.eltzner had the -A:bonkers flag after the main opts for nREPL.

seancorfield 2020-12-01T19:56:36.141Z

(I'm assuming a relatively recent CLI version BTW @d.eltzner -- what does clojure -Sdescribe show?)

Schmoho 2020-12-01T19:58:52.142600Z

Some rather interesting information - what would :force and :repro do? and how does the /usr/local deps.edn end up in the config-files? via the :install-dir?

{:version "1.10.1.716"
 :config-files ["/usr/local/lib/clojure/deps.edn" "/home/user/.clojure/deps.edn" "deps.edn" ]
 :config-user "/home/user/.clojure/deps.edn"
 :config-project "deps.edn"
 :install-dir "/usr/local/lib/clojure"
 :config-dir "/home/user/.clojure"
 :cache-dir ".cpcache"
 :force false
 :repro false
 :main-aliases ""
 :repl-aliases ""}

alexmiller 2020-12-01T20:00:59.143700Z

-Sforce forces classpath cache recomputation

2020-12-01T20:01:18.144300Z

thank you for pointing that out

alexmiller 2020-12-01T20:01:19.144500Z

-Srepro omits the ~/.clojure/deps.edn from the deps.edns that are used

alexmiller 2020-12-01T20:01:37.144900Z

these are both doc'ed in clj -h and man clj btw

alexmiller 2020-12-01T20:02:04.145300Z

the :config-files thing is actually a bit of a lie now

2020-12-01T20:02:13.145500Z

i'm pretty new to macros, and the macro club rule #1 tends to dampen my enthusiasm

2020-12-01T20:02:22.145900Z

so it wouldn't have occurred to me.

alexmiller 2020-12-01T20:03:41.147600Z

the first location there is created during installation and is now known as the "root" deps.edn in the docs. in reality it's actually read as a resource from the tools.deps library by clj. the file in that location should be the same file, but it is not actually read from the filesystem anymore (but that is there as some older tools, notably datomic ion dev tools) are still loading it from there

alexmiller 2020-12-01T20:04:42.148Z

if you have other tools-deps / clj questions, #tools-deps is a better channel for that

2020-12-01T20:04:42.148100Z

yeah, it’s very cool in itself, but practical applications are somewhat limited. Most things can be done more cleanly using mostly functions, with perhaps a small macro for syntactic sugar.

Schmoho 2020-12-01T20:06:17.149600Z

okay I'll keep it in mind! I'm just trying to pick it up as I go at the moment. by the way what I was up to worked out fine eventually, thank you both very much!

1🎉
2020-12-01T20:07:49.149900Z

The theoretical scope is astounding, though, isn’t it: your macro can take some arbitrary symbolic code as input and rewrite it in any arbitrary way it likes.

2020-12-01T20:10:00.150100Z

The main difference is that functions can’t control whether and how their arguments are evaluated. They don’t get access to the raw symbols, just to the results of evaluating those symbols. Macros get full control at the raw symbol level. This is sadly much less broadly useful than it may seem, though occasionally there are indeed real world use cases where nothing else will do.

2020-12-01T20:13:54.150400Z

Toy example for illustration: you can’t write if-then and similar control constructs directly as a function, only as a macro. As a function, (new-if-fn foo (bar) (baz)) will invoke both (bar) and (baz) before the function even starts. You’d have to do (new-if-fn foo (fn [] (bar)) (fn [] (baz))) to delay evaluation. The macro version (new-if-macro foo (bar) (baz)) just gets the symbols, though, so it can choose to not evaluate the losing branch. The same net effect is achievable both ways, but the syntactic sugar is much nicer with the macro.

yubrshen 2020-12-01T20:18:01.150600Z

@seancorfield Thanks for the generous help! I'll try them.

mbjarland 2020-12-01T20:23:34.150800Z

How would I instantiate the class from the gen-classed namespace for the class? Is that supposed to "just work"?

mbjarland 2020-12-01T20:24:12.151Z

And thank you for the reply and pointer

2020-12-01T20:44:16.151200Z

the def starts out holding nil, then gets a class instance when the static method is first called, reused afterward - delay / promise can be useful here as they enforce the "only set once" property

2020-12-01T20:44:49.151400Z

the class instance would be made via the constructor of course

walterl 2020-12-01T21:37:16.151800Z

For Integrant systems there's https://github.com/troy-west/cronut

juniusfree 2020-12-01T21:38:12.152500Z

@joetague You can check out #adventofcode. I got some great feedback there https://clojurians.slack.com/archives/C0GLTDB2T/p1606822120031800

1
dpsutton 2020-12-01T21:38:57.152800Z

there's probably no need to keep sending these to the channel. if you have specific questions or are particularly proud you should share them but this is starting to become just a blog feed

st3fan 2020-12-01T21:46:26.153400Z

Does anyone know a library that can (ascii) tabulate/format data so that i can print pretty reports in the repl or cli? Something like https://pypi.org/project/tabulate/

2020-12-01T21:51:45.154100Z

there's clojure.pprint/print-table for sequences of maps with the same key

1
st3fan 2020-12-01T21:52:10.154300Z

oh! cool 🙂

2020-12-01T21:52:58.154700Z

some limitations, but it works for quick and dirty

user=&gt; (print-table [{:a 0 :b 1} {:a 33 :b 12} {:a "OK" :b "bye" :c :hmm}])

| :a |  :b |
|----+-----|
|  0 |   1 |
| 33 |  12 |
| OK | bye |
nil

2020-12-01T21:53:13.155100Z

notice it doesn't attempt to show that :c key

2020-12-01T21:53:56.155700Z

and of course, for other cases, you can probably use group-by / mapcat etc. to make something print-table can consume

2020-12-01T21:55:21.155800Z

interesting

2020-12-01T21:56:07.156Z

thank you for sharing this, it's quite interesting.

1👍
2020-12-01T21:56:28.156200Z

someday i'll have the inspiration to really dig into macros.

st3fan 2020-12-01T21:57:25.156800Z

that is great - exactly what i need

nate 2020-12-01T21:58:03.157500Z

print table is amazing, I use it all the time. you can also pass in keys to use to fix the "missing :c" problem:

(print-table [:a :b :c] [{:a 0 :b 1} {:a 33 :b 12} {:a "OK" :b "bye" :c :hmm}])
result:
| :a |  :b |   :c |
|----+-----+------|
|  0 |   1 |      |
| 33 |  12 |      |
| OK | bye | :hmm |

1
2020-12-01T21:58:44.157700Z

> Down that path (syntax quoting) lies madness. Then you have to keep track of quoting and unquoting and evaluating and skipping evaluation it is tricky - i have to deal with this when programmatically building datomic expressions. do you have any thoughts on why datomic would make such extensive use of syntax quoting? would macros fill the same role?

2020-12-01T22:00:44.158700Z

@st3fan another more robust option is using clojure.data.csv to write a csv output, then use a spreadsheet to view the csv

2020-12-01T22:01:12.159200Z

oh, you specifically wanted CLI - so yeah I think you want print-table

2020-12-01T22:04:35.159600Z

Wow, I had no idea print-table was a thing. I’m going to use this all the time!

2020-12-01T22:06:10.159700Z

I’ve never used Datomic beyond a quick tryout, so I’m afraid I don’t know much about why it does anything

seancorfield 2020-12-01T22:11:17.160300Z

I love print-table I use it all the time when I'm REPL'd into production and querying the database 🙂

2020-12-01T22:13:57.160800Z

Are there any other somewhat obscure but highly useful functions like that lurking about?

dpsutton 2020-12-01T22:14:55.161500Z

clojure.set/index is amazing. i see hiredman talk about this one a lot and i think its incredibly useful and underused

seancorfield 2020-12-01T22:20:19.161900Z

Maybe follow https://twitter.com/rcfotd on Twitter? Random Clojure Function Of The Day

1🦜
nate 2020-12-01T22:23:15.162300Z

there are several

nate 2020-12-01T22:23:27.162500Z

frequencies blew my mind when I found out about it

1👍
nate 2020-12-01T22:23:40.162700Z

juxt is a really fun one for making functions with functions

1❤️
nate 2020-12-01T22:25:47.163Z

if you'd like to hear more about juxt, check out https://clojuredesign.club/episode/076-multiple-views-on-juxt/ (an episode on my podcast)

borkdude 2020-12-01T22:26:14.163400Z

Every time I open a new shell: Source: https://github.com/borkdude/babashka/blob/master/examples/random_doc.clj

23🤘
juniusfree 2020-12-01T22:28:18.164Z

@dpsutton Sorry about that.

dpsutton 2020-12-01T22:28:41.164200Z

oh no worries. love the enthusiasm. but its just a string of tweets is all

1👍
borkdude 2020-12-01T22:30:00.166200Z

Another fun way to discover new core fns: https://borkdude.github.io/re-find.web/

2❤️
2020-12-01T22:31:59.166700Z

user=&gt; (-&gt;&gt; (all-ns) (mapcat (comp vals ns-publics)) rand-nth meta ((juxt :name :doc)))
[load-file "Sequentially read and evaluate the set of forms contained in the file."]

2020-12-01T22:32:39.167200Z

realistically you probably want the namespace it came from as well...

borkdude 2020-12-01T22:33:28.167500Z

$ bb -e "(-&gt;&gt; (all-ns) (mapcat (comp vals ns-publics)) rand-nth meta ((juxt (comp ns-name :ns) :name :doc)))"
[clojure.set union "Return a set that is the union of the input sets"]

3💯
walterl 2020-12-01T22:51:39.168300Z

"Fortune, Clojure edition"