Fork me on GitHub
#clojure
<
2020-10-23
>
svt07:10:34

Anybody has idea on how we can run PACT Test as provider for amqp tests in Clojure, I’m using https://github.com/DiUS/pact-jvm

zilti11:10:03

No idea, but have you also looked at the Clojure solutions available? If you need to generate fake requests, there is e.g. ring-mock

mavbozo10:10:14

I use leiningen and I use pomegranate to add libraries needed when I experiment in the repl to avoid restarting the repl. Any other alternatives? quick google search shows alembic and add-lib

dominicm10:10:00

I'm pretty sure that's it for now.

emil0r11:10:27

In Rich Hickey’s talk Simple Made Easy he talks about set functions as a source of simplicity opposed to imperative loops/folds as a source of complexity

emil0r11:10:44

Does anyone have an idea of what he means exactly when he talks about set functions

Zor11:10:34

I believe that's a set, used as a function, like so: (#{1 2 3} 1) => 1 (#{1 2 3} 42) => nil

rutledgepaulv12:10:09

I believe he's referring to mathematical sets and implementations of them in clojure. Functions on sets like intersection/ union / conj / disj are simple because they are idempotent. Sets are simple because ultimately they're only about membership. I do not think he meant Seqs and all the functions that surround Seqs. Those properties of sets allow for declarative expression and manipulation of membership, whereas other data structures may require careful policing and ordering to achieve the same which leads to more complex and imperative code.

mavbozo12:10:22

it's about what collection functions that complect what's to be done and how that's done. he pointed loop and fold as examples. although both operates on whole collection (what), both operate from first element, one-by-one, to last element (how). like when using map or filter, we don't care the how, the order of things or the order of how things work--whether the work done from beginning-to-end, end-to-beginning, or even worked in parallel. I guess Rich named those 'set functions' because sets don't have ordering in its members.

emil0r12:10:29

Right… I have a hard time thinking it relates to clojure.set as you can do so much more in a imperative loop/fold than what clojure.set offers

emil0r12:10:14

map, filter, etc are equivalent power to imperative loop/fold, but are simpler

emil0r11:10:49

I’m assuming it’s not clojure.set

emil0r11:10:20

Hmmm… appears to be

emil0r11:10:16

Best I can make out of it is functions that take sets (in the mathematical sense, which for clojure could be lists, vectors, maps, sets, etc) and apply a function on each element in the set and then returns the output. So map, reduce, filter, etc would all apply

Zor11:10:56

The functions you're quoting here operate on the Seq abstraction, which is a very central Clojure thing. Maybe every seq is a set in the mathematical sense, but I doubt that was the point there.

Valentín13:10:24

Is there a variant of concat that allows you to do that (concat '(3 4) (5) 1 6 [3 [6] ]) returning '(3 4 5 1 6 3 [6])

Valentín13:10:16

Without doing that (mapcat #(if (coll? %) % (list %) ) '(1 [3 5] (3)))

andy.fingerhut13:10:48

In the Clojure core library, I think that is the most concise understandable way

Valentín14:10:33

Understood, thanks.

Ben Sless18:10:52

You can also do the opposite and write a maybe-cat transducer. Just copy cat's definition and add a coll? check which would branch to reduce or rf, I'll find an example later and send it if you're interested

Valentín20:10:56

Yes I'm interested

Ben Sless20:10:34

Something like

(defn maybe-cat
  "Like [[clojure.core/cat]] but falls through on non-sequential elements."
  [rf]
  (let [rrf (preserving-reduced rf)]
    (fn
      ([] (rf))
      ([result] (rf result))
      ([result input]
       (if (sequential? input)
         (reduce rrf result input)
         (rrf result input))))))

Ben Sless20:10:59

then just use it in a transduction

Ben Sless20:10:54

(into [] maybe-cat coll), or any other API

borkdude13:10:45

@vfernandez11 While I don't recommend using it, flatten comes close:

user=> (flatten '((3 4) (5) 1 6 [3 [6]]))
(3 4 5 1 6 3 6)
Probably better to just roll your own

Valentín13:10:33

You are rigth

Valentín13:10:03

But I'm solving 4clojure problems and I'm implementing flatten

Valentín13:10:17

With the restriction of using flatten

gtrak14:10:21

what do people use for code formatting lately, that works with different editors.

Tzafrir Ben Ami14:10:47

cljfmt, clj-kondo (both have good support for major IDEs)

borkdude15:10:12

clj-kondo doesn't do formatting

gtrak15:10:32

I saw zprint and joker do it too, but not sure how widely used they are

borkdude16:10:21

@U066U71AR This is a fork of cljfmt which looks pretty great: https://github.com/greglook/cljstyle by @U8XJ15DTK

gtrak16:10:02

thx, I'll check that out.

greglook16:10:39

been a bit of a lull while I’ve been busy with other projects, but I’m planning to get to a 1.0 release later this year with better config and more options 😄

borkdude16:10:28

while on the subject, can puget also pprint code or is it more tuned towards EDN @U8XJ15DTK

gtrak16:10:33

we're spoiled with prettier, black, and ocamlformat, but trying to get clojure in now.

greglook16:10:17

puget is very much about EDN/data rather than code, though it does do one or two code highlighting things

Grant Isom16:10:56

Anyone have some solid examples of this library in action by chance? https://github.com/weavejester/ring-oauth2 Perusing Github didn’t bring up much

Eric Scott18:10:48

I'd like to do something like this using spec, and I'm having a hard time.

(spec/def ::int-to-int-fn
  (spec/fspec
    :args (cat :n int?)
    :ret int?))

(defn add-5 [n] (+ 5 n))

(defn subtract-3 [n] (- n 3))

(spec/fdef add-5 ::into-to-int-fn) ;; this draws an error

(spec/fdef subtract-3 ::int-to-int-fn) ;; this draws an error
Is this possible? Or would I need to do
(spec/fdef add-5
    :args (spec/cat :n int?)
    :ret int?)
And repeat that for subtract-3 and any other function with that signature?

andy.fingerhut18:10:03

You don't get an error on the first attempted call to spec/fdef on add-5? I did, in my attempt to reproduce what you see.

andy.fingerhut19:10:43

Perhaps if you do (spec/def add-5 ::int-to-int-fn) it achieves what you want (note spec/def instead of spec/fdef)

Eric Scott19:10:17

No I got an error for both of them. Typo on my part.

Eric Scott19:10:22

I can spec/def add-5 ::into-to-int-fn without an error, but what I'm looking for to achieve the equivalent of giving :args, :ret, etc. with a single token declaring a common i/o signature

Eric Scott19:10:01

For example if I spec/def add-5, then ask for docs on add-5, the 'spec' section of the output is nil.

andy.fingerhut19:10:20

I do not know if there is a way to achieve what you want with spec. (I'm not saying there isn't -- just that I'm not enough of a spec expert to give a definitive answer either way)

Eric Scott19:10:59

Yeah it's starting to look like it's out of scope for spec. It'd be cool though. Thanks for your help!

andy.fingerhut19:10:34

You may get a more expert answer by asking in #clojure-spec channel

KJO18:10:00

While running this from the command line clj -Sdeps '{:deps {org.apache.pdfbox {:mvn/version "2.0.21"}}} I get the following errors and a stacktrace

Error building classpath. 3 problems were encountered while building the effective model for org.apache.pdfbox:pdfbox:2.0.21
[ERROR] Failed to determine Java version for profile jdk9 @ org.apache.pdfbox:pdfbox-parent:2.0.21
[ERROR] Failed to determine Java version for profile jdkGte9 @ org.apache.pdfbox:pdfbox-parent:2.0.21
[ERROR] Failed to determine Java version for profile jdk11 @ org.apache.pdfbox:pdfbox-parent:2.0.21org.apache.maven.model.building.ModelBuildingException: 3 problems were encountered while building the effective model for org.apache.pdfbox:pdfbox:2.0.21
[ERROR] Failed to determine Java version for profile jdk9 @ org.apache.pdfbox:pdfbox-parent:2.0.21
[ERROR] Failed to determine Java version for profile jdkGte9 @ org.apache.pdfbox:pdfbox-parent:2.0.21
[ERROR] Failed to determine Java version for profile jdk11 @ org.apache.pdfbox:pdfbox-parent:2.0.21    at org.apache.maven.model.building.DefaultModelProblemCollector.newModelBuildingException(DefaultModelProblemCollector.java:197)


Anyone have any idea how to resolve this?

seancorfield18:10:54

@heykieran That doesn't look like a valid coordinate to me -- you have just the group ID with no artifact ID.

seancorfield18:10:13

This works:

clj -Sdeps '{:deps {org.apache.pdfbox/pdfbox {:mvn/version "2.0.21"}}}'

KJO19:10:06

Thanks @seancorfield - I was trying to simplify a larger problem where I was getting an error dep’ing a local jar. I ran the cli in the same directory, which merged the deps, and what I was seeing is the original error. Sorry, clj never got to tell me I was an idiot for using bad coords. It had baled already. Back to square one for me.

Alex Miller (Clojure team)19:10:45

newer clj will fail earlier with a little better pointer

KJO19:10:15

It’s a long shot, but any obvious things I should look for (and might cause an error like this) while dep’ing a jar that I know can be referenced in Java, its classes imported, and used without issue?

Alex Miller (Clojure team)19:10:47

what error are you seeing? that stuff above?

KJO19:10:42

Yup. The only dep in the deps file is a local jar. Even just trying to start the repl throws the error. Not much info there, sorry.

seancorfield19:10:17

@heykieran Is it anything we can see publicly, to help you debug it?

KJO19:10:16

@seancorfield this is ironic. Once I got it working, I was going to write a blog post about how to merge data to Word files and push to docusign. The jar does the merging. However, I haven’t got the ok on that yet. And I don’t want to color outside the lines. I’ll see if I can reduce it to as simple a case as possible. Appreciate the offer.

Alex Miller (Clojure team)19:10:25

can you set JAVA_HOME and see if that helps?

Alex Miller (Clojure team)19:10:25

pdfbox parent pom has a property that uses ${env.JAVA_HOME}

Alex Miller (Clojure team)19:10:53

I think that's what's failing (and what's not failing for me because I have it set)

KJO20:10:24

Unfortunately, JAVA_HOME is set. I think it’s the way the jar (a kind of Uber jar, with everything included) is being created. I may pull it apart and then reassemble. Even if I take out the pdf dependencies in the jar, I get an error about commons-io. Two funny things, the base jar without its dependencies imports fine (but doesn’t work) and the uberjar works fine in Java. Appreciate your help.

Alex Miller (Clojure team)20:10:29

oh, that could be it - uber will sometimes strip or replace things that collide and you can run into some weirdnesses that way

Alex Miller (Clojure team)19:10:16

what you're seeing above is almost certainly due to jdk profile stuff in maven - you might need to explicitly pull in one of the classifier jars (maven has a whole system for figuring this out which is not really be used through clj)

vlaaad19:10:40

Question about polymorphism: should I limit myself to just built-in tools like protocols where they fit, or is it okay to have something in front of protocols that might perform automatic conversion to target type? For example, if there is a map with a special key, I might supply a particular behavior for these maps, while other maps are treated by default protocol impl

Alex Miller (Clojure team)19:10:38

as a general practice, I nearly always front a protocol method with a function

6
vlaaad19:10:17

and that function can do some automatic conversions?

Alex Miller (Clojure team)19:10:49

that's up to you, but it's often a good place for custom processing to grow

vlaaad19:10:25

I just worry that might be a source of complexity where easy to use makes it hard to reason

vlaaad19:10:58

if the API is "it has to be something implementing protocol, and we implement Object and nil for you", that's quite easy and straightforward, but for some common uses there might be wrappings required...

Alex Miller (Clojure team)20:10:47

well if you're the one doing the wrapping for an extender at use then you're in control. depends how the wrappings come into play

vlaaad20:10:15

Users have to do the wrapping, but I can infer that wrapping from what they supply to me from the data they supply, and it will work in 99% of cases. And for remaining 1% where they had the key but "didn't mean it", they will be able to supply the data in a way that I'll be able to treat as if they "didn't mean it"

vlaaad20:10:14

Hmm, I guess that might be worth it...

Louis Kottmann21:10:29

hello, I want to create a Slack bot where functions react to certain messages on chat depending on regexp matches to call the right function. i.e: a "cake" message gets dispatched to the (defn cake ...) method. I would like to specify the regexp that matches a function next to it in its own source file, but what is the best way to aggregate them all so that the dispatcher fn knows all the available regexps/defn couples? should I use some kind of reflection code or is there a better way?

phronmophobic21:10:03

there's definitely more than one way to do it. the approach that first comes to mind: • define your cake method and add some meta data with the regexp

(defn ^{:slackbot.ns/regexp #"cake.*"} cake ...)
• have the slack bot receive a dispatch function of regexps to handlers • create a function that given some namespace, will look up all the functions with the :slackbot.ns/regexp meta data • create your bot like: (make-bot (find-slack-handlers 'my.ns 'my.other.ns))

Louis Kottmann21:10:24

can I lookup in a wildcard namespace? like myapp.commands.*? maybe I'd just lookup all the subnamespaces of myapp.commands.*?

Louis Kottmann21:10:58

it's my first clojure project so I'll have lots to learn but I figured metadata was a likely answer

phronmophobic21:10:40

you can, but it's easier if the namespaces are already loaded when you try to find the handlers

Louis Kottmann21:10:55

another idea I had was to make create a macro that, when called, added a regexp to defn entry to a collection of maps and then defined the defn as well?

phronmophobic21:10:18

the other option that I've used is have a macro like defslackhandler and that handler will "register" the handler in a global list. "registering" just means swapping into an atom in the slack namespace

Louis Kottmann21:10:42

what would be the more idiomatic way?

phronmophobic21:10:07

seems like that's how spec registers specs

Louis Kottmann21:10:34

alright, thank you very much I'll go the macro route

phronmophobic21:10:55

the def macro translates to a register call which adds an entry to an atom

Louis Kottmann21:10:35

gonna be a fun exercise in demystifying macros 🙂

parrot 3
vlaaad21:10:32

You can also inspect ns with ns-interns and ns-publics

phronmophobic21:10:34

doesn't ns-interns require that the namespace is already loaded, not just available on the classpath?

vlaaad21:10:41

Reveal uses that to build cli command list from defs

vlaaad21:10:54

Yes, it has to be loaded

Louis Kottmann21:10:35

so will I need to "preload" all my calls to defslackhandler?

vlaaad21:10:49

Do you think you need dynamic loading and multiple namespaces? Maybe single ns with command list would do?

vlaaad21:10:16

Or maybe even a single def with a map...

Louis Kottmann21:10:27

I am reimplementing a bot with thousands of lines of ruby and 50 commands

Louis Kottmann21:10:37

if it's all in one file it's gonna be a mess...

vlaaad21:10:47

I think that's fine for a single map from regexps to handlers if handlers are extracted to other namespaces

Louis Kottmann21:10:38

I like to keep code that works tightly together in the same file, which I why I want the regexp and the defn next to each other

phronmophobic21:10:48

you just need to make sure an load all the namespaces with handlers from the namespace that contains your main

👌 3
Louis Kottmann21:10:55

so that I don't have to switch emacs buffers around to make modifications

lukasz21:10:33

Having just turned off the bot which was a part of our product's Slack integration: we have centralized all command handling in the HTTP handler function, since you're just going to get a raw message text and you'll have to parse the commands yourself. Disclaimer: that was an old school bot, it had to listen to all incoming messages. I never worked with slash commands, which are newer style and might do some command parsing

Александр Стоянов22:10:09

Hello. How can i add my_project/src/clj/server.clj to classpath? Inside my project.clj i have :source-paths ["src/clj" "src/cljs"] but it doesn't work and i dont know why:disappointed:

phronmophobic22:10:05

can you give a few more details as to what you are trying and the error message you're receiving?

Александр Стоянов22:10:13

I try to start backend REPL with `lein run` and get: Can't find 'grump2.server' as .class or .clj for lein run: please check the spelling. Syntax error (FileNotFoundException) compiling at (/tmp/form-init3649709 871957213789.clj:1:73). Could not locate grump2/server__init.class, grump2/server.clj or grump2/server.cljc on classpath. And it doesn't matter where is `server.clj` file: `grump2/server.clj`, `grump2/src/server.clj` or `grump2/src/clj/server.clj`

phronmophobic22:10:58

do you have (:gen-class) in your ns declaration?

Александр Стоянов22:10:40

is it in project.clj should be?

Александр Стоянов22:10:22

i need add this to server.clj?

phronmophobic22:10:24

I would try that, and it's expecting the file in:

<myproject>/src/clj/grump2/server.clj
with the namespace grump2.server

phronmophobic22:10:55

I think. if I'm reading the error messages correctly

Александр Стоянов22:10:42

i've created src/clj/grump2/ dir and added server.clj file and db.clj because i have import there. And get same error but now it can't find db.clj

phronmophobic22:10:13

do you have the command you're running and the error message you're getting?

Александр Стоянов22:10:27

thank you very much:grin:

😄 3
Александр Стоянов22:10:45

now i have new bugs but it's working now and it's great

parrot 3
Александр Стоянов22:10:22

Can i write to you sometimes for help?

phronmophobic22:10:21

I'd recommend posting in #beginners. if I'm around and available, I'll try to help!