Fork me on GitHub
#clojure
<
2018-08-02
>
caleb.macdonaldblack00:08:57

Can I do an update that puts the value in another key in a simple way?

caleb.macdonaldblack00:08:58

like if I had a key called :ten and I wanted to add 5 and call it :fifteen

rcustodio00:08:58

change the key name? well, you have to dissoc and then assoc

caleb.macdonaldblack00:08:09

Nah I still want :ten

rcustodio00:08:24

want to add a key key, assoc

mg01:08:38

(assoc m :fifteen (+ (get m :ten) 5))

jaihindhreddy-duplicate10:08:43

(assoc m :fifteen (+ (:ten m) 5))

lilactown03:08:42

how are people using CIDER with deps.edn aliases?

kennytilton06:08:33

Hey, Clojure! You have officially reached maturity. From an HN “who’s hiring?” listing: “some of our legacy code is in ClojureScript”. 🙂

😂 40
20
henrik11:08:08

I’ve created a protocol that strips out branches of data structures that end in something which registers as true to empty?. It blows up when I feed it UUIDs. Why is this? I thought java.lang.Object was a kind of catch-all. https://gist.github.com/eneroth/81fe5acf0aab82c355889f28887e08ca

valtteri12:08:44

It dies here (filter seq)

valtteri12:08:55

Did you mean seq? maybe?

henrik12:08:42

Well, I mean “not empty?.” Oh, weird. Why does java.util.UUID end up matching on clojure.lang.PersistentVector or clojure.lang.PersistentList?

henrik12:08:26

Ah, no, I see. Calling seq or empty? on a UUID makes it blow up. That’s inconvenient.

henrik12:08:42

I.e., (empty? (java.util.UUID/randomUUID)) Boom!

henrik12:08:09

So, I need something sort of like empty?, but more resistant to things it doesn’t recognize.

henrik12:08:10

Updated the gist with an ugly hack. Do you have any suggestions for improvements?

mfikes12:08:49

empty? is meant for collections. Perhaps if a spec were written for it the coll argument would indicate such somehow.

benzap13:08:29

you could try using seqable? as a check instead of using a try-catch

benzap13:08:58

It was added in clojure 1.9 though

henrik13:08:15

@U0670BDCH Good idea!

(defn safe-empty?
  [thing]
  (if (seqable? thing)
    (empty? thing)
    false))
Is somewhat less painful to look at.

henrik13:08:08

Yeah, I know @U04VDQDDY. I’m really looking for something that will return true for anything that’s known to be empty, and false otherwise.

jumar20:08:00

@henrik (and (seqable? thing) (empty? thing)) may be a bit better.

👍 8
henrik04:08:59

@U06BE1L6T A good conditional is an absent conditional

eraserhd13:08:21

@henrik I think what you want could be done more concisely as something like (clojure.walk/postwalk (fn [x] (cond-> x (map? x) (medley.core/filter-keys #(not (nil? (get x %))) input)

eraserhd13:08:57

er, cond->>

henrik14:08:36

Thank you! 🙂 Not quite—walk/medley:

[{:moose-says "blaaargh",
  :giant {},
  :elf {:can-see "bridge"},
  :elf/thinking-of
  [#:item{:pastry "cake"} {} #:location{:land "home"} {}],
  :elf/hat [{}]}]
strip-nil:
[{:moose-says "blaaargh",
  :elf {:can-see "bridge"},
  :elf/thinking-of [#:item{:pastry "cake"} #:location{:land "home"}]}]

lilactown14:08:04

does anyone not AOT compile their clojure apps? why or why not?

dominicm14:08:45

@lilactown I know @seancorfield doesn't 🙂 I don't really see the point in doing so anymore.

lilactown14:08:08

I’m not sure I completely understand the pros and cons. I know it improves startup time - is that it?

bronsa14:08:23

not just that

bronsa14:08:46

it allows you to have a concrete classfile which can be useful when interopping from java in certain cases

lilactown14:08:21

ah - like Java calling Clojure?

eraserhd14:08:57

I used to AOT everything, but that causes problems. Especially if you are releasing libraries. AOT as little as possible, usually just the main class if you need one. I just stopped AOTing my main class for my big project, and now instead boot it with java -cp uberjar.jar clojure.main -e '(do (require 'main.namespace) (main.namespace/main))'

noisesmith17:08:16

fyi you can replace that with java -cp uberjar.jar clojure.main -m main.namespace

noisesmith17:08:33

except main has to be -main for that to work... I misread :D

eraserhd17:08:39

Does it still need (:gen-class)

noisesmith17:08:22

it doesn't need gen-class (you are using clojure.main), but clojure implicitly looks for a -main when you use -m

eraserhd17:08:29

Nice, thanks.

eraserhd14:08:23

Problems I've seen: functions whose spelling differs only by case collide when compiled on a case-insensitive filesystem; dependency cycles in namespaces cause interfaces or record types to be reloaded multiply, so that two pieces of code reference different versions (sometimes the cycles are caused by REPL tooling which wants to reload things), macros which are expanded based on system or features present create compiled code that doesn't work on other machines.

lilactown14:08:37

yeah, I kind of just realized that since I’m using Docker anyways - not even much point to packaging it in an uberjar 😛

ghadi14:08:06

we don't AOT. We deploy to docker containers in ECS. We have about 15 seconds of startup time, followed by 25 seconds of downloading data slugs until the healthcheck succeeds.

dominicm16:08:42

We used Elastic Beanstalk ages ago, and were really put off by the inability for us to debug the damn thing. We couldn't just ssh on and prod it.

dominicm16:08:48

How is ECS for you & clojure?

dominicm16:08:04

We've built our own rolling deploy stack on EC2/CodeDeploy, and it's showing weaknesses in AWS.

ghadi16:08:23

ECS fargate is weird, but ok

ghadi16:08:34

It works -- but no filesystem mounting

dominicm16:08:23

no filesystem?!

ghadi16:08:34

I prefer Kubernetes over ECS greatly, but Datomic Ions are super compelling to us too.

ghadi16:08:09

There's a filesystem, but you can't do external volume mounts, like a K8S Volume

dominicm16:08:28

I see. So that's not so bad. But essentially there's no EBS integration for ECS?

ghadi16:08:59

not for Fargate, but for the other ECS variant where you run your own boxes

dominicm16:08:00

I see. That explains why they let you do that then

dominicm16:08:09

That seemed weird when I first saw it, except as legacy

eraserhd14:08:18

uberjars are nice for getting all your dependencies in one file and having a SHA256 hash of it for tracking what's running.

lilactown14:08:21

I’m interested in understanding what benefits AOT can provide though. like I get the startup time (which is non-negligible IMO) but wondering if there’s any other performance benefits

lilactown14:08:29

ah that’s true. dependencies

ghadi14:08:55

If you AOT && do direct linking, which isn't enabled by default, you'll get peak performance improvements.

ghadi14:08:18

otherwise AOT mainly provides better startup time

lilactown14:08:53

yeah, I guess one downside to deploying just a docker image is that your container needs to download all dependencies before startup

lilactown14:08:14

I wonder if there’s a way to cache those as part of the build

lilactown14:08:46

(other than just COPY ~/.m2 😉 )

lilactown14:08:21

but then why not just uberjar it I guess

Maris15:08:03

we deploy uberjars and :aot :all, I havent noticed any problems with aot

jgh15:08:53

@lilactown you could make a Docker image with all of your dependencies baked into it that your builds make their images from

jgh15:08:16

that way you just need to rebuild the base image whenever your dependencies change instead of every time someone commits something 😛

lilactown15:08:14

that would probably speed CI up at work quite a bit. :thinking_face:

jgh15:08:39

Ah in that case that piece of valuable advice will be $800 😉

😂 4
lilactown15:08:22

do you accept IOUs? 😬

jgh15:08:54

well i do but that also means you owe me a free t-shirt.

lilactown15:08:21

boy, I did not understand the terms going into this conversation! :rolling_on_the_floor_laughing:

lilactown15:08:21

seriously though, thank you and everyone else for answering my questions 🙂

ghadi15:08:03

FROM openjdk:10 as jdk
RUN jlink \
   --strip-debug \
   --compress=1 \
   --vm=server \
   --output /tmp/linkedjdk \
   --add-modules 

# multistage docker build
FROM debian:stretch-slim
COPY --from=jdk /tmp/linkedjdk /jdk/
COPY app.jar /app/
ENTRYPOINT ["/jdk/bin/java"]

👍 4
ghadi15:08:33

The whole docker image should be between 70-150MB depending on deps

lilactown15:08:57

nice! I’ve been using the clojure:alpine images and have gotten about the same size

ghadi15:08:09

those images pin you to java 8 though...

lilactown15:08:12

true. I haven’t had any need to update yet; I’ll might have to do that soon though, so then I’ll probably copy what you’re doing 😄

jgh15:08:15

graalvm native-image + scratch = 10mb images 😮

👏 4
ghadi15:08:09

Graal native-image is cool, but it imposes severe limitations that the community rarely mentions

ghadi15:08:18

it completely trades away dynamism

ghadi15:08:55

many widely used jdk modules are not supported by native-image

jgh15:08:06

yeah it's not for everything, but right now i'm messing with serverless stuff and it's great for that.

ghadi15:08:10

it is hard to get a non-trivial app to compile under native-image.

lilactown15:08:29

yeah I went down the GraalVM rabbit hole a month or two ago. it’s fun but unwieldly

lilactown15:08:57

makes total sense for serverless and some CLI apps, but didn’t fit my usecase

ghadi15:08:14

jaotc is another option with fewer caveats than native-image

benzap00:08:34

This interesting, it seems like jaotc would make for a pretty good speedup in initialization, while also allowing dynamism?

benzap00:08:17

An alternative idea for native-image would be to make a subset of the clojure language runtime which doesn't make use of java's dynamic invokation

benzap00:08:45

I'll have to check out this jaotc, it seems like a promising alternative

ghadi00:08:57

Can't use eval itself in native image, so no REPL

ghadi00:08:20

native image and jaotc both use graal, with different tradeoffs

benzap02:08:56

Yeah, I knew that dynamic invokation didn't work in graal-vm's native-image. It's a bummer to learn that it doesn't work in in jaotc as well 😞

benzap02:08:48

In your experience, does it seem like jaotc has better support in a windows environment?

benzap02:08:20

Could I compile my application with java.base to significantly improve runtime initialization?

ghadi03:08:12

It does work in jaotc

lwhorton18:08:09

with clojure.test fixtures is it possible to pass an arg to the function to run?

(use-fixture
  :once
  (fn [f]
    (do-setup)
    (f some-args)
    (do-teardown)))

noisesmith18:08:39

no, but you can use a dynamic var

👍 4
jsk18:08:59

This might not be the channel for this sorta thing, but want to say that I’ve been playing around with clojure for a prototype and it has been wonderful 😛

🙂 44
parrot 12