Fork me on GitHub
#beginners
<
2020-12-26
>
Grigory Shepelev05:12:54

It might be a stupid question. And it might me formulated incorrectly. But how do I run a channel in endless loop in my main function? I can do that in repl with (async/go-loop ...) but not with lein run

Grigory Shepelev06:12:09

Ok. I just figured out. It was not a problem of my channels misunderstaning, but wrong config.

Grigory Shepelev06:12:37

Now another question. A file being read in my code. How do I say it not to look for the same file to read after compilation, but rather have it "remembered"?

Timur Latypoff08:12:04

I think you could read the file inside a macro, and substitute the reading with actual values you read at compile time. Another approach would be to put the file you’re reading as a resource which is compiles as a part of the final JAR — so it’s always with you the way you compiled it.

Grigory Shepelev08:12:34

If I can somwhow pack it inside of jar?

Timur Latypoff08:12:13

Yes. With leiningen you do it by putting in resource/ folder in your project, and open the file with this function https://clojuredocs.org/clojure.java.io/resource

Grigory Shepelev08:12:15

yep. The provlem is I am doing exactly same thing by now with

(defmacro compile-time-read-file
  [resource-path]
  (slurp (io/resource resource-path)))

Grigory Shepelev08:12:52

ok. I got it.

👍 1
Grigory Shepelev07:12:25

Ok. I just get this. The problem is still with the first question.

jacklombard11:12:19

I'm using next.jdbc to connect to postgres which is running as a docker container. I am able to connect to it using intellij and psql, but not via the repl. I have the following in my project.clj

[org.postgresql/postgresql "42.2.5"]
[seancorfield/next.jdbc "1.1.613"]
This is the code I executed to test
(comment
  (require '[next.jdbc :as jdbc])
  (def db {:dbtype    "postgresql"
           :classname "org.postgresql.Driver"
           :dbname    "foo-dev"
           :username  "foo"
           :password  "foo"
           :host      "localhost"
           :port      7432})
  (def ds (jdbc/get-datasource db))
  (jdbc/execute! ds ["select * from some-table"]))
I am able to connect to it via psql (entering the password on prompt)
psql -h localhost -p 7432 --username foo -d foo-dev
The error I get when I run (jdbc/execute! ds ["select * from some_table"]) is this
Execution error (ConnectException) at java.net.PlainSocketImpl/socketConnect (PlainSocketImpl.java:-2).
Connection refused (Connection refused)

jacklombard11:12:01

This is the docker-compose.yml part for the postgres container

db:
    image: postgis/postgis:13-master
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - 7432:5432
    environment:
      POSTGRES_USER: foo
      POSTGRES_PASSWORD: foo
      POSTGRES_DB: foo-dev

dharrigan11:12:12

Change username to user

dharrigan11:12:30

user=> (def db {:dbtype "postgres" :classname "org.postgresql.Driver" :dbname "foo-dev" :user "foo" :password "foo" :host "localhost" :port 7432})
#'user/db
user=> (jdbc/execute! (jdbc/get-datasource db) ["select now()"])
[{:now #inst "2020-12-26T11:25:58"}]

jacklombard12:12:44

still the same error 😕

dharrigan12:12:46

Interesting. Works for me, and I basically copy and pasted your code to my terminal

jacklombard12:12:41

Tried it in the older clojure.jdbc and it works, guessing it's a problem with next.jdbc and my system

(def idb {:classname                                  "org.postgresql.Driver"
          :subprotocol                         "postgresql"
          :subname                             "//localhost:7432/foo-dev"
          :user                                "foo"
          :password                            "foo"})

jacklombard13:12:31

Missed something important, had to use host.docker.internal instead of localhost since I was testing the port forwarded db connection. Works now, sorry my bad

dharrigan14:12:21

Glad you got it sorted! 🙂

dharrigan11:12:51

❯ docker ps                CONTAINER ID   IMAGE                       COMMAND                  CREATED         STATUS         PORTS                    NAMES
04d4199d1cd8   postgis/postgis:13-master   "docker-entrypoint.s…"   4 minutes ago   Up 4 minutes   0.0.0.0:7432->5432/tcp   david_db_1

Joe11:12:41

Is clojure.lang.PersistentQueue still the appropriate data structure to use if you want a FIFO queue? i.e. conj to the back, pop off the front?

rakyi12:12:06

AFAIK that is its primary purpose

👍 1
noisesmith17:12:02

NB - don't ever use first / rest / etc. seq operations on a queue, it can quietly turn your fifo into a lifo

noisesmith17:12:31

only use into, peek, conj, and pop

noisesmith17:12:13

(and other tools built on those)

Andrew Byala16:12:32

Hey, everyone. I'm coming in from the Java/Kotlin world, and I'd like to try building a REST API using Clojure. In Java, you download Spring Boot and get to work, but I'm reading that in the Clojure world you tend to put together the pieces that you want, with everyone using Ring. Is there a de facto standard for building APIs nowadays? I I've seen samples with Reitit and Compojure; where is the industry heading?

noisesmith16:12:02

compojure and reitit are routers, ring provides an http server (which can be combined with the router of your choice). none of these are REST specific

noisesmith16:12:37

@abyala for "batteries included" opinionated setups, the biggest player is luminus, they have a project template generator which accepts args reflecting the setup you are looking for (eg. cljs webapp support, database backend...) https://luminusweb.com/ - the excellent book "web development with clojure" uses a luminus template, walks through building a full app, and is worth the price https://pragprog.com/titles/dswdcloj3/web-development-with-clojure-third-edition/

noisesmith17:12:57

but depending on what kind of REST API you are trying to make, there are tools that simplify that as well (and those can be combined with the big pile of code that luminus hands you)

Andrew Byala17:12:20

Awesome, I'll check that out. Thanks!

noisesmith18:12:31

@popeyepwr for many functions that take variable argument counts, adding an arg to the function is equivalent to another call - in that case apply and reduce do the same thing

noisesmith18:12:15

so "can" - for many vararg functions that treat their arguments homogenously, you can use either

noisesmith18:12:00

in practice reduce has some optimizations that the function might not, so it's often preferable

noisesmith18:12:10

concretely: (+ 1 2 3) will always be the same as (+ (+ 1 2) 3), so apply and reduce will do the same thing with + and [1 2 3]

noisesmith18:12:37

also conj

(ins)user=> (apply conj [] [1 2 3])
[1 2 3]
(ins)user=> (reduce conj [] [1 2 3])
[1 2 3]

noisesmith18:12:15

but with apply, it can be smarter about building the result, with reduce it needs to do more allocations (it builds a bunch of immutable vectors it only needs once)

noisesmith18:12:37

for correctness they both work, it is case by case which is more efficient

👍 1