Fork me on GitHub
#clojure
<
2021-05-01
>
matheusashton00:05:50

Hello, I'm creating an api with reitit with ring and using component approach, my main handler is a function in order to receive as param a component with all needed dependencies. I wanted to use ring.middleware.reload to avoid having to restart my server at every change, but for what I could get from https://stackoverflow.com/a/43075132 I need to pass a var reference to wrap-reload but I can't because I need to start the system, get all the components provided, and then call my handler with the component so it can have all the dependencies it needs. Do you have an idea how can I achieve that in this situation? Here is the project if you want to take a look: https://github.com/ashton/fiis-api PS: sorry if it's kinda dumb question, started working with clojure recently

piyer03:05:52

your system component comes from env?

matheusashton04:05:26

I created a config component that could receive some env variables

matheusashton04:05:35

like database credentials

borkdude09:05:05

What is the cost of turning a persistent collection into a transient and vice versa? Is this negligible, as in, it almost always pays off to use a transient if you have multiple edits, or should you make a careful trade-off?

borkdude10:05:13

user=> (defn assoc2 [m k1 v1 k2 v2] (-> m (assoc k1 v1) (assoc k2 v2)))
#'user/assoc2
user=> (time (dotimes [i 100000000] (assoc2 {} :a 1 :b 2)))
"Elapsed time: 4107.996251 msecs"
nil
user=> (defn assoc2transient [m k1 v1 k2 v2] (-> (transient m) (assoc! k1 v1) (assoc! k2 v2) persistent!))
#'user/assoc2transient
user=> (time (dotimes [i 100000000] (assoc2transient {} :a 1 :b 2)))
"Elapsed time: 7006.140274 msecs"

Ben Sless10:05:45

persistent  0   59.834286   ns
transient   0   126.623222  ns
persistent  1   50.380727   ns
transient   1   97.708084   ns
persistent  2   77.446552   ns
transient   2   108.747859  ns
persistent  3   104.248826  ns
transient   3   121.066979  ns
persistent  4   129.282491  ns
transient   4   133.730972  ns
persistent  5   153.419134  ns
transient   5   149.018422  ns
persistent  6   180.185956  ns
transient   6   158.353261  ns
persistent  7   207.039484  ns
transient   7   170.311342  ns
persistent  8   234.054261  ns
transient   8   181.334001  ns
persistent  9   258.810761  ns
transient   9   194.844289  ns
persistent  10  286.604407  ns
transient   10  203.995842  ns
persistent  11  313.167452  ns
transient   11  217.507117  ns
persistent  12  340.265275  ns
transient   12  229.006417  ns
persistent  13  371.397952  ns
transient   13  242.451556  ns
persistent  14  395.458757  ns
transient   14  249.939500  ns
persistent  15  426.517073  ns
transient   15  264.421980  ns

Ben Sless10:05:54

(require '[criterium.core :as cc])

(doseq [n (range 16)]
  (println "persistent " n)
  (cc/quick-bench (reduce conj [] (range n)))
  (println "transient " n)
  (cc/quick-bench (persistent! (reduce conj! (transient []) (range n)))))

borkdude10:05:56

Cool, this is with a vector. Can you run it with a map as well?

Ben Sless10:05:18

sure, please hold 🙂

Ben Sless10:05:58

looks like the inflection point for maps is around 4 elements

Ben Sless10:05:51

welcome 🙂 Just to clarify, 4 assoc!s are faster than the persistent version

Ben Sless10:05:21

this is not a complete test, however, it doesn't cover maps with more interesting shapes, I wonder if it has an effect

borkdude10:05:05

Some core fns switched to transients for performance, but considering the above benchmarks, the core fns should be actually slower after this change, for some inputs?

Ben Sless10:05:05

Which functions besides into?

Ben Sless10:05:01

But theoretically, yes

borkdude11:05:14

I'm beginning to see a small perf benefit when using over 10 keyvals but below that it's slower with transients, in a graalvm binary. I was trying to speed up the bindings in a loop, but more than 10 local loop bindings is pretty uncommon.

Ben Sless05:05:38

I'll try this test again with the JIT off

Ben Sless10:05:57

There's an inflection point at some size, I think around 8

Adam Helins10:05:25

Is there a reason behind not implementing this?

`{~@[:a 42]}
;; Syntax error, map literal must contain an even number of forms

p-himik10:05:54

The map literal is consumed during the reader stage. The ~@ thing is expanded during the macro expansion stage, which is later.

💯 3
p-himik10:05:28

If you need it in a macro, you can just use hash-map explicitly - there shouldn't be any noticeable difference.

delaguardo12:05:37

or hack it around using {~@[:a 42] ~@()} 😛

yuhan16:05:42

I recall the Swearjure creators ran into the same problem :P https://hypirion.com/musings/swearjure

yuhan16:05:55

implementation of hash-map without alphanumeric characters:

(def my-hash-map
  #(`[{~% ~@%&}] (+)))

3
Adam Helins16:05:09

Haha, the things some people invent... I didn't know about Swearjure, truly an excellent mind twister

zendevil.eth10:05:31

Can someone tell me what this error is about?: I’m trying to handle a websocket connection using immutant async:

(def websocket-callbacks
  "WebSocket callback functions"
  {:on-open connect!
   :on-close disconnect!
   :on-message notify-clients!})

(defn ws-handler [request]
  (async/as-channel request websocket-callbacks))
But calling the ws-handler gives :
No method in multimethod 'initialize-stream' for dispatch value: :servlet
on line
(async/as-channel request websocket-callbacks)

Noah Bogart13:05:01

Idk what as-channel does but that error is telling you what you need to do: make a defmethod for initialize-stream for the value :servlet

Karol Wójcik13:05:24

How can I make lein-template clj-new compatible?

borkdude13:05:26

@karol.wojcik Why is it currently not compatible? I thought clj-new worked with lein templates out of the box but I might be mistaking

Karol Wójcik13:05:49

Hmm. Probably I don't know how to correctly call it with holy-lambda template :((

borkdude13:05:01

@karol.wojcik What have you tried?

Karol Wójcik13:05:15

@borkdude clj -X:new holy-lambda basic

borkdude13:05:53

you should write clj -X:new :template holy-lambda :something-else basic, that is how -X works, pass key/val (or path/val)

borkdude13:05:47

afaik you can still use the main function but this isn't documented by @seancorfield - I don't understand the tendency to move towards "EDN on the command line over well-design command line interface" but that's how it is

💯 3
borkdude13:05:12

@karol.wojcik

$ clojure -M:new -m clj-new.create holy-lambda foo.bar
Generating fresh 'lein new' holy-lambda project.

Karol Wójcik13:05:52

@borkdude Thank you! Found this works as well: clojure -X:new clj-new/create :template holy-lambda :name basic.core

borkdude13:05:13

yeah, that's how you're supposed to use it. See docs

❤️ 3
borkdude13:05:34

You can put the :exec-fn in the deps.edn :new alias

Santiago14:05:43

working with websockets client for the first time: how do I go from java.nio.HeapCharBuffer to a string or something I can feed to clojure.data.json/read-str ? (I’m using hato as the client in a backend app, this is not cljs!)

Santiago14:05:37

I had typo :face_palm: ofc that works thanks

genRaiy16:05:01

what's the state of the art for deps.edn projects when building a cljs client to serve from a clj server? Are we still all using two commands, one each for the client and the server? [ Just want to be sure I didn't miss a memo ]

p-himik16:05:36

The server command runs the server - the run time, after deploying. The client command builds the client - the compile time, before deploying. They should not be a single command.

andy.fingerhut16:05:07

I would not be surprised if some people create shell aliases and/or tiny shell scripts so they can reduce typing for these kinds of things.

p-himik16:05:36

Definitely! And there's a bit less of a need for that with the recent clj CLI. But still - two separate commands. :)

genRaiy17:05:27

ok - cool, it's how I thought. Thanks @U2FRKM4TW and @U0CMVHBL2

Jacob Emcken18:05:43

Is it possible to eval a single form inside a comment block in Emacs (Spacemacs)? I use C-c C-c to eval stuff like function definitions. I have a comment block with something like the following:

(comment
  (require 'app.stuff)
  (def a-list (app.stuff/get-list))
  )
I'm trying to put the cursor on require and "do something" that will evaluate only (require 'app.stuff) . I got inspired from "Rich comment blocks" but I must be missing something. Maybe what I need isn't bound in Spacemacs... but I have no idea of what it is that I'm looking for.

OrdoFlammae18:05:54

Maybe ask in the #spacemacs channel? You'll be more likely to get an answer faster in the right channel.

👍 4
dpsutton18:05:27

There’s a var for that

dpsutton18:05:47

Check out m-x apropos toplevel

OrdoFlammae18:05:08

Also, try putting the cursor on the last paren of require . Haven't used spacemacs in a while, but that might work a bit better. What function are you running to eval the expression?

dpsutton18:05:56

(setq clojure-toplevel-inside-comment-form t)

dpsutton18:05:37

> Eval top level forms inside comment forms instead of the comment form itself. Experimental.

lilactown18:05:39

typically what I do is cider-eval-last-sexp, which in spacemacs' clojure layer is bound to SPC m e e by default

7
Jacob Emcken08:05:25

I did try cider-eval-last-sexp which is also bound to C-c C-e but I didn't understand where I had to place the cursor. Without correct cursor position the result was somewhere between errors and unuseable.

Jacob Emcken08:05:43

But now that I understand it a bit better I found the following to work:

(comment
  (require 'app.stuff)
█ ;; place cursor here and "eval-last-sexp"
  ;; to "require app.stuff"
  (def a-list (app.stuff/get-list))
  ;; place cursor here and "eval-last-sexp"
  ;; to define a-list
  )

Jacob Emcken08:05:51

thanks for your help

awb9919:05:16

cI have a problem parsing a xml document. can someone help me? I try to use zippers

awb9919:05:06

(ns edgar.nport (:require [clojure.string :as str] [clojure.xml :as xml] [http://clojure.java.io :as io] ;[clojure.data.xml :refer [parse-str] [clojure.zip :as zip] [clojure.data.zip :as zf] [clojure.data.zip.xml :as zip-xml])) ; zippers ; https://blog.korny.info/2014/03/08/xml-for-fun-and-profit.html ; http://clojure-doc.org/articles/tutorials/parsing_xml_with_zippers.html (defn dl [n-p] (let [node-p (first n-p) tag-p (-> node-p :tag) nodes-c (:content node-p) v-c (for [node-c nodes-c] [(:tag node-c) (first (:content node-c))])] ; {:tag-p tag-p :c (into {} v-c)} (into {} v-c))) (let [r (-> "demodata/a.xml" io/file xml/parse zip/xml-zip) g (zip-xml/xml1-> r :b)] ; g ;(zf/descendants g) (dl g)) (defn dl-p [root & paths] (-> (apply zip-xml/xml1-> root paths) dl)) (def root (-> "demodata/N-PORT/primary_doc.xml" io/file xml/parse zip/xml-zip)) (def gi (zip-xml/xml1-> root :formData :genInfo)) (dl gi) (dl-p root :formData :genInfo) (dl-p root :formData :fundInfo)