Fork me on GitHub
#clojure
<
2019-04-11
>
aryyya05:04:35

Is it possible to get ParEdit working in the Clojure REPL (the one invoked with lein repl)?

Robert Nikander07:04:44

@aryyya.xyz Which editor are you using? I can turn on paredit-mode in the REPL in Emacs.

aryyya07:04:18

@rob704 I’m not using an editor, I’m using a terminal.

Robert Nikander07:04:20

Oh, okay. Without an editor wrapping the terminal/repl, then I don't know the answer.

aryyya07:04:33

@rob704 I’ve also got it working in the CIDER REPL with ParEdit in Emacs, but I’m trying to transition away from Emacs in favor of VS Code, which I run a regular terminal inside of with the REPL. I’ve got pretty much everything working for my own workflow as it would be in Emacs with CIDER, but I can’t figure out this one minor thing.

Robert Nikander09:04:36

@aryyya.xyz I wanted to try that too (VS Code). Do you have key combos to quickly eval/reload things in the REPL, without having to cut-n-paste? In Emacs, commands like cider-eval-defun-at-point, cider-eval-sexp-at-point, cider-load-buffer.

aryyya17:04:01

Yes I believe those are all available.

aryyya19:04:55

Check out the Calva package for VS Code.

dominicm08:04:34

@aryyya.xyz I think rebel-readline does paredit.

Mike C13:04:20

I have a little golfing challenge if anyone's feeling bored on a Thursday afternoon: https://gist.github.com/clarkema/61464cb52ba107047c28cdff0539d030

Mike C13:04:37

I'm looking for the absolute fastest way to loop over an index from 1 to n

Alex Miller (Clojure team)13:04:54

you're ruining it with the boxed constant prob

Alex Miller (Clojure team)13:04:47

(time (loop [i 1]
        (inc i)
        (if (< i 100000000)
          (recur (inc i)))))

Alex Miller (Clojure team)13:04:50

alternately, this should have similar effect:

Alex Miller (Clojure team)13:04:54

(def ^long ^:const up-to 100000000)

Alex Miller (Clojure team)13:04:24

might help the other timings too

Alex Miller (Clojure team)13:04:24

and actually the inc i would be even faster if using unchecked math. you can turn that on as the default AND get warnings about boxed usage like this:

Alex Miller (Clojure team)13:04:34

user=> (set! *unchecked-math* :warn-on-boxed)
:warn-on-boxed

Alex Miller (Clojure team)13:04:04

user=> (time (loop [i 1]
        (inc i)
        (if (< i up-to)
          (recur (inc i)))))
Boxed math warning, NO_SOURCE_PATH:3:13 - call: public static boolean (long,java.lang.Object).

Mike C13:04:21

@alexmiller That's really interesting, thanks!

Alex Miller (Clojure team)13:04:54

with unchecked math and avoiding boxing, more like 32 ms

Alex Miller (Clojure team)13:04:24

should basically be emitted as essentially the same bytecode you'd get from a tight java numeric loop on a long counter (although more natural in Java to use ints)

Mike C13:04:25

I'll have a go with that in the real example (up-to in real life is actually the result of .size on a java.util.ArrayList

Alex Miller (Clojure team)13:04:19

you can type-hint it or coerce it at point-of-use too - result of .size is an int, and a coercion to primitive long will be required somewhere. best to do it explicitly once, then every time through the loop if possible.

Mike C14:04:47

yup, that's shaved a pretty nice chunk off

Mike C14:04:49

thanks 🙂

macrobartfast15:04:40

I need to add a content-type/application-json header to a luminus swagger endpoint that looks like

["/json" {:get (constantly (ok (json/write-str {:foo "bar"})))}]
any thoughts?

macrobartfast15:04:21

I'm getting

"content-type": "application/octet-stream",
instead.

macrobartfast15:04:20

the new luminus/swagger uses reitit so I think things may be different than before.

nickmbailey15:04:37

can you call defmacro within defmacro?

lilactown16:04:39

I would not 😛 what’s the use case?

dominicm16:04:59

You can do it though, might be a little tricky.

Alex Miller (Clojure team)16:04:06

do you mean emit or call?

Alex Miller (Clojure team)16:04:35

defmacro-emitting macros are definitely possible and useful. also quite painful to write.

👍 8
ikitommi17:04:51

@macrobartfast if you have a content-negotiation middleware in the mw chain, it should do the formatting for you, there is a example here: https://github.com/metosin/reitit/blob/master/examples/ring-spec-swagger/src/example/server.clj#L82

Alex Miller (Clojure team)17:04:03

still looking for more experience reports feedback on the Clojure 1.10.1-beta2 changes in error reporting if anyone has the opportunity to live with it for a bit. See https://www.reddit.com/r/Clojure/comments/bc264v/clojure_1101beta2_is_now_available/ekn9qr3/ for an example.

seancorfield18:04:02

I just updated our code base to use Beta 2 and all tests pass (of course) -- the next failure that I hit will make me appreciate CLJ-2497 being fixed 🙂

danielstockton19:04:57

Anyone fancy a 4clojure type exercise? A function that takes a vector and an item in that vector and shifts the item right or left by one.

dpsutton19:04:05

items in the vector are distinct?

dpsutton19:04:39

ie, (shift :left :a [:x :x :a :x :a :x]) returns what?

danielstockton19:04:16

(shift :left 1 [1 2 3 4 5]) -> [5 2 3 4 1]

danielstockton19:04:01

(shift :left 3 [1 2 3 4 5]) -> [1 3 2 4 5]

Alex Miller (Clojure team)19:04:03

cycle, drop x, take n handles that (computing x appropriately for right/left)

Alex Miller (Clojure team)19:04:36

oh, shifts single item not the whole thing

👍 4
dpsutton19:04:54

i was looking at split-with #(not= e %) and then recombining based on left or right

dpsutton19:04:07

(let [[before [_ & after]] (split-with #(not= e %) coll) and play from there

👍 4
danielstockton20:04:38

(defn shift [direction i coll]
  (let [[before [_ & after]] (split-with #(not= i %) coll)]
    (if (= direction :left)
      (if (butlast before)
        (vec (concat (butlast before) [i] (take-last 1 before) after))
        (vec (concat (take-last 1 before) after [i])))
      (if (empty? (rest after))
        (vec (flatten (concat [i] before)))
        (vec (flatten (concat before [(first after)] [i] [(rest after)])))))))
Pretty ugly but it works

danielstockton20:04:06

Can tidy it up a bit

noisesmith20:04:10

if this was 4clojure I would make [[1] [2] [3]] an input (to rule out using flatten)

danielstockton20:04:49

I think it still works, because i flatten after splitting

noisesmith20:04:06

it would return the wrong output

danielstockton20:04:14

Flatten just lets me make everything a seq so that concat doesnt blow up

noisesmith20:04:31

there are solutions that don't force you to destroy the structure of your input

danielstockton20:04:39

You're right, it breaks when using flatten

danielstockton20:04:02

I'm sure there are, what i have is very inelegant

Alex Miller (Clojure team)20:04:20

I'd get rid of :right / :left and use +/- in index

Alex Miller (Clojure team)20:04:52

is i an index? or is that a value to match?

Alex Miller (Clojure team)20:04:34

I guess value, so nvm. I totally misunderstood (twice now) what this is doing. :)

danielstockton20:04:05

Yes, bad naming, sorry

danielstockton20:04:14

x would be more idiomatic?

Alex Miller (Clojure team)20:04:51

well, i was confusing :)

noisesmith20:04:14

el elt or needle might be good

Alex Miller (Clojure team)20:04:49

cheese ("who moved my cheese?")

😄 8
👆 8
danielstockton20:04:11

I'll have to try again tomorrow, brain is tired. :sleeping_accommodation:

butterguns20:04:06

Can I use a bit of java interop?

(defn shift [direction item coll]
  (let [f (case direction :left dec :right inc)
        pos (.indexOf coll item)]
    (when (not (neg-int? pos))
      (let [target-pos (mod (f pos) (count coll))
            overlay {target-pos item, pos (nth coll target-pos)}]
        (reduce (fn [coll [position new-value]] (assoc coll position new-value)) coll overlay)))))

danielstockton20:04:21

Sure, I asked in the #clojure channel after all. Too bad i'm wanting it for clojurescript, oops :man-facepalming:

😆 8
danielstockton20:04:53

Looks like it can translate fairly easily

danielstockton20:04:10

(.indexOf (make-array coll) item) 🙂

noisesmith21:04:39

@mattmorten doesn't that when ensure that you return nil if you step past the index the item isn't found?

butterguns21:04:40

I wasn't sure what the requirement was for that

aryyya21:04:04

Is there a more semantic way to do a catch all in a cond?

Alex Miller (Clojure team)21:04:40

all keywords are logically true

Lennart Buit21:04:59

oh! today I learned

Lennart Buit21:04:53

I just kinda assumed :else was something cond understood

Lennart Buit21:04:16

but … ofcourse not

Alex Miller (Clojure team)21:04:05

so you could also just say :catch-all if you wanted :)

aryyya21:04:18

Ahh interesting, thanks!

aryyya21:04:31

:else is the convention then.

Alex Miller (Clojure team)21:04:43

on occasion, I add a bit of whimsy

aryyya21:04:06

I like the word :otherwise, so I’ll probably go with that.

noisesmith21:04:31

there are linters that accept :else but not :otherwise

Lennart Buit21:04:53

always make code the least surprising right 🙂

aryyya21:04:27

Ok, you’ve convinced me.

dpsutton21:04:20

i like a convention in cond-> to use :always

seancorfield21:04:01

user=> (cond-> 1
:please inc
:don't  inc
:do     inc
:this   inc)
5
user=> 
(runs away)

Lennart Buit21:04:44

Even apostrophes in keywords, you madman

seancorfield21:04:48

user=> :<>:<>:<>
:<>:<>:<>
user=>
(I was a bit surprised multiple : were accepted!)

Alex Miller (Clojure team)21:04:25

"A symbol can contain one or more non-repeating ':'s" and "Keywords are like symbols"

Alex Miller (Clojure team)21:04:01

that said, I wouldn't recommend it :)

seancorfield22:04:21

Ah, thank you. I'm sometimes not quite sure whether something is intentionally accepted (and documented) or not when it comes to literal keywords 🙂

seancorfield22:04:52

(and UTF-8 just adds a whole newer layer of fun on top of all this!)

seancorfield22:04:07

user=> (let [💩 42] (* 💩 💩))
1764

Lennart Buit22:04:05

Well that makes more sense in non Latin scripts ^^. I kinda wonder whether there are many people using bindings with non-Latin names

hipster coder22:04:24

I forgot what the -> does

seancorfield22:04:45

-> is "thread first" so it threads the value (initially 1) into each of the expressions for which the test expression is truthy.

seancorfield22:04:23

So it ends up being (-> 1 inc inc inc inc) (because all those keywords are truthy) which is (inc (inc (inc (inc 1))))

Alex Miller (Clojure team)22:04:44

although that page probably needs some better examples

seancorfield22:04:41

Yeah, especially around the use of as-> since it doesn't show it nested inside -> 😞

seancorfield22:04:14

(-> 42 inc (as-> x (* x x)) dec)

ackerleytng22:04:53

is there any way to combine regexes, other than combining strings and then using re-pattern?

ackerleytng22:04:31

I already have regexes and i need to concatenate them to find a larger pattern

noisesmith22:04:26

@ackerleytng this is the full API - I think making strings, combining, then making a new pattern is the most direct thing https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html

devth23:04:05

I have a curious situation where attempting to evaluate any expressions (even something as simple as 1) inside of a Clojail sandbox on an app running inside a Docker container trips an exception:

Exception in thread "async-dispatch-8" java.security.AccessControlException: access denied ("java.io.FilePermission" "/var/log/yetibot/yetibot.log" "read")
the app is completely crippled after this point (any sort of IO will fail), even outside of the sandbox. this only happens when running the Docker container on Digital Ocean. I run the same image on an internal VM at work and it works fine. it also works locally (outside of Docker). ideas? :thinking_face:

seancorfield23:04:41

I assume it is tripping up trying to write the log file...?

seancorfield23:04:53

(although it says "read")

devth23:04:03

yes, though writing logs should happen outside of the sandbox, and normally works fine

devth23:04:11

it's only when i try invoking the sandbox that it starts happening.

devth23:04:19

and once it happens, any http request also trips the same exception

devth23:04:45

only way to recover is to restart the docker container as far as i know

devth23:04:02

i also put a very permissive java policy file inside the docker image. i don't know much about java policy though.

devth23:04:59

this is what it looks like when attempting to make an http request after it's been crippled:

java.security.AccessControlException: access denied ("java.net.NetPermission" "getProxySelector")
        at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
        at java.base/java.security.AccessController.checkPermission(AccessController.java:895)
        at java.base/java.lang.SecurityManager.checkPermission(SecurityManager.java:322)
        at java.base/java.net.ProxySelector.getDefault(ProxySelector.java:96)
        at clj_http.core$get_route_planner.invokeStatic(core.clj:227)

devth23:04:38

the very mysterious part is why the same docker image works on one VM but not on a DigitalOcean VM.

seancorfield23:04:38

I'd be tempted to follow a Digital Ocean support path at that point I think... ¯\(ツ)

devth23:04:12

yeah. i might try that. i'm pretty baffled