Fork me on GitHub
#clojure
<
2019-09-16
>
ahungry04:09:53

When a package is published on clojars, does it tend to just be the jar that gets uploaded? or the clojure source itself if it's available? I'm trying to be more considerate of old JRE users (those who still may be on java 8 ) when building a thing for distribution. If I swap between java versions locally, must i make sure to always switch to java 8 before uploading with something like lein ?

sogaiu04:09:11

isn't the source typically included in the jar?

hiredman04:09:07

It is a bad idea to aot compile libraries

ahungry04:09:54

cool, so, if my library does not specify any "aot" in the lein project.clj, its safe to assume lein isn't compiling anything for me at all when I deploy the lib, its just pushing the source as I'd hoped

andy.fingerhut08:09:38

It is pretty easy to check a .jar file, which is pretty much just a zip archive, using a command like unzip -v foo.jar, either after downloading one, or before uploading one to Clojars, if you are curious what files are inside of it.

andy.fingerhut08:09:15

At least on Mac and Linux systems. On Windows you can probably rename the file to have .zip suffix and double click on it to see the contents, and dozens of other ways.

vemv05:09:25

> It's "OK" to do AOT on everything as the last step when building an uberjar can it have a drawback, even in the context of uberjars? (not sure myself)

plexus06:09:13

@vemv unless you're doing stuff which you shouldn't be doing like redefining vars at runtime I think it should be fine

👌 4
vemv06:09:47

thanks! yes, I haven't had a bad experience with it (web deployment) so far, but I fear I could hit an obscure issue someday.

Iwo Herka07:09:40

Hello, are you aware of any good guides on the design of Clojure compiler? The structure of the projects, key components, getting around, algorithms used, this kind of stuff. Much appreciated, thanks.

Thomas Deniffel09:09:07

Unfortunately not. I'm sure you are aware, that the source code is available on Github? Analyzing it could bring you further.

Iwo Herka09:09:30

Yes, of course. The codebase is large though so I thought to start with guides.

Thomas Deniffel16:09:11

I had to think about your question when watching this video from Rich Hickey. I hope it helps https://youtu.be/wASCH_gPnDw?t=1381

Thomas Deniffel16:09:01

Also, chapter 4 of SICP could help

Iwo Herka08:09:01

That's great, thank you!

Iwo Herka07:09:05

(Besides reference docs)

Michael08:09:19

hello, anybody knows what is the last version of clojure to support java 7?

andy.fingerhut09:09:30

That is the same source and latest info I know of. It was not until Clojure 1.10 was released that Clojure required Java 8 or later.

Michael09:09:31

thank you very much both, i suspected such because there was no other mention of requirement until 1.10 but wasn't 100% sure 🙂

andy.fingerhut09:09:33

There are some even older versions of Clojure that mention minimum Java requirements, but you have to go back to Clojure 1.6 in the change log before you find that it requires Java 6 plus a special package, or Java 7.

dazld09:09:40

did anyone try making a prettier plugin for clojure?

dazld09:09:56

there’s a java one here, for comparison: https://github.com/jhipster/prettier-java

dazld09:09:50

zprint is working great for me! took a little hunting to find a nice way to make it work in intelliJ - if anyone is searching for how to transform selected text in place via a command that works with streams, then look for a plugin called pipeprofen

hjrnunes10:09:42

Hi. I'm struggling to find a convenient way of calling instrumentation for my tests. I mainly run them with lein test. I've seen people around recommending loading (st/instrument) in :injections but this has never worked for me. I can see the namespace is loaded, but instrumentation never happens. It just doesn't. The only way I can make it work is to sprinkle (st/instrument) over all my test namespaces... Does anyone have an instrument config that actually works with :injections? Or some alternative way of setting this up? Thanks

vemv12:09:59

https://github.com/jeaye/orchestra offers enabling instrumentation globablly https://github.com/borkdude/respeced seems more fine-grained. Personally I have reservations about the whole instrumentation approach, which is why I authored https://github.com/nedap/speced.def/ . It's been a success where I work.

hjrnunes12:09:23

Yep, I understand orchestra offers that. My point is where do people call instrument. I'd like to be able to call it once, and have all my test runs instrumented. I've only been able to do this by calling instrument in every test namespace.

hjrnunes15:09:03

Ha! But that is using circleci's test-runner... I have it as a plan B, but ideally I'd find a solution using vanilla clojure.test.

vemv15:09:06

Yeah, I also have ci.test only "on the radar" in case someday I really need it. Seems well crafted anyway

emccue12:09:37

Is there a way to have a double "default" for multimethods

emccue12:09:57

like if i dispatch on [(type x) (type y)]

emccue12:09:00

something like

emccue12:09:06

[Integer :default]

emccue12:09:18

[:default String]

vlaaad13:09:51

2. via custom hierarchy hack:

(defmulti multi-type (fn [a b]
                       [(type a) (type b)])
  :hierarchy (atom {:ancestors (constantly #{:default})}))

(defmethod multi-type [Number :default] [_ _]
  [Number :default])

(defmethod multi-type [:default Number] [_ _]
  [:default Number])

(multi-type 1 "a") ; => [java.lang.Number :default]
(multi-type "a" 1) ; => [:default java.lang.Number]
(multi-type 1 1)
; Syntax error (IllegalArgumentException) compiling at (editor_extensions.clj:51:1).
; Multiple methods in multimethod 'multi-type' match dispatch value: [java.lang.Long java.lang.Long] -> [:default java.lang.Number] and [java.lang.Number :default], and neither is preferred

vlaaad13:09:20

this is a hack because it uses hierarchy implementation and usage details and there is no promise it will work that way forever

dominicm13:09:56

Although the hierarchy code is clearly coded to support this.

plexus13:09:40

exactly, AFAIK this is a feature, not an implementation detail

vlaaad13:09:28

well, isa? docstring says hierarchy should be obtained via make-hierarchy

vlaaad13:09:46

not should, *must*

👍 4
vlaaad13:09:36

(doc isa?)
-------------------------
clojure.core/isa?
([child parent] [h child parent])
  Returns true if (= child parent), or child is directly or indirectly derived from
  parent, either via a Java type inheritance relationship or a
  relationship established via derive. h must be a hierarchy obtained
  from make-hierarchy, if not supplied defaults to the global
  hierarchy

vlaaad13:09:59

derive, which also uses hierarchy, states the same:

clojure.core/derive
([tag parent] [h tag parent])
  Establishes a parent/child relationship between parent and
  tag. Parent must be a namespace-qualified symbol or keyword and
  child can be either a namespace-qualified symbol or keyword or a
  class. h must be a hierarchy obtained from make-hierarchy, if not
  supplied defaults to, and modifies, the global hierarchy.

vlaaad13:09:19

so all hierarchy-related functions imply that hierarchy's shape is implementation details

plexus13:09:29

right, how about this

(defmulti multi-type (fn [& args] (mapv type args)))

(defmethod multi-type [Number Object] [_ _]
  [Number :default])

(defmethod multi-type [Object Number] [_ _]
  [:default Number])

(multi-type 1 "a") ; => [java.lang.Number :default]
(multi-type "a" 1) ; => [:default java.lang.Number]
(multi-type 1 1)
                                        ; Syntax error (IllegalArgumentException) compiling at (editor_extensions.clj:51:1).
                                        ; Multiple methods in multimethod 'multi-type' match dispatch value: [java.lang.Long java.lang.Long] -> [:default java.lang.Number] and [java.lang.Number :default], and neither is preferred

💯 4
plexus13:09:20

what I meant by "feature" is that isa? clearly is meant to support vectors like this, although the docstring doesn't mention it. That would be worth creating a ticket for I think.

mpenet13:09:47

I think he meant that building a custom hierarchy like this (atom {:ancestors (constantly #{:default})}) and abusing invoke on its vals is a hack

mpenet13:09:04

otherwise the rest is "legal"

plexus13:09:26

yes, I get that

mpenet13:09:53

custom hierarchies are awesome. Little under-used gem of the clojure language

plexus13:09:31

they really are, which is why I did a whole lambda island episode about them 🙂

✌️ 4
plexus15:09:02

@alexmiller should the behavior of isa? on vectors be documented? I can make a ticket and suggest a patch.

dominicm15:09:20

fwiw It's documented on the multimethods page on http://clojure.org @plexus > isa? works with vectors by calling isa? on their corresponding elements:

Alex Miller (Clojure team)15:09:06

seems reasonable to doc that in isa? too

Eduardo Mata15:09:44

Hey guys, I am trying to solve a Blocking I/O problem with ETL tool I am building. I posted my problem in reddit. https://www.reddit.com/r/Clojure/comments/d52c4l/blocking_io_in_clojure/

Eduardo Mata15:09:53

I hope someone could help me out

Chico15:09:09

Does anyone know if there is a coverage plugin using the openclover standard

FiVo17:09:21

Is there a clojure reader that gives me the AST with location information of the tokens?

ghadi17:09:53

tools.reader is a reader that gives you that (but isn't really an AST)

vlaaad17:09:05

@finn.volkel including stuff like comments?

ghadi17:09:06

tools.analyzer can take in read forms and return an AST

Joe Lane17:09:36

@finn.volkel SourceLoggingPushbackReader will give you all the location information of the tokens but they will be forms, (like (defn foo [a b] (+ a b)), not the AST. Not sure if that is helpful for you.

Joe Lane17:09:50

Its in the tools.reader project

Joe Lane17:09:38

The loc info is attached to each form as metadata

andy.fingerhut17:09:42

IIRC even tools.analyzer won't give you location info for things that cannot have metadata, e.g. keywords, strings, and comments are not represented at all. It does have location information for all lists, vectors, sets, maps, and symbols, which can have metadata, and that metadata contains line/column info.

andy.fingerhut17:09:32

https://github.com/xsc/rewrite-clj is a library that enables reading Clojure code and data in a way that preserves whitespace and comments, yet make changes to it after reading it, so that it can be printed in a way that is textually as close as you want to what you read. Different kinds of use cases for that than what you want, perhaps.

David Rueda18:09:58

Hi there! I would like to get a remote position as a Clojure developer. Would someone like to give me some hints?

seancorfield18:09:54

#jobs-discuss would be a good place for that conversation @davd33

peterdee20:09:05

Hi! I have a luminus project for which I’m trying to make an uberjar. The jar builds with one warning:

WARNING: var: clojure.string/replace-with is not public at line 327 target/cljsbuild/public/js/cuerdas/core.cljc
But it doesn’t run:
java -jar nb-agent-0.1.0-SNAPSHOT.jar
Exception in thread "main" java.lang.NoClassDefFoundError: clojure/lang/Var
Any idea what that might be about or how to investigate it?

Alex Miller (Clojure team)20:09:56

sounds like nb-agent does not include compiled Clojure itself (as you'd expect in an uberjar)

noisesmith20:09:22

@peterd when you make an uberjar, lein creates two jars, the one with your project itself, and the uberjar whiich includes that plus all deps

noisesmith20:09:34

usually by default the one you want has standalone in the name

noisesmith20:09:23

it makes both because the one for your project alone is considered a pre-requisite for the uberjar, but this is a common tripping point

Alex Miller (Clojure team)20:09:47

that sounds like a correct analysis to me

peterdee20:09:16

Yup! My luminus project renames the jars, and I didn’t think to look at the other one! Thanks!

roninhacker20:09:31

Is there a way to use spec on a map without mandating that the kw and spec have the same name? Like {:sponsor value-conforming-to-:person-spec}?

seancorfield20:09:41

@dchristianbell If you're working with unqualified keys, probably the simplest workaround would be an alias spec:

(s/def ::person-spec ,,, whatever ,,,)
(s/def :person/sponsor ::person-spec)
(s/def ::sponsor-map (s/keys :req-un [:person/sponsor ,,,]))

seancorfield20:09:09

That key will be :sponsor but the spec will be :person/sponsor which is aliased to ::person-spec.

roninhacker20:09:40

Okay, great, thank you.