Fork me on GitHub
#beginners
<
2021-01-14
>
Joe00:01:40

Just watched Sean’s REPL talk using VS Code and Clover. If I’m pretty happy with my Calva set up is there any argument in favour of switching? Or is more a personal preference / devil you know sort of thing?

seancorfield00:01:17

@allaboutthatmace1789 Mostly personal preference -- as I said in the talk, I want a setup that works with just a socket REPL and no additional dependencies in my project, so I have the exact same experience with any Clojure process running (since I can start a socket REPL via a JVM option -- not code).

seancorfield00:01:45

Everything I showed can be done with (almost) any other editor/integration setup.

Joe00:01:24

That makes sense, thanks!

roelof09:01:59

I have this as response from a api

({:levels
  [{:name "z1",
    :width 2810,
    :height 2177,
    :tiles

Frankline Apiyo13:01:07

is there a more idiomatic way to write (first (filter filter-function sequence))

Idan Melamed13:01:39

Maybe the thread last macro? ->> sequence (filter filter-function) first

👍 1
Frankline Apiyo13:01:15

this seems all right... I was just wondering if there's a built-in function that I don't know about that. seems there isn't

Max Deineko13:01:39

Ad built-in function: such a proposal was rejected at some point -- see https://clojure.atlassian.net/browse/CLJ-2056?focusedCommentId=12986

nice 2
👍 2
delaguardo13:01:18

(some #(when (filter-function %) %) sequence)
but this will fail if it suppose to return false

👍 1
andy.fingerhut14:01:51

The small library medley contains find-first, and several other useful small functions: https://github.com/weavejester/medley

👍 1
Marcus14:01:22

What is the difference between >! and put!?

alexmiller14:01:02

the first is parking (used in go blocks only) - ie park the go block until the operation can succeed. latter is async, can be used from either in or out of go block

alexmiller14:01:41

in most cases, if you are in a go block, you should prefer the parking operation (the async ops are lower level)

Marcus15:01:26

@alexmiller ah of course. For some reason I thought of parking and async as the same thing. Thanks!

Mitch15:01:51

This example fails to generate:

(require '[clojure.spec.alpha :as s])

(s/def :person/id string?)
(s/def :robot/id number?)

(s/def ::person
  (s/keys :req-un [:person/id]))

(s/def ::robot
  (s/merge ::person
           (s/keys :req-un [:robot/id])))

(gen/sample (s/gen ::robot))
Is this behavior expected? I thought that one of the benefits of merging map specs would be that you could overwrite defaults specs for certain keys

alexmiller16:01:29

no, that's not expected to be supported

alexmiller16:01:41

you've written a spec that has incompatible options for the same key

Mitch16:01:18

Okay, thanks! So if I understand correctly, the spec merge is semantically different than core merge. Core merge overwrites keys left to right, while spec merge tries to take the union of the map specs being merged. Sometimes, a union of specs can create an impossible to satisfy predicate

Mitch16:01:03

Is the union of two specs achieved using s/and?

alexmiller16:01:41

If you want something that satisfies both, yes

alexmiller16:01:55

But note that s/and flows conformed values

alexmiller16:01:30

So using it on maps may not be what you want (it depends)

alexmiller16:01:39

Spec 2 will have an s/and variant that does not flow conformed values (currently called s/and- but maybe to be called s/union)

alexmiller16:01:26

Just FYI, there is #clojure-spec for more detailed spec questions

Mitch16:01:54

Thanks Alex! I am going to make a note to document this on clojureDocs when I have a moment. Super helpful

andy.fingerhut17:01:11

Oh, http://ClojureDocs.org does have pages for each function in Clojure spec now (and probably has for a while now). I just didn't notice them.

Eamonn Sullivan17:01:09

I have a really basic question about spec. I have a library where I define some specs (s/def). They are used in the library for various things and they work fine. However, I would also like to use some of the specs from outside the library (as options or config validation, for example), but I can't figure out how to use the spec outside of the original library. Contrived example (excuse the syntax errors):

(ns my.lib (:require [clojure.spec.alpha :as s]))
(s/def ::is-thingy string?)
(defn publicfn [thing] {:pre [(s/valid? ::is-thingy thing)]} ,,,) ;; this works fine
In client:
(ns my.client (:require [my.lib :as lib] [clojure.spec.alpha :as s])

(defn my-code [options] (when (s/valid? ::lib/is-thingy (:thing options)) ,,,)) ;; this doesn't. "Unable to resolve spec: :my.lib/is-thingy.
How do I refer to the spec definitions created in the library, outside of that library?

alexmiller17:01:24

:my.lib/is-thingy is the fully-qualified name of your spec

alexmiller17:01:42

::lib/is-thingy should work as a way of creating an alias - your code works for me

1
Eamonn Sullivan09:01:49

facepalm I didn't run clojure -X:jar before installing the library...

Eamonn Sullivan18:01:20

Thanks. Must be some other issue I'm having then. Maybe it's not resolving the correct library.

GGfpc19:01:10

Is multiple maps in sequence in a threaded macro a smell?

(defn get-game-data
  [user-id]
  (let [url (str BASE_URL user-id)
        request-headers {:headers      {:accept "application/x-ndjson"}
                         :query-params {:max 20}}]
    (as-> (client/get url request-headers) games
          (:body games)
          (str/split games #"\n")
          (map json/read-str games)
          (map walk/keywordize-keys games)
          (map #(update-in % [:moves] str/split #" ") games))))
Stuff like the above. I could make it a single map, but then the code wouldn't be as clean

hiredman19:01:46

seems fine to me. I guess I would usually reach for -> or ->> before as->. some people really don't like as-> used outside of another arrow form (I don't agree with this)

seancorfield19:01:47

I'm one of those "some people". I think using as-> there makes it much harder to read...

alexmiller19:01:22

if you're talking about 10s or maybe even 100s of things, then I wouldn't worry about it, clarity wins. if trying improve perf, better to move to transducers and then multiple maps is also not a big deal.

seancorfield19:01:28

(-> (client/get url request-headers)
    :body 
    (str/split #"\n")
    (->> (map json/read-str)
         (map walk/keywordize-keys)
         (map #(update-in % [:moves] str/split #" ")))
That is much clearer to my eyes.

seancorfield19:01:28

What this highlights is that you're changing the data type in the middle of the pipeline (from a "thing" to a sequence).

benny19:01:11

@seancorfield Thank you for your Clojure London talk on REPL-Driven Programming. I learned quite a bit! (ref for others: https://www.youtube.com/watch?v=gIoadGfm5T8)

seancorfield19:01:31

Glad it was useful!

Stuart19:01:26

Yes, it was good 🙂 @vlaaad needs to take down his xmas tree though...👀🌲

vlaaad19:01:52

It's so snowy here in Stockholm, finally some Christmas weather!

roelof19:01:49

here in the netherlands no snow the whole winter 🙂

vlaaad20:01:02

It was like that here last year

roelof20:01:42

but maybe net Sunday we have a few hours snow

Santiago20:01:15

I need to write something that 1) subscribes to a rabbitmq queue 2) gets a message and writes it to a TCP socket 3) TCP socket must be always open otherwise client (a Spark cluster) will close. AFAIK I need two loops concurrently: 1 to subscribe to rabbitmq and the other to serve the TCP socket. I have never done such a thing and would like to try doing in clojure. What literature do you recommend for such a problem?

hiredman20:01:27

Depending on a tcp socket to always be open is usually a bad idea

Santiago20:01:04

I think it won’t work otherwise, but in any case could you expand on why? I haven’t had experience with these topics at such a low level

hiredman20:01:25

Network hiccups are surprisingly common

Santiago20:01:34

maybe “always open” is not the correct nomenclature

Santiago20:01:04

https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html#quick-example they use netcat in the tutorial. When you launch nc ... is it “always on”?

hiredman20:01:39

My guess is this is written with spark as the client, and your code as the server to deal with exactly this kind of thing

hiredman20:01:32

Or not, I dunno

Santiago20:01:38

right, so I need to a server running plus the rabbitmq subscriber which also runs in a loop 🤷

hiredman20:01:29

My comment about networking hiccups is mostly on the scale of weeks to months, if your whole whatever has a shorter runtime than that you might not care

Michael Stokley22:01:09

is there an easy way to remove all existing taps

Michael Stokley22:01:51

i find that i've polluted my set of taps with various functions over time and can't seem to remove-tap all of them

Michael Stokley22:01:10

i should just restart the repl.

noisesmith22:01:18

yeah, a big gotcha is adding a function itself as a tap, rather than the var holding the function

Michael Stokley22:01:04

@U051SS2EU do you mean i should (add-tap (var f)) instead of (add-tap f)?

noisesmith23:01:50

if you want to be able to reload f, yeah (or the equivalent of (var f), #'f)

noisesmith23:01:15

f itself is no longer equal after you run defn again, the var remains equal to the var

Michael Stokley23:01:19

thanks, this has proven really useful just now in refining what i want f to be

noisesmith22:01:32

which means when you redef the function, you no longer have the thing to call remove-tap on

dpsutton22:01:37

(reset! @#'clojure.core/tapset #{}) should work

dpsutton22:01:41

its just a private atom with a set. you can see from the source of remove-tap that there's no cleanup dance to do. just toss it

Stuart23:01:08

I'm trying to use next/jdcb for a mssqlserver. I can't see how to specify "TrustedConnection=True;" rather than providing a username and password?

seancorfield23:01:29

@qmstuart You can pass extra properties via the db-spec hash map (that you build a datasource from): {:dbtype "mssql" :dbname "your-db" :TrustedConnection true :host "..."} something like that I expect.

seancorfield23:01:47

Then call jdbc/get-datasource on that (and then use that return ds everywhere). If you're using a connection pool, you'll need to consult the docs for the pooling library in use and figure out how it passes properties to the driver manager.

seancorfield23:01:15

#sql is a good place for next.jdbc questions as well as general DB-related stuff.

Stuart23:01:04

thanks! I dunno how I didn't see :TrustedConnection. I looked at the docs, I swear 😄