Fork me on GitHub
#clojure
<
2017-08-22
>
stuartrexking06:08:38

I have a vector of 8760 values (one for each hour in a non-leap year). I want to calculate the average of each day. How can I map over the vector in increments of 24?

bfabry06:08:31

specifically (partition 24 1 values) by the sounds

magra07:08:25

Hi, this code is supposed to delete all files in a directory and then repopulate it with previews. (defn build-previews [] (clear-directory "resources/public/preview") (map (partial spit-ad "resources/public/preview/") (filter #(= "true" (:preview %)) (vals (:ads @db)))) (println "debug build-previews done")) all the lines work if I eval them individually, the files get deleted and the previews get written. But when I execute them together the only the println gets executed. If I wrap the three in a do it won't help. Could someone please give me a hint?

curlyfry07:08:51

@magra Each of the statements are supposed to perform side effects, right?

the-kenny07:08:59

magra: map isn't useful for producing side effects as it's lazy. Use doseq.

curlyfry07:08:10

My guess is that you aren't seeing any effects in your "resources/public/preview" folder because you're using map which is lazy and meant for pure functions. When you evaluate that line by itself your evaluation will consume the map and show you the result, but when you have it as one of the statements you are building a lazy seq without any code that consumes it, meaning that it won't have an effect. Try using doseq instead.

magra08:08:28

@curlyfry Thanx! That works.

Pablo Fernandez09:08:39

When using gen-class, how do I override this method:

public abstract void start(Stage primaryStage) throws Exception;

Pablo Fernandez09:08:57

Stage is javafx.stage.Stage.

Pablo Fernandez09:08:07

-start-javafx.stage.Stage?

davids10:08:29

Hi! I am using Gradle to build a multiproject big project, and on of the projects is in Clojure, which I am depending on from a Java project so I AOT compile it. So I tested the dependent project, and everything works in Gradle, but IntelliJ cannot find the generated classes and it is pretty annoying. I am using the nebula.clojure Gradle plugin. The projects are imported from Gradle. Do you know a way to fix this?

cddr12:08:03

Not familiar with that plugin but I guess this boils down to a classpath problem. I'd try to find where (in the filesystem) the clojure classes are being emitted, and what your intellij classpath is set to.

davids15:08:24

it turns out Cursive uses source code inspection to add this functionality, which only work for simple cases but not for macros. So I have to work around it, and add the output to the classpath 😕

zilti10:08:12

How can I execute a core.logic goal repeatedly until exhausted, and use the result as a list in my logic program? I'm looking for the equivalent to "nesting" a run expression, so to speak

zilti11:08:26

@pupeno you don't have to override it; add (defonce force-toolkit-init (javafx.embed.swing.JFXPanel.)) to initialize the toolkit, then simply create a new Stage and use it (see ClojurefX) 🙂

Pablo Fernandez11:08:02

@zilti I managed to get it to work… I’d rather not use the Swing part if I can avoid it.

Pablo Fernandez11:08:03

Why does the default lein template for an app include skip-aot for the main function/namespace?

noisesmith15:08:11

Aot causes bugs that don't happen without aot, and it is rarely needed.

zilti12:08:34

Basically what I have now is:

clojure
(defn next-free-license [ltype]
  (run 1 [q]
       (fresh [licid tid link links license]
              (datascript= [tid :type/name ltype])
              (datascript= [licid :license/type tid])
              (datascript= [licid :license/key license])
              (datascript= [licid :license/user link])
              (membero link links)
              (== q [links licid license]))))
Which gets me `[(138 . _0) 6 "532f16c2c9b13540eb6a"]

zilti12:08:04

Which gets me [(138 . _0) 6 "532f16c2c9b13540eb6a"] but I need [(138 143 151 153) 6 "532f16c2c9b13540eb6a"]

Pablo Fernandez13:08:01

Can anybody confirm whether creating fields/members in a Java class in Clojure is impossible?

bronsa13:08:59

static fields

bronsa13:08:24

you can create instance fields using deftype

zilti13:08:14

At that point you should think if forcing that into Clojure instead of using a Java class is really the way to go, though

Pablo Fernandez13:08:20

Let me see about deftype.

Pablo Fernandez13:08:20

@zilti I’ll evaluate that later if it’s too ugly or impossible; but having a Java class will also be very ugly.

Pablo Fernandez13:08:26

@bronsa but deftype cannot add new instance methods, can it?

bronsa13:08:08

i suggest you drop to java, it'd be clearner

Pablo Fernandez13:08:01

I’m not sure if it’d be cleaner. I’d have to deal with the mismatch of data types between Java and Clojure.

Pablo Fernandez13:08:26

But if Clojure cannot do it, then, there isn’t much of a choice.

bronsa13:08:50

what mismatch?

Pablo Fernandez13:08:39

@bronsa keyword indexed maps of various different types that are impossible in Java.

bronsa13:08:19

you can always use clojure.lang collecitons

Pablo Fernandez13:08:36

@bronsa: have done that? have an application half done in Java and half done in Clojure? I have a Clojure server and just writing a Java client for that was a pain due to the lack of dynamic types. You have to define everything in advance and cast/convert.

Pablo Fernandez13:08:07

I mean, just having to call Clojure functions from Java is horrible: https://clojure.org/reference/java_interop#_calling_clojure_from_java

bronsa13:08:19

yeah sure, I wasn't suggesting half an app in java invoking clojure, just that one class you need

Pablo Fernandez13:08:53

@bronsa that one class is the controller for the UI… possibly 20% or 25% of the app.

bronsa13:08:26

can't you just write the java class as a proxy for the actual clj impl?

Pablo Fernandez13:08:31

It is doable but then the advantage of using Clojure at all is going down.

bronsa13:08:40

& just use java to create the class w/ the fields you need

bronsa13:08:00

which is kind of how proxy/gen-class work

Pablo Fernandez13:08:17

What do you mean by just use java?

bronsa13:08:18

class Foo extends Bar { public Object myField; void myMethod () { RT.var("my-ns", "my-method-impl").deref().invoke()) };}

bronsa13:08:46

drop down to java to create your class, delegate to clojure for the impl

Pablo Fernandez13:08:58

Yes, that’s what we’ve been discussing. I don’t believe the proxying would be that simple.

bronsa13:08:35

alternative: create an abstract java class with all the stuff you need, than proxy it in clojure

Pablo Fernandez13:08:38

First, things in the real world rarely are simple. Second, is not going in one direction, it’s going in both directions. The Java class would have to pass its instance to the Clojure functions, so they can keep a reference to call back. Because Clojure won’t be able to interact with JavaFX directly, I’d have to make a lot of proxying methods/functions so that the code can be written in Clojure or just write it in Java.

Pablo Fernandez13:08:01

I haven’t tried it yet, so, this is just what I’m coming up from the top of my head.

bronsa13:08:31

right, i don't know how you're going to need this in your real world code, I'm just answering the question of whether or not it's possible to do it in clojure

bronsa13:08:48

and the answer is not, and those are the two alternatives you have

Pablo Fernandez13:08:00

Yeah… this is sad.

tbaldridge13:08:01

"Because Clojure won’t be able to interact with JavaFX directly" There's two JavaFX/Clojure libraries that do exactly that

tbaldridge13:08:39

There's nothing really that special about JavaFX, it's just Java classes and Clojure interop works quite well with it.

Pablo Fernandez13:08:28

@tbaldridge there are three, fn-fx, fx-clj, both of which cannot do fxml which is what I’m trying to do. ClojureFX does it, but I’m not very happy with its code, it seems quite experimental and handling fxml require some horrible hacks which I was trying to stay away from.

tbaldridge13:08:54

yeah, fxml is something I haven't looked into adding to fn-fx

tbaldridge13:08:24

mostly because I've coded my UIs through the years without fxml or xaml designers. I should look into that sometime perhaps

Pablo Fernandez13:08:53

@tbaldridge what’s special about JavaFX or rather, fxml, is that you have an xml that points to a class and when you load the fxml, it instantiates that class and sets member/fields on that class. I’m trying to generate those classes from Clojure but this looks impossible.

Pablo Fernandez13:08:11

@tbaldridge are you fn-fx’s developer?

tbaldridge13:08:48

yeah, I mean fxml is more-or-less the same as fn-fx's EDN based data.

Pablo Fernandez13:08:11

Cool. You should check out ClojureFX’s solution for inspiration.

tbaldridge13:08:13

Except for any class extension/inheritance stuff, and I haven't dug into that enough to know if it's really needed.

Pablo Fernandez13:08:49

The reason why I’m trying to use fxml is not for XML but for the UI designer.

tbaldridge13:08:45

it's probably possible to write a fxml importer or converter

zilti13:08:41

Yes, I've come up with a pretty neat FXML loader and an accompanying generator for the controller classes

tbaldridge13:08:42

the problem would be with the binding and event models. JavaFX's model of binding components via listeners and observers is a pattern I disagree with. I'll have to see if these UI designers can support fn-fx's React-esque model

Pablo Fernandez13:08:49

Also, I’m trying to reduce the amount of experimental/unmaintained stuff I have. I wrote the app on Electron+ClojureScript and there’s a lot of very new, very experimental stuff there and the app is not stable enough. Hence why I’m analyzing re-writing it on the JVM.

Pablo Fernandez13:08:03

I wasn’t sure if fn-fx was actively maintained: https://github.com/halgari/fn-fx/pulse/monthly

tbaldridge13:08:24

it kindof is...I just don't have a lot of uses for it, so I don't make updates often.

zilti13:08:40

ClojureFX is actively maintained right now: https://bitbucket.org/zilti/clojurefx Since I now have the main importer, I'm open to recommendations

zilti13:08:45

Especially binding stuff

Pablo Fernandez13:08:37

@zilti: I looked at the code to interface with fxml, and I bet it’s very clever, but I couldn’t understand it and I don’t know how stable it is; so, I wouldn’t want to deal with instability coming from it. Also, I couldn’t figure out how I’m supposed to access members. I read in the manual that it is possible but not how.

tbaldridge13:08:55

fxml is good feedback though, and that's what I need at the moment, more user feedback

Pablo Fernandez13:08:17

(and to be fair, I also wanted to do this manually to understand fxml/javafx a bit better and know what I’m getting into if I choose it)

zilti13:08:55

@pupeno: Class members? Just like normal Java class members. The FXML loader generates a Java class. Everything with an fx:id is represented as a Java class member in the generated class.

Pablo Fernandez13:08:48

So, if I have an fx:id that says label, I can just do (.label whatevs) to access it?

zilti13:08:20

@pupeno: exactly. And "whatevs" is given to the init function as the argument.

Pablo Fernandez13:08:05

ok… let me give that a try.

Pablo Fernandez13:08:34

What were you referring to when you said you wanted feedback about the binding stuff?

zilti13:08:26

pupeno: feedback about how to improve how to bind to Stuff happening in the GUI (yes, there isn't much at the moment). Right now you'd do

clojure
(.addListener someListenableObj
                  (fx/fi javafx.beans.value.ChangeListener [ovable oldV newV]
                         (when-not (= oldV newV)
                           (debug "Selected row" newV))))
to e.g. listen for a row selection change, which is obviously somewhat cumbersome

tbaldridge13:08:07

That's something I'd like to see different in ClojureFX. As a user (not speaking as the author a of a competitor lib here), why use ClojureFX if I'm still using Java Interop?

tbaldridge14:08:13

But I guess that's the point of the lib? it's mostly a syntax wrapper?

zilti14:08:48

Well, I'm planning on resolving that listener "issue", but I haven't decided on how to do it yet

Pablo Fernandez14:08:54

@tbaldridge I think my attempt at trying to use JavaFX shows why 😉

zilti14:08:58

Especially because I don't want it to be a framework, I can't stand frameworks (and ironically, JavaFX itself shows why - happy initializing without the Swing hack...)

tbaldridge14:08:16

It's an interesting contrast, and I suppose that's what you have to ask yourself @pupeno do you want to use a stateful OOP UI style, or a React-esque diffing model.

tbaldridge14:08:42

I think both are valid in different situations, but it is a design decision that affects consumers of the UI library

Pablo Fernandez14:08:46

@zilti I got an error that I think it’s coming from the controller generator: https://gist.github.com/pupeno/4eb3fbc61d86e6a622cb81f494972653

cjhowe14:08:28

@tbaldridge btw, is there any reason event handlers aren't functions in fn-fx? is it because you need to check if the event handler has changed?

zilti14:08:51

@pupeno you have to give it the full-path symbol to the init function - it needs to extract the namespace, too, for the action handlers.

zilti14:08:27

@pupeno or a string works too. Like "some.project.maincontroller/init"

tbaldridge14:08:38

@cjhowe that's pretty much it, but more and more I think the fn-fx model is better. Functions can do anything. Defining functions as data forces users to stick with the circular event model of: state change -> differ -> ui -> event -> change state

tbaldridge14:08:31

In UI code I've noticed that the first thing people do with Event handler functions is go do some sort of side-effect

tbaldridge14:08:12

And the whole idea of fn-fx is to turn JavaFX into a functional interface, with few (or no) side effects in user code.

cjhowe14:08:33

but it's still pushing the problem of state management and side effects to the handler, i think it could be useful to have more tools to work with side effects and the building of handlers themselves

cjhowe14:08:29

i guess the intent is to push that handler functionality to another library though?

tbaldridge14:08:40

true, the handler has to do something with the data. In fn-fx it simply passes that data to the function given to the renderer.

tbaldridge14:08:09

So yeah, maybe it's less about functional purity and more about not wanting users to put swap!, send, transact, etc inside a event handler

tbaldridge14:08:34

And I absolutely don't want an event hander mutating another control.

Pablo Fernandez14:08:18

@zilti I’m sorry, to which function?

zilti14:08:28

pupeno: when JavaFX initializes the FXML file and its controller, it has to call an init function. You have to tell ClojureFX the fully qualified name of that function. (defn init [controllerinstance] ...)`

Pablo Fernandez14:08:42

How do I tell ClojureFX that?

zilti14:08:38

pupeno: e.g. (fxml/load-fxml-with-controller (io/resource "fxml/whatever.fxml") "my.companion.namespace/init")

Pablo Fernandez14:08:01

oh, I have to pass the symbol instead of a function.

zilti14:08:36

Because handlers for e.g. a clicked button also get called inside the same namespace as the init function

Pablo Fernandez14:08:27

It seems to want a string, not a symbol: Caused by: java.lang.ClassCastException: clojure.lang.Symbol cannot be cast to java.lang.CharSequence

zilti14:08:56

Ah, yes. That'll get corrected in the next release.

bendlas15:08:06

For the spec (s/and vector? (s/cat :a int? :b string?)), s/unform returns a list. Am I doing it wrong or is this a bug? @alexmiller

Alex Miller (Clojure team)15:08:11

currently, it is difficult to spec something that is both a regex and a vector and get the desired behavior for conform, unform, gen, and explain

Alex Miller (Clojure team)15:08:33

it is possible to get some of those to work desirably via various workarounds

bendlas15:08:05

i guess this is one of the reasons for spec.alpha, right?

bendlas15:08:18

thanks for clearing it up to me

Alex Miller (Clojure team)15:08:45

rich is still trying to decide on the best way to handle this, but it’s definitely a real need - this comes up frequently in macro specs in particular

Alex Miller (Clojure team)15:08:04

for your specific example, I would use (s/tuple int? string?)

Alex Miller (Clojure team)15:08:26

that should conform to a vector I think

Alex Miller (Clojure team)15:08:32

sorry, unform to a vector

bendlas15:08:33

@alexmiller thanks, but i actually need the regex spec. I'm trying to transform garden stylesheets:

(s/def ::rule
  (s/and vector?
         (s/cat :selectors (s/+ ::selector)
                :styles+rules (s/* (s/alt :style ::style
                                          :rule  ::rule)))))

Alex Miller (Clojure team)15:08:31

it is possible to fix the unform by using a conformer with an unform function (which has some downsides for gen, form, etc, so it depends which things you care about most)

bendlas15:08:49

ok, I thought so. thanks!

Alex Miller (Clojure team)15:08:36

something like (s/def ::rule (s/and vector? (s/conformer identity vec) (s/cat ...)))

👍 1
bendlas15:08:58

Thanks!, I was just about to piece that together. Very helpful!

noisesmith15:08:09

Also, run! is a drop in replacement for to arg map, and is for side effects

(run! println (range 10))

pwrflx16:08:33

I've instrumented a middleware function using Cider and if I directly invoke this function the debugger stops fine. however, if I invoke it indirectly bu making a request to Jetty, it does not stop any more. Is this normal?

noisesmith16:08:34

depends how you started jetty

noisesmith16:08:23

if you passed the var of the handler to jetty, clojure should see and call the new definition on every invocation, if you only passed the function, it won’t see redefinitions of that function (it’s only resolved once when initially passed in)

pwrflx16:08:53

@noisesmith hm good point. I'm actually using stuartsierra's jetty component, that is like this:

pwrflx16:08:37

`(let [options (-> component (dissoc :app) (assoc :join? false)) handler (atom (delay (:handler app))) server (jetty/run-jetty (fn [req] (@@handler req)) options)] (assoc component :server server :handler handler))`

pwrflx16:08:10

so I guess the atom and the delay can result an such issues

noisesmith16:08:11

wow, an atom wrapping a delay?

noisesmith16:08:15

that’s super odd

pwrflx16:08:43

maybe it's on purpose so it can be replaced without jetty being restarted?!

noisesmith16:08:17

oh, right, you can put a new delay into the atom, looked up via the component

noisesmith16:08:23

but a delay inside that?

hiredman16:08:10

what makes you say that is stuartsierra's jetty component?

pwrflx16:08:34

@hiredman ah sorry you are right, I remembered wrong. it just uses component, but the jetty component is not written by stuart. here is the source:

mike_ananev17:08:22

Could this lib make Clojure faster? https://github.com/jgpc42/insn

noisesmith17:08:38

not likely - clojure already does byte code generation

dpsutton17:08:53

i'm running a dev server from my repl with (jetty/run-jetty handler/app {:port 3001}) but running into cors issues. is there a way to set the jetty instance to allow all CORS? I'm not seeing it in the code for that

noisesmith17:08:56

but you can totally use that lib to avoid writing java for stuff that needs to be optimized

jeff.terrell17:08:31

@dpsutton - Can you wrap handler/app in ring middleware? If so, that's how I'd do it.

dpsutton17:08:00

yeah, i can but then my dev settings for cors are leaking into the app

dpsutton17:08:19

was hoping i could do it at the jetty level since that's in a ns loaded only in the dev profile

noisesmith17:08:31

I’ve often felt like the cleanest thing is to have a middleware stack directly driven by the configs - I think the way pedestal interceptors work might allow this? I have also in the past used a wrap-config middleware that takes a handler, a tergent env, and the current env, and either wraps the handler or returns it unchanged based on matching the env

noisesmith17:08:57

(defn wrap-config [handler current-env target-env middleware] (if (= target-env current-env) (middleware handler) handler))

dpsutton17:08:25

yeah, sounds like i'll need to do a bit more wrangling. thanks for the suggestoins

Alex Miller (Clojure team)18:08:42

there are a couple of tickets in this area already, so probably a dupe of those

bendlas18:08:03

hm, I'll see if i can find one ...

bendlas18:08:10

thanks, I'll see if I can contribute to one of thos

bendlas18:08:35

in my case, unform shows correct behavior (i.e. throws on conform's output)

bendlas18:08:44

hm, it looks like the case in @pbrown's comment in CLJ-2003

bendlas18:08:59

I'll give the attached patch a whirl

mokr19:08:44

Anyone familiar with IntelliJ’s “New -> Clojure namespace”? I’m in the process of creating my first Clojure library to push to Clojars. I started with a simple “lein new foo”. This template creates a source structure like “src/foo”, but I would like it to be “src/clj/foo” (in preparation for cljs and cljc being added later). My issue now is that whenever I create a new namespace in IntelliJ, it insists on calling it “clj.foo.newns” instead of “foo.newns”. Inconvenient, and the running “lein test-refresh” complains right away about a missing namespace. I can’t seem to figure out where this might be configured, project.clj, IntelliJ itself or possibly by Cursive. Sidenote: For my regular projects I use the Luminus template that has my desired source structure, and then IntelliJ works the way I would like. Any help appreciated.

delaguardo19:08:56

how you define :source-paths in your project.clj?

mokr19:08:00

:source-paths [“src/clj” “src/cljc”]

mokr19:08:15

Copied from a project using Luminus template

delaguardo19:08:19

strange, i saw the same problem in emacs when source paths was defined like “src”

mokr19:08:24

Solved it now, but thanks anyway

cfleming21:08:45

@mokr It sounds like src/clj wasn’t marked as a source root, perhaps your lein project wasn’t synced?

mike_ananev19:08:24

@mokr try this: select src folder, right click, unselect as Root SRC Folder, select clj folder, right click, select as root source

mokr19:08:00

@mike1452 Thanks, I’ll try

mokr19:08:47

@mike1452 That solved it! Thanks a lot 🙂

beoliver19:08:04

anyone know which types are not comparable using =? The only thing I have found so far is java.util.regex.Pattern i.e (= '#"a" '#"a") returns false.

beoliver19:08:07

I am comparing quoted expressions so for example even though java.util.regex.Matcher is not comparable and (= '(re-matcher '#"a" "a") '(re-matcher '#"a" "a")) returns false, this can be compared by compaing by (map = '(re-matcher '#"a" "a") '(re-matcher '#"a" "a")) which gives (true false true) meaning that it is only the Pattern that can not be matched

beoliver19:08:12

So I guess I could re-phrase the question. Which types that can be represented in source code can not be compared?

seancorfield19:08:40

@beoliver From the docstring for =:

Equality. Returns true if x equals y, false if not. Same as
  Java x.equals(y) except it also works for nil, and compares
  numbers and collections in a type-independent manner.  Clojure's immutable data
  structures define equals() (and thus =) as a value, not an identity,
  comparison.
So, effectively everything that can compare equals in Java under the hood.

seancorfield19:08:10

So java.util.regex.Matcher's equals() method doesn't behave the "intuitive" way I guess.

delaguardo19:08:04

boot.user=> (instance? java.lang.Comparable "")
true
boot.user=> (instance? java.lang.Comparable #"")
false

seancorfield19:08:10

But you can't exhaustively specify what "can not be compared" since reader literals let you create fairly arbitrary objects and the behavior of equals() is going to depend on the underlying type.

seancorfield19:08:56

(and, strictly speaking, they can be compared but the answer might not be what you expect)

beoliver19:08:02

you mean the underlying DFA?

seancorfield19:08:28

And there's also stuff like (= Double/NaN Double/NaN) producing false -- is that what you're expecting?

beoliver19:08:55

my bad, thought you were talking about comparing regular expressions

beoliver19:08:11

deterministic finite automata

seancorfield19:08:42

No, I'm talking in general about source code expressions that look equal but = will produce false for.

beoliver19:08:06

the thing is that I am comparing quoted expressions so (= 'Double/NaN 'Double/NaN) is true as we are just comparing symbols. The only problem that I have encountered is that of the Pattern. I guess this has more to do with the dispatch macro?

seancorfield19:08:53

Yes, if you're just comparing reader-processed data -- hence my initial comment about reader literals #some-thing {:stuff 1}

seancorfield19:08:29

Whether two of those will compare equal (`=`) will depend on the type instance that it expands to.

seancorfield19:08:47

@delaguardo Comparable is about ordering, not equality -- and the definition of Comparable specifically states that x.compareTo(y) == 0 does not necessarily have to mean x.equals(y) (although that is normal)

seancorfield19:08:28

Java equality is a strange beast, unfortunately.

beoliver19:08:24

are user defined reader literals a common thing?

beoliver19:08:49

reader macros

seancorfield19:08:41

They are becoming more common. They were only introduced a few versions ago.

beoliver19:08:20

I guess the other way to compare for equality would be to fully macro expand both expressions and then compare strings factoring that two expressions may use different locally bound names

seancorfield19:08:33

I guess the question we should be asking is: what problem are you actually trying to solve?

beoliver19:08:07

Given an top level expression E in namespace N (source file). Assume that you have run an expensive test on E and it passed. Now, when the code is changed, I only want to run the test if the code is different. I don't want to run all tests for that namespace. So I locate the expression that has been changed and decide if the changes actually "change" the expression. Eg variable renaming should be ignored.

seancorfield20:08:36

Hmm, a very difficult problem in the general case...

beoliver20:08:38

I wrote a proof of concept where i just used a special case test against Pattern... but I would prefer to have something that is provably correct.

seancorfield20:08:54

Something to consider is that a reader literal can generate a different value every time it is read, depending on what it does.

Alex Miller (Clojure team)20:08:39

I’d say that if you do that, you deserve what you get

Alex Miller (Clojure team)20:08:54

and also, don’t do that

seancorfield20:08:45

I will make no attempts to justify it beyond "convenience" 🙂

Alex Miller (Clojure team)20:08:13

does not seem convenient :)

seancorfield21:08:03

This particular case is actually just an "include" syntax for an EDN configuration file so the reader is local to "reading in the file". It was more meant as an example of just how #foo/bar 0 can "do stuff" behind the scenes and make code level equality harder to detect.

Alex Miller (Clojure team)21:08:27

literals should be values, comparable by equality. the end. :)

Alex Miller (Clojure team)21:08:45

what do you think this is, OO? ;)

beoliver20:08:43

yeah, this I what I am trying to fully understand. When is it "safe" to consider something symbolically equal etc

seancorfield20:08:46

For example, we have a reader literal we use in our configuration library that "includes" a file (reads an EDN file) -- so the value it returns depends on an external file's contents at the time of processing.

beoliver20:08:43

yeah, I have been considering a pass to infer if a function is pure or not

beoliver20:08:13

as a trivial example (= '(rand) '(rand)) is true 😄

seancorfield20:08:40

Also, reader literals can have different meanings when the (external) data_readers.clj file is changed. So two separate test runs could have #foo/bar 0 turn into different values.

beoliver20:08:21

the question is, is this task undecidable, or just complex?

seancorfield20:08:59

I think it's undecidable in the general case. But tractably complex in a more realistic case, i.e., with a few caveats since worst case you say code has changed when it hasn't, so assuming unequal is "safe" but less than optimal.

seancorfield20:08:25

"Provably correct" is definitely undecidable tho'. "Mostly correct" is tractable.

beoliver20:08:00

seems reasonable, although I wonder if it is the macros or the calls to java that would make it so. I can imagine most expressions where the user calls out java would fall into the "I'm going to assume that the world has changed"

beoliver20:08:48

I guess that anything that is not the same object can not be said to be equal for eternity. Even with a regex, perhaps the reference to one of them was changed etc.

seancorfield21:08:47

Well, Java's Matcher is stateful as I recall so it has to use non-equal objects. A bit surprised about Pattern but maybe it's also stateful (ages since I dug into that low level).

seancorfield21:08:24

As for var renaming, to be honest, if I do a refactoring that is just a renaming, I'd probably still want my tests to be re-run -- just to be sure.

seancorfield21:08:06

And then of course there's always the question of "Why is your test so expensive?" so I might find ways to make the test cheap enough that I don't care if it runs all the time.

beoliver21:08:23

I must admit that the genesis for this case comes from the fact that tests for our project take me between 5 and 30 mins to run (lots of db access) while for the rest of the team they are consistently fnished after 5. Thought I could be smart (although I appreciate that this is not fixing the problem!) On the other hand I am thinking about a masters thesis... as I am working with clojure I thought it could be an interesting space (static analysis, code/project/complexity managment etc)

pwrflx20:08:42

Is there a way to see what ring middleware is configured in a runtime way? to my surprise, a middleware is in use, which I've not configured myself, and I'm curious where/how it got included

noisesmith20:08:13

usually people have something like wrap-defaults that throws a bunch of middlewares onto your app

noisesmith20:08:39

because functions are opaque, and middleware each return a new function, analyzing the middleware based on the runtime value of handler would be tedious (involves checking which namespace the function was made in, figuring out where in that ns the middleware was defined, then figuring out who called it and where the inner function came from etc.)

pwrflx20:08:01

yes exactly.. I'm surprised why middleware was designed in this way. Having a bit more structure would make it less error prone IMHO. At the moment it is just a pile of higher order functions on top of each other.

noisesmith20:08:24

this is why pedestal interceptors were invented btw

pwrflx20:08:07

I'll take a look at that! thank you

fedreg22:08:37

Hi all, I can't seem to figure out how to define a value as a valid schema as per the plumatic/schema library. Can anyone familiar with the library give me a hand? I need an tuple that takes an array of variable numbers of keywords or ints and a string. So: [[:keyword Int :keyword ....] "string"] Example: [[:users 0 :names] "Steve"] Thanks for any help!

noisesmith22:08:14

@fedreg that would be

[(s/one [(s/one :keyword "explanation of this keyword")
         (s/one Int "explanation of this int")
         (s/one :keyword "another explanation")]
        "explanation of this vector")
 (s/one String "explanation of this string")]
(or something a lot like it)

noisesmith22:08:39

as you can probably see, schema doesn’t really like the usage of heterogenous vectors, and pushes you toward hash-maps which are much more elegant to specify

noisesmith22:08:19

also, I have no idea what the .... in your example stands for so I ignored it

noisesmith22:08:26

but you can probably extrapolate

fedreg22:08:45

@noisesmith Awesome! Thank you!! The .... just meant there could be more keywords or ints (it's a path) but I can definitely work with your example. Thanks again!

noisesmith22:08:18

yeah- if they are arbitrarily mixed with no pattern you probably want something more like [(s/either Keyword Int)] to describe the whole collection

noisesmith22:08:43

or s/conditional with cases for matching each

fedreg22:08:14

I think s/either will do it. Thanks!

cjhowe23:08:17

hi, i'm trying to connect to my database with clojure.java.jdbc, and get-connection keeps throwing No suitable driver found for jdbc:, where my DB is tracer. i'm not really a java person and i have no idea how to solve this, does anyone know what the issue is?

ghadi23:08:12

@cjhowe do you have the postgresql dependency defined in your project?

[org.clojure/java.jdbc "0.7.0"]  ;; sql library
                 [org.postgresql/postgresql "42.1.4"] ;; database driver
                 [com.zaxxer/HikariCP "2.6.2"] ;; connection pool

ghadi23:08:37

that's an example for leiningen ^

ghadi23:08:02

the connection pool is optional, and you have to set it up manually, but the driver is required

ghadi23:08:18

btw, I find it easier to create a JDBC "DataSource" and then pass it to clojure.java.jdbc with {:datasource the-ds} as the connection map. DataSources are kinda like connection factories.

ghadi23:08:15

I've been working on a us gov patient matching competition, and I instantiate my connection pooling datasource like so: {:datasource (-> "resources/db.properties" HikariConfig. HikariDataSource.)}

ghadi23:08:41

i use postgres for the matching database

ghadi23:08:22

my db.properties looks like this:

dataSourceClassName=org.postgresql.ds.PGSimpleDataSource
dataSource.user=postgres
dataSource.password=REDACTED
dataSource.databaseName=pmc
dataSource.portNumber=5432
dataSource.serverName=localhost

ghadi23:08:06

I don't use any clj wrapper for the Hikari connection pool. Just the tiny little bit of interop i already pasted above

ghadi23:08:36

i don't need a clojure library just to call a constructor

cjhowe23:08:52

oh, i was going to add hikari-cp soon

cjhowe23:08:45

i was considering using heroku so i would have to get the DB connection string from an environment variable

ghadi23:08:53

that works. you can pass the postgres database url directly to the HikariConfig. Untested:

(-> (doto (HikariConfig.)
      (.setJdbcUrl (System/getenv "DATABASE_URL"))
      (.setPasswordOrWhatever foo)
  (HikariDataSource.))

juanjo.lenero23:08:26

Hi, I’ve been learning clojure for the past few weeks.

juanjo.lenero23:08:07

Two of the most recent tutorials (one for backend with pedestal, the other one for front end with reagent) are using boot instead of lein.

juanjo.lenero23:08:35

Is the community moving towards boot? Is everything that is possible with boot possible with lein?

juanjo.lenero23:08:49

Are they the same thing? Do I need to learn both of them?

ghadi23:08:44

They're in the same category. boot takes a more library and code-based approach to scripting a build. It is newer. There is less learning material available for boot, but the good people #boot are very responsive. lein is older and stabler, and takes a declarative approach. It's a bit slow and despite some design warts, works well.

ghadi23:08:24

I would refer to the yearly State of Clojure surveys to see if there is any community motion, but I don't think there is an en masse migration

juanjo.lenero23:08:42

thanks for the comments

juanjo.lenero23:08:51

which one would you recommend to newcomers?

cjhowe01:08:37

i used boot to start, if you're somewhat experienced with functional languages i'd definitely recommend it

ghadi23:08:22

but if you do a lot of clojurescript stuff, maybe boot.

ghadi23:08:28

it's a coin toss really

juanjo.lenero23:08:08

Yea it seems that way, I guess I’ll bite the bullet and setup boot since that’s what the tutorials use

ghadi23:08:30

There is a third option emerging that is distinctly not in the same category as lein and boot (build tooling) but in the smaller dependency management category, and that is the new tools.deps + clj launcher

juanjo.lenero23:08:30

and disregard everything else until I gain more experience in clojure

ghadi23:08:40

heh. you'll go far here.

ghadi23:08:27

clj is a little bash script that wraps tools.deps. All it does is fetch dependencies, shove them on a classpath and launch a clojure REPL

ghadi23:08:14

it's functionally equivalent to java -cp $(lein classpath) clojure.main ... with the middle subshell cached intelligently

ghadi23:08:32

I think when that hits Stable, it will be good enough for beginners.

ghadi23:08:45

It is not build tooling/release mgmt/packaging, etc.

juanjo.lenero23:08:50

coming from node I need to read up on this classpath thing, in nodejs every dependency was shoved inside a folder in the projects directory

ghadi23:08:40

a classpath just a bunch of directory roots or jar files that contain the necessary code.

ghadi23:08:09

when Java or clojure needs to load or link a class, it searches through those roots.

juanjo.lenero23:08:37

so when you declare deps in boot/lein, they download them to your project directory, add each of them to the classpath and then pass it as an argument to java when running clojure?

ghadi23:08:59

essentially, yes.

ghadi23:08:13

they fetch them into $HOME/.m2 though, not your working directory

juanjo.lenero23:08:27

got it, do lein/boot come with a different repl? or is the repl independent from those tools?

ghadi23:08:36

yeah, unfortunately