clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
xceno 2020-10-08T00:13:49.167Z

To future readers, who may find this in a slack archive or zulip mirror: I found the problem. It's the Set-Cookie header. When configuring the middleware like this:

(ring.middleware.defaults/wrap-defaults
 {:session true
  :security  {:anti-forgery   true
              :hsts           true
              :ssl-redirect   false
              :frame-options  :sameorigin
              :xss-protection {:enable? true
                               :mode    :block}}})
it will add a header like this:
"Set-Cookie" ("ring-session=17a0900a-00b0-42ea-b54d-fbeec2acb15e;Path=/;HttpOnly")
Notice that the value is a seq, and that's the issue. The value must be a string for the AWS API Gateway to pass it through correctly. Adding an ugly workaround like this additional middleware fixes the issue:
(defn fix-aws-api-gateway-cookie-header [handler]
  (fn [req]
    (let [res (handler req)
          cookieList (get-in res [:headers "Set-Cookie"] [])]
      (assoc-in res [:headers "Set-Cookie"] (or (first cookieList) "")))))

2020-10-08T00:15:20.167400Z

iiuc docker may go away, but you get podman and its friends instead...

seancorfield 2020-10-08T00:15:49.167600Z

They look like Clojure future and promise -- what am I missing?

seancorfield 2020-10-08T00:16:55.168500Z

(:import (org.apache.sshd.common.session SessionHeartbeatController$HeartbeatType))
;; or just
(:import org.apache.sshd.common.session.SessionHeartbeatController$HeartbeatType)
;; if you're only importing one class from that package

dpsutton 2020-10-08T00:49:47.169400Z

Can that alias just the inner class?

alexmiller 2020-10-08T02:16:06.171500Z

in Java, inner classes are not hierarchically "below" inner classes, they are just lexically nested within them. The only hierarchical relationship is classes in packages.

alexmiller 2020-10-08T02:16:47.172Z

the class name of the nested class is SessionHeartbeatController$HeartbeatType so there is no way to break that apart

dpsutton 2020-10-08T02:18:17.172500Z

Oh I see. Thanks so much @alexmiller

grounded_sage 2020-10-08T05:05:43.176Z

Okay. But if the ns that does the require alters a dynamic var. The var being used by the macro in the required ns. Is that too late to alter how the macro expands?

victorb 2020-10-08T08:16:44.177300Z

Not sure if mostly Java related or Clojure, could guess Java/visualvm related but asking here just in case. Basically returning to my workstation today I find my project directory filled with *.class files, generated somehow. Guess it could be from a visualvm session yesterday with profiling?

Tamas 2020-10-08T09:14:47.181Z

Does this relatively new deprecation warning from Clojure tools WARNING: Use of :main-opts with -A is deprecated. Use -M instead. means that it is preferred to have $ clj -M:test:runner now instead of $ clj -A:test:runner -M:runner as described in https://github.com/seancorfield/clj-new?

Adrian Smith 2020-10-08T09:37:17.181800Z

Does anyone understand the mechanics of how this worked under the hood? https://www.youtube.com/watch?v=YY6B9EHbH24, particularly viewing values inside of function calls

Tamas 2020-10-08T10:14:07.184Z

Ahhh, I see @seancorfield was updating the README of seancorfield/clj-new a few hours ago. I must have had the previous version open in my browser 🙂

jumar 2020-10-08T11:36:25.185500Z

That looks like AOT compilation- nothing to do with visualvm

seancorfield 2020-10-08T16:06:25.191500Z

@sztamas Yup, I'll be overhauling clj-new to favor the -X execution approach in the next release (while still retaining the -M stuff), but I wanted to get the README etc updated sooner (you'll see the same issue with projects generated from clj-new until I make that release).

Tamas 2020-10-08T16:10:31.194Z

Yes, thanks for that! The timing of it was a bit funny. I asked, then actually forked your project to make a PR with the README changes, but by then it all looked OK in my fork. Had a bit of a huh? moment... :-)

victorb 2020-10-08T16:26:31.194300Z

hm, could not be happening when running the samples/profiles from visualvm?

2020-10-08T17:18:37.196400Z

Is there a way to use with-redefs such that you wrap the root binding? For example:

(defn fake-invoke [arg]
  (println "HEY!")
  (original/invoke arg))

(with-redefs [original/invoke fake-invoke]
  (original/invoke "Something"))
This will cause a stack overflow because original/invoke is still rebound. I'd like to "escape" the rebinding in the fake-invoke call.

dpsutton 2020-10-08T17:24:51.198300Z

(let [original redefed] (with-redefs [redefed (fn new [...] (prn "intercepted) (original ...))

🙏 1
2020-10-08T17:46:49.200600Z

at my last job before with-redefs was added to clojure we had a macro with-var-roots that did the same thing, but had the added feature of being able to use metadata to ask that the original value of the var by bound to some name in the scope of the expression

2020-10-08T17:48:21.202200Z

(with-var-roots [^{:original foo} original/invoke (fn [arg] (println "HEY!") (foo arg))] (original/invoke "something"))
so you could do something like that

🙏 1
vlaaad 2020-10-08T19:18:46.205Z

What do you think of reducible queue?

(defn reducible-queue [^BlockingQueue q]
  (reify IReduceInit
    (reduce [_ f init]
      (loop [acc init]
        (let [ret (f acc (.take q))]
          (if (reduced? ret)
            @ret
            (recur ret)))))))

(let [q (doto (ArrayBlockingQueue. 1024)
          (.put 1)
          (.put 2))]
  (future (Thread/sleep 1000)
          (.put q 3))
  (transduce (take 3) conj [] (reducible-queue q)))
;; 1 second later:
=> [1 2 3]

phronmophobic 2020-10-08T19:21:30.205100Z

one of the neat things about lisps (including clojure) is that they typically have a small number of language primitives, https://clojure.org/reference/special_forms . Not sure how Light Table did it, but you can basically just macro expand any form, look for the binding primitives (eg. let fn), and rewrite the code to extract the value when you eval the snippet

2020-10-08T19:27:51.205800Z

Just reduce over the queue

2020-10-08T19:29:20.208500Z

You can already reduce over all java Collections and even all, I forget the interface iterables?

Jan K 2020-10-08T19:31:27.209700Z

Reducing directly over the queue wouldn't wait for the last value 3. But it seems to me like (reducible-queue q) could be (repeatedly #(.take q))

vlaaad 2020-10-08T19:34:11.211100Z

oh, I haven't thought that queues are ordinary java collections

vlaaad 2020-10-08T19:34:39.211700Z

I wanted a reducible version for performance, I don't need intermediate collection...

vlaaad 2020-10-08T19:35:51.213100Z

hmm no, just reducing over queue does not block, that's not what I want

vlaaad 2020-10-08T19:36:32.213800Z

(let [q (doto (ArrayBlockingQueue. 1024)
          (.put 1)
          (.put 2))]
  (future (Thread/sleep 1000)
          (.put q 3))
  (transduce (take 3) conj [] q))
;; immediately
=> [1 2]

vlaaad 2020-10-08T19:37:43.214700Z

ah, you already pointed it out @jkr.sw 🙂

Jan K 2020-10-08T19:38:52.215200Z

(into [] (take 3) (reducible-queue q)) would probably be even faster since it uses transients

vlaaad 2020-10-08T19:39:10.215500Z

yeah, true 🙂

alexmiller 2020-10-08T19:59:52.216800Z

core.async has a reduce that reduces channels

alexmiller 2020-10-08T20:00:39.217100Z

although I now feel like we've had this identical conversation already

ghadi 2020-10-08T20:01:09.217600Z

often you want to walk away from the queue based on an external signal, so continuous reduce might not be best thing

ghadi 2020-10-08T20:01:46.218200Z

(no different with channels)

Matias Francisco Hernandez Arellano 2020-10-08T20:48:48.222600Z

Hi folks. I was asked to write a little post about Clojure and one question I would love to answer is Why Clojure. To me was more curiosity than anything else... So wondering what is tour reason to choose Clojure over other functional or jvm languages (if this dont be long here just let me know Thabks)

lread 2020-10-09T14:35:33.267Z

The Clojure community is also great. Some attributes that come to mind: smart, humble, curious, thoughtful, generous, patient, welcoming.

💪 1
phronmophobic 2020-10-08T20:52:14.222700Z

I came to clojure because I read a bunch of blog posts saying lisps were cool. I stayed for the emphasis on programming with pure functions and ubiquitous use of immutable data structures.

💪 2
Nassin 2020-10-08T20:58:26.222900Z

We like dogma and cults

😂 1
1
Adrian Smith 2020-10-08T21:01:13.223200Z

Most languages ship dead fish binaries, old languages like lisp/smalltalk encourage you to REPL into your running programs to build up your programs at runtime, Clojure still has this ability This is game changing for debugging and building long running processes like web servers or LSP servers or video game creation

seancorfield 2020-10-08T21:07:46.223400Z

The question is fine here as long as folks stick to answering in this thread (otherwise, for a more wide-ranging discussion, I'd suggest #off-topic ). My answer to "Why Clojure" is based on my language arc: I'd done a fair bit of Lisp at university (in the early '80s) and I specialized in FP for my postgraduate work (ML, Miranda, SASL -- all precursors of Haskell, along with the research language I created: SURE). My early professional work was COBOL, C, and assembler, then on to C++ in '92 (and eight years on the ANSI Standards Committee), then Java in '97 -- and I liked the JVM so everything since has been JVM-based. CFML/ColdFusion while I was at Macromedia, alongside Java. Then Groovy, then Scala -- as I wanted to tie together my earlier FP work with something on the JVM. That was around 2009. That got me casting around for more FP options on the JVM so I found Clojure in 2010, then introduced it at work in 2011 and cross-trained the other developers. And I've been doing Clojure in production ever since. So, "Why Clojure" is: a) because I have always felt FP is a better way to design/construct programs (despite all my years in the OOP wilderness -- and a lot of advocacy for OOP, since I never figured FP would go "mainstream") b) because I like dynamic languages better than statically typed languages (mostly personal) and compile-on-demand languages better than aot-compiled languages (my laziness and lack of patience 🙂 ) c) because immutability by default eliminates a whole class of bugs d) because the REPL provides immediate feedback and an interactive way to build programs (again, my lack of patience 🙂 )

Matias Francisco Hernandez Arellano 2020-10-08T21:18:43.224Z

Thanks for the thorough answer

vlaaad 2020-10-08T21:19:30.224200Z

don't remember it... I'm reluctant to depend on core async because of the startup time penalty it brings

vlaaad 2020-10-08T21:20:56.224400Z

well that's what returning reduced is for?

phronmophobic 2020-10-08T21:21:01.224600Z

repl driven development support has also been a big reason I've stuck with clojure.

vlaaad 2020-10-08T21:21:40.224800Z

e.g. (take-while (fn [_] @running)) is somewhere in xform

vlaaad 2020-10-08T21:31:35.225Z

this is for a library for others to depend on...

vlaaad 2020-10-08T21:34:16.226400Z

is there a transducer that does windowing by time? sort of like a partition-by, but flushes elements at least every n millis if non-empty

2020-10-08T21:36:06.226700Z

you can't do that with a transducer

alexmiller 2020-10-08T21:36:39.227Z

https://github.com/cgrand/xforms has some windowing xforms

🙏 1
2020-10-08T21:37:26.227900Z

the reducing function returns whatever value to a reducing context, and cannot wait for some timeout and flush

vlaaad 2020-10-08T21:38:35.228100Z

ah, good point

Matias Francisco Hernandez Arellano 2020-10-08T21:55:08.228400Z

I still can't follow the idea of Repl DD haha.. good point

seancorfield 2020-10-08T22:04:52.228600Z

Eric Normand's REPL-Driven Development course on http://PurelyFunctional.tv is awesome (if you don't mind paying $49 for a month's subscription). Stu Halloway has two great talks on the topic: Running With Scissors and REPL-Driven Development.

seancorfield 2020-10-08T22:06:09.228800Z

I've prattled on about it a lot too: never type instead of the REPL, don't use refresh/reload "magic", eval every single change as you make it (without even saving files), learn to run tests via the REPL using a hot key in your editor.