Fork me on GitHub
#clojure
<
2017-12-20
>
seancorfield01:12:11

We put Clojure 1.9.0 into production today. We've been on RC builds in production for a while so it was uneventful (as all of our Clojure version upgrades are!).

shaun-mahood02:12:08

Isn't it boring to be on an actual release though? :)

seancorfield02:12:45

I'm already looking forward to 1.10-alpha1!!! 🙂

qqq02:12:26

https://clojuredocs.org/clojure.string/capitalize <-- I can't believe there is a builtin function for this.

seancorfield02:12:07

@qqq Even after seven years of Clojure, I still find new-to-me functions in the core namespaces 🙂

kaosko02:12:57

my jvm is crashing after some time developing. this is a mixed clojure+java projects and I'm using plugins like virgil (to reload java classes). I get the crash log but no core dump even though jvm said it wrote it (probably just need to change location). so.. first question, is this something that is more or less expected or a strong indication of a bug?

seancorfield03:12:52

Sounds very unusual to me, but I don't use Virgil so it may be an issue with that.

seancorfield03:12:22

I've been doing Clojure for over seven years and my experience -- both of the REPL when developing locally and of Clojure in heavy production use -- is that it's rock solid.

kaosko03:12:00

asking because to me this seems suspiciously like the classic PermGen OoM error with plain Java but could also be just my previous experiences. I'm on 1.8 java, the mem consumption doesn't look too bad to the OS but I haven't visualvm'd this yet. I'm new to Clojure but know my java, so I'm not sure whether I should stress out about it at this point or not. This is not in production yet but I really wouldn't like to find out at that time

andy.fingerhut03:12:12

clojure.string/capitalize is a very strange thing to have in Clojure, I agree. It also has a subtle bug. (Hint: Java strings, and thus Clojure strings, are represented in memory encoded as UTF-16)

andy.fingerhut03:12:40

but such corner cases of Unicode are best left for more comprehensive libraries like ICU4J

shawn.wang04:12:55

really hope that DL4Clj could be updated more efficiently.

ihabunek08:12:14

is there something that makes the stack traces a bit more human readable? using vanilla lein run at the moment at least something that highlights the stack lines which are in my code, as opposed to clojure.lang...

flowthing10:12:02

Not sure if Ultra does exactly that, but you could give it a go: https://github.com/venantius/ultra

qqq12:12:43

I'm translating this to Clojure. Is there a amore idiomatic way instead of converting the while loop into a loop-recur?

;;        private static byte[] toByteArray(InputStream inputStream)
;;            throws IOException
;;        {
;;            ByteArrayOutputStream baos = new ByteArrayOutputStream();
;;            byte buffer[] = new byte[8192];
;;            while (true)
;;            {
;;                int read = inputStream.read(buffer);
;;                if (read == -1)
;;                {
;;                    break;
;;                }
;;                baos.write(buffer, 0, read);
;;            }
;;            return baos.toByteArray();
;;        }

It's fine to get either a byteArray or a string as output -- this data won't be too large -- it's the error msg (or stdout) of a very simple process).

New To Clojure12:12:00

@qqq

(do
  (... read ...)
  (while (not= read -1)
    ( ... write ...)
    (... read ...))
  (.toByteArray baos))

New To Clojure12:12:06

I don't think there's do-while in Clojure.

bronsa12:12:00

(doseq [r (take-while #(not= -1 %) (repeatedly #(.read is buff)))] (.write baos buffer 0 r))

qqq12:12:01

according to https://clojuredocs.org/clojure.core/slurp , slurp takes IhnputStream as an argument too

qqq12:12:10

so that whole thing should be reduced to slurp

bronsa12:12:24

something like this if you want, or slurp if it's good eno- ^

qqq12:12:26

(last part of question says "either a byteArray or a string as output")

qqq12:12:53

yeah, the java whiles really do not translate well to idiomatic clojure

qqq12:12:51

slurp worked

mbjarland16:12:07

a quick question. This to me was perhaps not what I expected:

((every-pred =) 1 2)
=> true
I assume this is caused by the fact that (= 1) => true and that every-pred applies every predicate to one argument at a time, is there anything in clojure core that would do this but apply all arguments to the predicates

mbjarland16:12:42

the docs for every-pred are not entirely conclusive here: > Takes a set of predicates and returns a function f that returns true if all of its composing predicates return a logical true value against all of its arguments, else it returns false. , but I guess I can see why it's implemented this way

Bravi16:12:49

@mbjarland probably you’d need to use

(every? (every-pred pos? (partial > 0)) '(1 2 3 -1))

Bravi16:12:26

or not-every?

Bravi16:12:33

depends what you’re trying to achieve

Bravi16:12:28

oh I see what you mean

Bravi16:12:51

nvm the above 😄

eraserhd16:12:40

Hey, so I know the Clojure philosophy is, wrt errors and stack traces, barf everything and let the tools sort it out. Is there a REPL tool to sort it out? Something usable with lein repl?

fmind16:12:35

@eraserhd you mean something to make stacktrace and error more human friendly ?

eraserhd16:12:54

I have stack traces that contain prn-str data (from pedestal) that exceed my 5000 line scrollback.

fmind16:12:03

(different question) do you know if Clojure support as many characters for keywords as for strings ?

fmind16:12:40

I need to handle JSON documents, and the library is converting each JSON key to a keyword instead of a string

fmind16:12:21

I'm worried that some characters will not be handled well as keywords

eraserhd16:12:55

If you pr-str/read-string it, this will definitely cause problems. I'm pretty sure that keyword does not validate the contents of the namespace or name, and they are stored as Java String.

eraserhd17:12:36

@fmind Hmm. It might not deal with the crazy amount of data in ex-info but this seems nice. Also ultra which uses it seems pretty useful.

Alex Miller (Clojure team)17:12:49

Keywords are made of strings. If you are programatically creating and using them you should be fine

Alex Miller (Clojure team)17:12:25

But don’t expect to be necessarily be able to print and read as data

Alex Miller (Clojure team)17:12:08

Also keep in mind that keywords are interned so there are memory effects if using a large number of arbitrary keywords

noisesmith17:12:02

it’s entirely valid (IMHO preferable) to just tell the json library not to keywordize - both clojure.data.json and cheshire let you choose, and almost everything else is using one of those

noisesmith17:12:07

our codebase has a bunch of nonsense for handling numbers that got turned to strings when they were keys in json, then turned into keywords when retrieved from the json… huge headache

scriptor17:12:20

we haven't really had any issues like that, and we tend to keywordize pretty often

scriptor18:12:00

not everywhere, though, have to do it judiciously

noisesmith18:12:44

@scriptor yeah the problem was that the people integrating monger (the clojure mongodb wrapper) didn’t realize keywordizing was optional, and didn’t sanitize the data to make sense for mongo insertion (eg. avoiding numeric keys), and by the time it was pointed out that we had other options the inconsistency of number / string / keyword in the data keys was baked into all the code consuming the data

scriptor18:12:20

yeah, only way to avoid situations like that is mandating thorough code review from more experienced people

scriptor18:12:45

which can be hard to do if most people on the team are still somewhat unfamiliar with clojure and/or its libraries' conventions

noisesmith18:12:32

right, a few iffy decisions made in the beginning (“move fast and break things!“) then years of pain

hiredman18:12:36

even experience people often get really annoyed when keys aren't keywords and write elaborate mapping layers

hiredman18:12:48

it drives me nuts

hiredman18:12:55

(the mapping layers)

noisesmith18:12:56

yeah - it’s a weird thing that causes so much bs

New To Clojure18:12:32

it's probably because you can't use (keyname map) syntax to get values when keyname isn't keyword.

New To Clojure18:12:48

Clojure encourages keywording

bronsa18:12:22

get is only 3 chars

potetm18:12:37

Honestly, keywordizing user input is one of the biggest time sinks in the clojure community.

bronsa18:12:39

and the benefits of not having to convert from/to keywords are way more than saving 3 characters

noisesmith18:12:43

@ghsgd2 I would be quite upset if I saw (:1234 foo) in my codebase, those keywords existed because nobody realized how easy it would be to not create them

bronsa18:12:10

not even considering that you can still do (my-map "my-key")

scriptor18:12:14

not a big fan of using maps as functions, personally, have to do a double-take to realize that it's a map and not a function defined elsewhere

mikerod18:12:24

The only thing I find a little confusing in this situation is that the external keys may come in via strings - and you leave them that way, but internally you probably have maps you make with keywords (in clj-land). so now you have both and that can get awkward or error prone

mikerod18:12:38

However, it typically is ok. You just sort of have to make those boundaries clear

tbaldridge18:12:02

@scriptor but the nice thing is you can swap it out later for a function with no change to the code

noisesmith18:12:06

@mikerod if the key comes in via user input, I prefer to make the key a string

noisesmith18:12:50

and for reasons that should be obvious, I don’t use the same data structure to look up based on user input and compiled code

noisesmith18:12:18

I mean, lisps are about arbitrary code at runtime and all but I like to pretend I’m not absolutely bonkers

justinlee18:12:27

is there a lot of expressive power gained from the whole IFn thing where keywords and collections can be in function position? as a newb I was totally surprised the first time I saw that, and I’m not 100% sold that the terseness is actually better for readability (echoing @bronsa’s statement that get is only 3 chars). but maybe it is nice to have once you get used to it?

noisesmith18:12:25

@justinlee it’s often that I discover some function that I wrote can be replaced by a simple hash-map, and since hash maps are much less powerful than functions it’s always a win to do that substitution

noisesmith18:12:40

that’s a refactor that would be impossible if hash-maps didn’t implement IFn

bronsa18:12:07

@lee.justin.m it really is convenient, esp when you can use them HOF (e.g. (map :foo my-coll)), but it's also really important to know when reaching for that conveniency causes unnecessary performance issues or having to handle conversions down the line

jstew18:12:27

Seem like it could come in handy in threading macros too. Random thought.

noisesmith18:12:59

right -it can make chained data access in nested data much cleaner

noisesmith18:12:38

@jstew but similarly to what I was saying about not using the same data for user input lookup and program lookup, I also don’t tend to write code such that user input comes in deeply nested, and yes I would absolutely use keywords for program created nested data structures

noisesmith18:12:59

and this doesn’t run into the problems with keyword/ string cross conversion we were discussing

jstew18:12:17

¥es indeed. When first starting with clojure I spent lots of time converting everything to keywords since it “looks prettier”. Esp with JSON there are dark corners to get caught in like you mentioned.

noisesmith18:12:04

also I can’t recommend transit enough if you need to write data to json (or external storage in general) in one place and then read it from another

noisesmith18:12:53

if I was remaking our app all the mongo insertions would be small json maps, with the indexed keys at the top, then a larger transit encoded payload under one key with the actual original clojure data embedded

noisesmith18:12:22

come to think of it I should make a small library that implements that pattern

hiredman18:12:43

are you sure you would still use mongo 😛

noisesmith18:12:34

@hiredman heh there’s some out of band / external stuff behind that but fair point

hiredman18:12:51

its been my experience that even with a "greenfield" project datastore choice is almost always dictated to you

noisesmith18:12:10

glad to know it’s not just me

hiredman18:12:37

in some ways it seems like validation of one of the core propositions of clojure, data is more important than programs

jgh19:12:51

>wishes he’d never gotten excited about MongoDB all those years ago... Me, 3 1/2 years ago: “Ah we’ll never get funding, I’ll make the app in Swift.” (Narrator: they did)

qqq21:12:45

I'm trying to rewrite:

Pointer kernelParameters = (
            (new int[]{numElements}),
            (deviceInputA),
            (deviceInputB),
            (deviceOutput)
        );
as
kparam (Pointer/to
              (Pointer/to (int-array [numE]))
              (Pointer/to devA)
              (Pointer/to devB)
              (Pointer/to devOut))
but I'm getting a "no matching method: to" on the first "Pointer/to" line -- this is despite I already have an (:import [jcuda Pointer])

noisesmith21:12:01

is Pointer/to varargs? EDIT - yes, it is, and that means you need to put all the variable args into an array

noisesmith21:12:24

wow, that’s a lot of calls to into-array, if I were doing this I’d make a function that constructs the varargs and calls the method (or maybe a macro)

qqq21:12:50

@rauh: thanks! @noisesmith: yeah, agreed, this is "1. make it work; 2. make it pretty" ; I'm currently on step 1

qqq21:12:24

I'm expecting:

devA    (CUdeviceptr.)
      _       (Pointer/to (to-array [devA]))

to work, but it's telling me "NO matching method Found to"

qqq21:12:15

instead of (to-array ...), I need (into-array Pointer ...)

noisesmith21:12:33

right, you need into-array

qqq22:12:30

is to-array basically (into-array Object ...) ?

noisesmith22:12:18

as I understand it yes

bronsa22:12:12

except more efficient

bronsa22:12:37

@qqq for questions like those I suggest just looking at the sources btw, it takes about 20 seconds and you'll learn much more