Fork me on GitHub
#clojure
<
2018-03-20
>
schmee00:03:29

@pablore no, it is sort of like a struct in C, less indirection and higher performance than objects for certain use-cases

qqq00:03:50

Is https://stackoverflow.com/questions/3132931/mutable-fields-in-clojure-deftype up to date? To make a field mutable, I need to mark it volatile

schmee01:03:15

you can use ^:unsychronized-mutable as well

pablore02:03:25

@ghadi well clojure’s data structures are not only inmutable, they are also persistent. And because of that I find it difficult to implement them with these new “values”.

grzm02:03:09

I seem to be loosing the :p argument somewhere along the way here:

(defprotocol F
    (-f [this a & r]))

  (defn f [this a & r]
    (prn [:f {:this this :a a :r r}])
    (apply -f this a r))
  
  (defrecord Fer []
    F
    (-f [this a & r]
      (prn [:-f {:this this :a a :r r}])
      {:a a :r r}))

  (def fer (->Fer))
  
  (f fer :x :p {:args :foo})
  ;; => {:a :x, :r {:args :foo}}

  ;; stdout
  ;; {:this #user.Fer{}, :a :x, :r (:p {:args :foo})}
  ;; {:this #user.Fer{}, :a :x, :r {:args :foo}}

grzm02:03:14

Looks like it's happening when the f wrapper function calls the -f protocol method implementation. Any ideas what's going on?

grzm02:03:45

Compare with using only functions: :p isn't lost:

(defn -g [this a & r]
    (prn [:-g {:this this :a a :r r}])
    {:a a :r r})

  (defn g [this a & r]
    (prn [:g {:this this :a a :r r}])
    (apply -g this a r))

  (g :this :x :p {:args :foo})
  ;; => {:a :x, :r (:p {:args :foo})}

  ;; stdout
  ;; [:g {:this :this, :a :x, :r (:p {:args :foo})}]
  ;; [:-g {:this :this, :a :x, :r (:p {:args :foo})}]

ghadi02:03:27

protocols do not support varargs

ghadi02:03:20

you've accidentally defined a protocol that takes three arguments -- one of them is named & - if you printed & within the protocol implementation, you'll find your missing argument

grzm02:03:20

Interesting. And surprising. Happen to have a reference?

ghadi02:03:06

worth an enhancement ticket to add a sentence to the defprotocol docstring

grzm02:03:39

Indeed. And to spread the word far and wide.

dpsutton04:03:59

i think that's one of the differences in clj/cljs. because of the host language cljs

dpsutton04:03:20

does clojure guarantee evaluation order of its args?

arrdem06:03:44

Does lein not inject :test dependencies when you run a REPL? I thought it did, but I’m not able to explain how looking at the implementation of the repl task and my project’s profiles via show-profiles.

xtreak2906:03:27

I don't think running repl task will inject :test dependencies as I can see from the below. I might be wrong though . Maybe you can try lein with-profile test,repl repl (Not verified) > Some tasks automatically merge a profile if specified. Examples of these are the :test profile, when running the test task, and the :repl profile, when running the repl task. Please note that putting things in the :test profile is strongly advised against as it can result in tests which can't be run from the repl. https://github.com/technomancy/leiningen/blob/master/doc/PROFILES.md#task-specific-profiles

arrdem06:03:35

Ah okay good

xtreak2906:03:37

You're welcome

xtreak2906:03:08

How is Clojure tested with JDK 10 which is on release candidate phase ? I can see reports of the Kotlin compiler breaking on JDK 10 early access releases : https://github.com/junit-team/junit5/issues/1169

bronsa09:03:13

it’s not

xtreak2907:03:21

Seems like there is a test case failing. Filed : https://dev.clojure.org/jira/browse/CLJ-2337

alexmiller13:03:43

fyi, this is just a fragile test, not an issue with Clojure and Java 10

xtreak2909:03:03

@bronsa Thanks. My bad "JDK 10" didn't bring up any tickets in JIRA search. I will close it then.

bronsa09:03:21

nw, jira search sucks

Shantanu Kumar11:03:54

When a macro contains ~*ns*, does it imply that we are forcing it to evaluate at that point of time?

xtreak2911:03:42

I think you are right but I am curious if there are any exceptions

$ clj
user=> (defmacro foo [f & rest] `(str ~*ns*))
#'user/foo
user=> (foo 1)
"user"
user=> (ns spam)
nil
spam=> (user/foo 2)
"spam"

Shantanu Kumar11:03:02

I found its usage in clojure/tools.loogging and want to understand what are its cost implications

xtreak2911:03:54

Seems like a nice way to print the current namespace useful for logging. I also found a similar quoted usage in core : https://github.com/clojure/clojure/blob/master/src/clj/clojure/core.clj#L1828

mpenet11:03:39

what's the go to jdbc/postgres driver these days?

tatut11:03:50

yesql/jeesql/hugsql

tatut11:03:55

and specql for the adventurous

mpenet11:03:52

I'd rather use something quite low level with a handful of basic functions

tatut11:03:09

if clojure.java.jdbc seems bloated (I don’t think it is), then java interop is reasonably easy way to do it

ikitommi11:03:01

hugsql & funcool/clojure.jdbc

mpenet11:03:45

funcool almost qualifies, but no reducible resultsets make me sad

ikitommi12:03:36

it’s time to diy? 😉

mpenet12:03:16

not again ...

ikitommi12:03:54

haha, maybe PR to funcool? it’s otherwise kinda nice.

mpenet12:03:55

I might just fork/publish squee and try that

mpenet12:03:36

yep, code is nice/simple and might just be what I am looking for

mpenet12:03:28

I followed some of its design for another lib I authored, so I am quite familiar with it too

mpenet11:03:31

squee seems quite nice/simple, clojure.java.jdbc seems like an obvious contender but it seems a bit bloated at first glance, maybe it doesn't matter

Shantanu Kumar11:03:15

(Shameless plug) I wrote Asphalt https://github.com/kumarshantanu/asphalt to use SQL “in anger”. We are using it at Concur in production for over two years with MySQL and MS-SQL. Has no dependency.

mpenet11:03:59

interesting, thanks

mpenet11:03:01

well squee is not even on clojars 😞

Shantanu Kumar11:03:13

@mpenet You might get more responses on the #sql channel.

petr.mensik11:03:56

Has anyone seen similar exception to this? ERROR [compojure.api.exception:286] - clojure.pprint.proxy$java.io.Writer$IDeref$PrettyFlush$4923d848 cannot be cast to clojure.pprint.PrettyFlush Application is packaged as uberjar (tried both {:aot all} and only namespace with main), it works normally on localhost however it produces errors like this on AWS. Application works correctly, however it replaces original expcetion with this one on error. I tried to remove various dependencies and played with AoT but nothing so far helped 😕

petr.mensik12:03:06

I have read it however dropping to 1.7 doesn't sound like a good option 🙂

pesterhazy12:03:42

@petr.mensik any particular reason why you're AOT'ing? That can lead to all sorts of trouble

petr.mensik12:03:53

@pesterhazy I ended up with :profiles {:uberjar {:aot [spc.core]} which is default - I thought that namespace containing the -main has to be AoTed

pesterhazy12:03:21

another thing you can try is java -cp uberjar.jar clojure.main -e '(do (require 'myproj.main) ((resolve 'myproj.main/-main'))'

pesterhazy12:03:53

I think that should work right?

pesterhazy12:03:03

in which case you shouldn't have to AOT anything

petr.mensik12:03:38

Ok, I can try that, thanks

pesterhazy12:03:11

updated the snippet ^^ let me know if it works

petr.mensik12:03:38

And how do I workaround the fact that lein uberjar adds implicit AoT for the :main?

petr.mensik12:03:57

Warning: specified :main without including it in :aot. 
Implicit AOT of :main will be removed in Leiningen 3.0.0. 
If you only need AOT for your uberjar, consider adding :aot :all into your
:uberjar profile instead.
Compiling spc.core

petr.mensik12:03:38

@pesterhazy Ok, I removed the :main from project.clj and I am able to build it. However java -cp mayjar.jar clojure.main -e '(do (require [spc.core]) (resolve 'spc.core/-main'))' yields a Exception in thread "main" java.lang.ClassNotFoundException: spc.core, compiling:(NO_SOURCE_PATH:1:5)

pesterhazy12:03:12

@petr.mensik there's an apostrophe missing before the ns

pesterhazy12:03:45

`"(do (require 'spc.core) ((resolve 'spc.core/-main)))"

pesterhazy12:03:11

note the doulbe parentheses around resolve

petr.mensik12:03:59

@pesterhazy ok, it works locally so I'll let you know if it works on the AWS as well. However it's still not that nice since I have to change default run command on all instances 😕

petr.mensik12:03:15

But definitely thanks!

pesterhazy12:03:06

agreed. The other way should work as well (only aot a single ns)

grav12:03:08

Has anyone used an API that consumes com.fasterxml.jackson.databind.JsonNodes? I’m trying to figure out if an existing clj-library (like cheshire or jsonista) can produce such one from Clojure datastructures.

miro13:03:59

hello guys, a quick question about classloaders and require, maybe somebody here played with it: Even though I add a dependency to classpath with pomegrenate, the require of the dependency still fails... It IS definitely on the classpath of that given classloader. I tried tweaking *use-context-classloader* but it seems to make no difference. What am I missing? (Tried this so far only in repl, not sure whether that may be relevant?)

(let [new-cl (-> (Thread/currentThread)
                (.getContextClassLoader)
                (clojure.lang.DynamicClassLoader.))]
 (cemerick.pomegranate/add-dependencies :coordinates [['com.draines/postal "2.0.2"]]
                                       :classloader new-cl)
 (.setContextClassLoader (Thread/currentThread) new-cl)
 (require 'postal.core))
FileNotFoundException Could not locate postal/core__init.class or postal/core.clj on classpath.  clojure.lang.RT.load (RT.java:449)

dominicm13:03:10

it's possible that clojure doesn't use the context classloader. I'm not certain though. Clojure is a bit funky with classloaders.

miro13:03:53

I think by default it should be using the context classloader... will try to tag @cemerick, maybe he's around?

miro14:03:46

ok, after some poking in the RT.class it seems that this really might be REPL related:

public static ClassLoader baseLoader() {
        return Compiler.LOADER.isBound()?(ClassLoader)Compiler.LOADER.deref():(booleanCast(USE_CONTEXT_CLASSLOADER.deref())?Thread.currentThread().getContextClassLoader():Compiler.class.getClassLoader());
    }
I guess in REPL the loader is bound hence it wont ever check *use-context-classloader*. So will have to test this in uberjar and to see whether it works...

jholkeboer13:03:31

Does anyone have experience using clojure.core/hash as a way to give a unique ID to maps? What are the pros and cons of using that vs something like sha256? I was surprised how few numbers are in the clojure hash and it seems like collisions would be much more likely, no?

jholkeboer13:03:04

My use case is I have a bunch of JSON objects and i want to detect dupes, but avoid false positives

alexmiller14:03:10

Java hashes are constrained to be 32-bit integers

alexmiller14:03:58

hash collisions are of course possible (the murmur hash changes in 1.6 have made this less common)

alexmiller14:03:19

I would not use it as a way to obtain unique IDs (since they aren’t necessarily unique)

mpenet14:03:26

they can also change in between jvm restarts right?

mpenet14:03:00

replikativ has a subproject that deals with this

alexmiller14:03:07

well they should probably be the same but would potentially vary across clojure versions.

mpenet14:03:48

or jvm vendors

alexmiller14:03:38

well, clojure controls the collection hashes and I think the jvm spec controls primitive value hashes so that is probably not the case

JJ15:03:32

@alexmiller would it be inadequate to add the '-m -M .clj' options to rlwrap for the 'clj' script in the repo? those flags fire up your $EDITOR with ctrl-^

alexmiller15:03:17

did you mean .clj there?

JJ15:03:37

correct

alexmiller15:03:47

those options don’t work for me on mac at least

alexmiller15:03:05

I don’t particularly want to lock in too hard to rlwrap as I’m hoping to actually integrate rebel-readline instead

dominicm15:03:43

@alexmiller what version of rlwrap is on a mac?

alexmiller15:03:57

depends on whose mac you mean :)

dominicm15:03:14

😛 on yours I guess

alexmiller15:03:29

whatever brew installs :)

JJ15:03:00

@alexmiller ok, haven't tried it in a mac, works fine on linux, weird it doesn't work in osx though, didn't know about rebel-readline, fair enough

dominicm15:03:00

okay, so in theory the -M .clj should work.

alexmiller15:03:09

looks like I have 0.43

alexmiller15:03:34

rlwrap: warning: on this system, the getopt() library function doesn't
grok optional arguments, so '-M' is taken as an argument to the -m option
Is this what you meant? If not, please provide an argument

alexmiller15:03:52

so I think that’s about the -m part which expects an argument

dominicm15:03:13

yeah, me too. I don't understand why it would be -m -M, only -M makes sense.

JJ15:03:55

@alexmiller would rebel-readline be optional? or at least opt-out, don't want to slow down that start-up time 😉

alexmiller15:03:07

still needs evaluation. why do you think it’s slower?

alexmiller15:03:33

I would happily trade a small amount of time for the vastly increased functionality

JJ15:03:55

yes, was just about to say that I don't really know how much overhead it would bring, just that is another dependency (which has its own dependencies, jline) that is needed for boot up

alexmiller15:03:17

that doesn’t make it any slower necessarily

JJ15:03:11

ok, these are all very nice features anyway 😉

dominicm15:03:11

@alexmiller Try -m' \ ' -M ".clj" that seems portable

alexmiller15:03:32

@devicesfor you can try it with clojure -Sdeps "{:deps {com.bhauman/rebel-readline {:mvn/version \"0.1.1\"}}}" -m rebel-readline.main yourself (but ignore the first timing as it has to download and cache deps)

alexmiller15:03:19

note that b/c of how it’s being started there are some inefficiencies that can be reduced - for me I see ~2 seconds to start a repl with clj and maybe 7 seconds with rebel-readline

alexmiller15:03:07

consider that an upper bound - if included and packaged with clj, I’m sure this can be reduced

alexmiller15:03:11

given what rebel-readline gives you (multi-line editing, completion, doc arglist and source inline), it’s pretty useful

dominicm15:03:18

@alexmiller I'm sure clojure 1.10 will bring that down too 🙂

dominicm15:03:09

I thought there was some performance improvements planned for 1.10?

alexmiller15:03:54

oh, there are other ideas in work but I’m not sure they would affect this necessarily

Bravi16:03:50

;; lazy, will only traverse once
 
(def colors ["red" "green" "blue"])
 
(println
  (map #(str % "foo") (map first colors))
;; => ("rfoo" "gfoo" "bfoo")
can someone please help me understand why is this being traversed once?

Bravi16:03:24

I assumed colors had to be a list instead of vector, for it to be a lazy seq?

JJ16:03:12

@bravilogy what result do you expect?

Bravi16:03:36

I would’ve thought that there would be 2 iterations happening

Bravi16:03:59

compared to js equivalent

Bravi16:03:42

oh I’m not talking about the result, but rather - why will it only traverse once?

JJ16:03:30

asked about the result cause I'm trying to understand what you want to accomplish

hiredman16:03:43

map always returns a lazy seq

Bravi16:03:22

@hiredman yes, map returns a lazy sequence. so when (map first colors) runs, doesn’t it iterate over colors vector to generate that lazy sequence?

pauld16:03:15

@bravilogy Creating a lazy sequence from a lazy sequence doesn't require traversal.

pauld16:03:40

See the code snippet above for the equivalent.

Bravi16:03:10

@pauld so the second (outer) map doesn’t actually iterate over the lazy sequence generated by the first one?

Bravi16:03:37

that snippet makes sense why there would be just 1 iteration

Bravi16:03:58

but I don’t get why there’s also 1 iteration in the example I posted

JJ16:03:03

@bravilogy there are twoo, inner and outer map

Bravi16:03:06

I would’ve thought there’d be two

the2bears16:03:43

@bravilogy evaluate (map first colors) in your REPL

the2bears16:03:11

Then, take the result and evaluate it with (map #(str % "foo") ...)

the2bears16:03:19

That's what is happening.

JJ16:03:26

@bravilogy why do you think there is only one?

Bravi16:03:39

because the comment says so @devicesfor

Bravi16:03:14

under ‘lazy sequences’

Bravi16:03:47

@the2bears I think I’m not explaining correctly which part I don’t understand 😄 I know what the result would be and how 2 maps work but what I don’t get is that the comment in there - why will it only be traversed once

hiredman16:03:12

because you don't traverse the vector to create a lazy seq

pauld16:03:37

@bravilogy to understand you might have to look at the code of (map) in clojure. But the key is just knowing you can create a lazy sequence from a lazy sequence without realizing / traversing the first one.

hiredman16:03:58

if you are familiar with iterators, think of it as a stack of iterators

hiredman16:03:07

calling seq on the vector returns the iterator over the vector

hiredman16:03:33

map takes an iterator, and returns an iterator that calls the mapped function on each value as you take it from the iterator

Bravi16:03:38

so it’s kinda like a transducer

Bravi16:03:56

in a sense of creating stacks

hiredman16:03:16

sure, but you are generating intermediate seqs as you go, where transducers don't do that

Bravi16:03:33

aah ok that makes more sense now

pauld16:03:37

That's why my clip above was more or less equivalent to your code.

pauld16:03:24

My syntax may have been off a bit.

pauld16:03:39

maybe no # required.

Bravi16:03:18

no that’s fine, I think I understand now. so basically that example is sort of similar to

(take 5 (range))

Bravi16:03:54

in a sense that the inner map will generate a sequence that will be ‘fed’ to the outer map and that’s what will actually ‘realise’ it

pauld16:03:20

and it only get's realized when print is called on it.

Bravi16:03:40

damn, that’s cool

JJ16:03:49

@bravilogy oh I see, yes colors is only iterated once, but your example has two iterations

Bravi16:03:21

so if I don’t call println, then there’s basically nothing happening

Bravi16:03:38

we just have some sort of a sequence that’s waiting for something to happen

JJ16:03:41

correct, unless you are in the repl

pauld16:03:16

lazy sequences can sometimes be confusing as you may get surprised by when the sequence is evaluated or realized.

pauld16:03:36

yes, the repl has an implied print on everything.

Bravi16:03:57

would it be the same result if I was to simply change it to

(def my-seq (map #(str % "-foo") (map first colors)))
(println my-seq)
?

Bravi16:03:46

ok that repl part makes sense now

pauld16:03:08

or if in repl, just 'my-seq' without println.

Bravi16:03:17

and it makes sense why is automatically ‘realising’ the sequence

Bravi16:03:24

yeah that’s exactly what I did there

Bravi16:03:41

thank you all 🙂

Bravi16:03:15

now I’m one step closer to becoming clojurian

mbjarland16:03:48

@alexmiller seems the -Sdeps option is quite new? 4.2s for the rebel-readline on my ubuntu box, 4.8s on a fairly recent mbp

seancorfield17:03:41

@mbjarland The -Sdeps option came in January with TDEPS-19 Add support for command line deps config data

pavani18:03:32

@seancorfield Is there a way to use TemporalAdjusters with joda.time? I am referring to clj-time but I cant find functions for dayOfWeekInMonth and firstInMonth

seancorfield18:03:28

@vellalpavani You'll have to use Java interop to call those. Not everything in Joda Time is exposed directly in clj-time.

pavani19:03:01

@seancorfield Thank you. I will use clojure.java-time.

seancorfield18:03:16

(and, for all sorts of reasons, I'd recommend using Java Time over Joda Time these days -- and looking at clojure.java-time as a wrapper if you don't like Java interop)

Michael Fiano19:03:53

When would it be a good idea to use a StructMap over a Record? The documentation for StructMap says "Most uses of StructMaps would now be better served by records.". What would "most" not cover?

ghadi19:03:14

ignore structs

ghadi19:03:19

they're deprecated

Michael Fiano19:03:41

Ah, I didn't see it say that anywhere.

ghadi19:03:28

"effectively" simple_smile

ghadi19:03:04

structmaps are mostly about optimizing storage, Records can integrate with protocols, and still have optimized storage

Michael Fiano19:03:37

Isn't there an overhead for creating a proper JVM class?

ghadi19:03:47

sure, but all functions do it

schmee19:03:16

even all function invocations, right?

ghadi19:03:33

just definitions

tatyana19:03:47

Hello, I am trying to transform a UTC date string into a Local date string: “2018-03-20T12:40:40Z” -> “3/20/18 8:40am”. I’ve tried various to-local-date-time and unparse-local functions, but I can’t seem to put it together. I’m getting an error:

ClassCastException org.joda.time.DateTime cannot be cast to org.joda.time.ReadablePartial  clj-time.format/unparse-local-date (format.clj:212)
I got it to:
(def local-date (local/to-local-date-time "2018-03-20T12:40:40Z"))
=> #'recruit-app.util.date/local-date
local-date
=> #object[org.joda.time.DateTime 0x311f327a "2018-03-20T08:40:40.000-04:00"]
but then I need a way to reformat it to something readable,
(tf/unparse-local-date (tf/formatter :mysql) local-date)
ClassCastException org.joda.time.DateTime cannot be cast to org.joda.time.ReadablePartial  clj-time.format/unparse-local-date (format.clj:212)

schmee19:03:14

I'm trying to understand locals clearing, I'm looking at the bytecode for this simple function (m is a Java hash map):

(defn put [m k v]
  (.put m k v))
and it has a bunch of this going on:
0  aload_0 [m]
     1  aconst_null
     2  astore_0 [m]
seems like it's unnecessary to clear locals in this case? when is local clearing needed? is it for recur?

gtrak19:03:00

the clearest case for it is holding on to the head of a seq in a binding but passing it in tail position to another function

schmee19:03:48

I saw that thread bronsa but I wasn't sure it was still relevant since it's all the way from 2009

seancorfield19:03:05

@tlomberg Are you wedded to Joda Time (`clj-time`)? If you're on Java 8 or later, the Joda Time folks recommend using Java Time instead, and there's a nice wrapper called clojure.java-time.

seancorfield19:03:15

Here's that parsing / add timezone / formatting using clojure.java-time:

user=> (require '[java-time :as jt])
nil
user=> (-> (jt/zoned-date-time "2018-03-20T12:40:40Z") (jt/with-zone-same-instant "America/Los_Angeles") (->> (jt/format "MM/dd/yy hh:mma")))
"03/20/18 05:40AM"

bronsa19:03:37

@schmee yeah nothing much has changed for locals clearing since then

bronsa19:03:01

there's been a few improvements and it happens in places where it didn't use to but the general principle is the same

tatyana19:03:45

@seancorfield: Thanks, I’ll look into it

schmee19:03:21

@bronsa aight, thanks :thumbsup: I guess I want to follow the PathNodes in the compiler to figure out how it's done?

seancorfield19:03:39

(FWIW, I'm one of the maintainers of clj-time and I just updated the repo to include the notice from the Joda Time website that recommends users migrate to JSR-310 a.k.a. Java Time)

👍 4
qqq21:03:25

Is there any language with Clojure-like syntax and is good for high performance numerical computing?

jgh21:03:46

i think there’s a lib that can do hardware acceleration and stuff for clojure….trying to remember the name of it

qqq21:03:37

neandertheral / clojurcl / clojurecuda ?

jgh21:03:10

not sure if that’s what you’re looking for or not

qqq21:03:40

@jgh: it's a wonderful answer to the question I asked, but not the question I intended to ask, as the cuda/opencl 'kernels' are still not written in clojure 🙂

jgh21:03:47

oh i see

jgh21:03:28

could you make clojure macros that compile to the cuda/opencl kernel language?

jgh21:03:22

eg Apple’s Metal uses LLVM so some enterprising upstart could use a different language than C++ for the kernel language

jgh21:03:10

(btw possibly one of the worst API names ever…at least go uses golang)