This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-09-05
Channels
- # asami (13)
- # aws (7)
- # babashka (4)
- # beginners (16)
- # biff (7)
- # cljdoc (10)
- # clojure (32)
- # clojure-europe (27)
- # clojure-nl (14)
- # clojure-norway (7)
- # clojure-uk (3)
- # clojurescript (2)
- # conjure (2)
- # core-async (13)
- # datalevin (4)
- # datomic (3)
- # holy-lambda (7)
- # kaocha (3)
- # lsp (23)
- # off-topic (39)
- # pedestal (10)
- # portal (5)
- # practicalli (2)
- # rdf (10)
- # releases (1)
- # shadow-cljs (66)
- # tools-deps (146)
- # uncomplicate (1)
- # xtdb (10)
Is there some core function that helps with adding a stateful transducer to an xform that has your own logic? Something to add a xform step that receives both the current value and the previous one to build things like dedupe
?
You need to close over a stateful data structure.
(defn foo-transducer
[rf]
(let [previous (volatile! nil)]
(fn ([] (rf))
([result] (rf result))
([result input]
(let [prev @previous]
(vreset! previous input)
(transform-somehow input prev))
))))
Search goog for "stateful transducer" to find more examples. The docs for transducer
includes an example that uses a Java ArrayList
instead of volatile!
.
https://clojuredocs.org/clojure.core/transduce#example-59523d78e4b06e730307db43@U90R0EPHA yes, I understand that's how the stateful transducers are implemented, but I'm wondering if there's a helper which kind of abstracts this process to something like a map
xf but with access to the previous value. Guess not. It's not that difficult to write but I thought it might be a common enough case that there's a fn for it.
Thanks @U90R0EPHA
1. dedupe
is already a transducer, but I'm guessing you mean implementing something similar?
2. are you familiar with https://github.com/cgrand/xforms ? It's a good toolkit of ready-to-use transducers (and I suppose can also be used as guide for building more complex ones)
3. your specific example of mapping over the current item and the previous, I would probably implement via xforms as: (x/partition 2 1 (x/reduce xf))
Thanks @U05476190. I've been browsing over xforms a bit but using the functions you mentioned wasn't obvious to me. I ended up just implementing the transducer without any such helpers, but I'm curious to try those and other parts of the lib at some point.
Quick question - in Emacs is there a keybinding in clojure-mode that sorts out indentations in clojure code? I'm fairly sure there's something like it in org-mode, but it's been a few months since I was looking at Emacs & Clojure, and I've forgotten a bunch.
I tend to use paredit and call paredit-reindent-defun
(M-q). You can call clojure-align
from Clojure mode (I have that mapped to C-c SPC). Alternatively call cider-format-buffer
or cider-format-defun
but you’ll need to set key bindings for those in your init.el
Hi, I submitted this problem on Stackoverflow: https://stackoverflow.com/questions/73613891/how-to-edit-the-inline-style-of-a-re-frame-component-to-add-a-scroll-to-an-overf Any help would be appreciated
Hi, I'm trying to troubleshoot a CORS error. I followed a couple previous suggestions here about using Ring wrap-cors
middleware https://github.com/prestancedesign/todo-backend-reitit/blob/master/src/todo_backend/core.clj#L61 as well as trying someone's custom handler
(defn allow-cross-origin
([handler]
(allow-cross-origin handler "*"))
([handler allowed-origins]
(fn [request]
(if (= (:request-method request) :options)
(-> {:status 200 :body ""}
(assoc-in [:headers "Access-Control-Allow-Headers"] "*")
(assoc-in [:headers "Access-Control-Allow-Origin"] allowed-origins)
(assoc-in [:headers "Access-Control-Allow-Methods"] "HEAD,GET,POST,DELETE"))
(-> (handler request)
(assoc-in [:headers "Access-Control-Allow-Headers"] "*")
(assoc-in [:headers "Access-Control-Allow-Origin"] allowed-origins)
(assoc-in [:headers "Access-Control-Allow-Methods"] "HEAD,GET,POST,DELETE"))))))
But neither did the trick for me, and I'm not sure how to proceed. Any ideas where I went wrong? I don't have very informed ideas about middleware order in case that is an issue, but I think I understand the "bottom" middleware is applied first, so I thought cors middleware should appear there as it does in the "todo" example I first linked. The departure from the "todo" example is that I'm using http-kit
instead of jetty, though I understand it is ring compatible. Thanks for reading.
(def app
(ring/ring-handler
(ring/router
[["/" {:name ::root
:get (fn [_] {:status 200
:body {:info "Backend API"}})}]
["/api" {:name ::api
:get {:parameters {:query {:url string? :start string? :end string?}}
:responses {200 {:body {:file string?}}}
:handler (fn [{{{:keys [start end url]} :query} :parameters}]
(get-sample start end url)
{:status 200
:body {:file (str "samples/" (hash (str start end url)) "." extension)}})}}]]
{:data {:coercion reitit.coercion.spec/coercion
:muuntaja m/instance
:middleware [format-negotiate-middleware
format-response-middleware
rrc/coerce-response-middleware
exception-middleware
rrc/coerce-exceptions-middleware
format-request-middleware
rrc/coerce-request-middleware
parameters/parameters-middleware
;;allow-cross-origin
[wrap-cors :access-control-allow-origin #".*"
:access-control-allow-methods [:get :put :post :patch :delete]]]}})))
Don't try to write your own -- you'll almost certainly get it wrong -- use the "standard" Ring wrap-cors
middleware -- it works. The most common thing people do wrong is put it at the wrong end of the middleware stack: it should be at the outermost layer of it all. I have no idea which way round reitit works. And it needs to be outside any routing -- otherwise your own handler code will try to handle the OPTIONS calls (incorrectly).
If you're still stuck, ask in #reitit
Thanks. I agree and am trying to use wrap-cors
. My code fragment above is modeled off the same setup as the "todo" example and the same middleware position, but still giving CORS errors. I'll keep trying and ask in #reitit if I'm still stuck.
Aha! I'm not sure how it can be working for the linked example, but moving it from the bottom of the middleware stack (what I thought was applied first) to the top did the trick.
Yup, a very common mistake unfortunately. Glad you got it working!