clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
matheusashton 2021-05-01T00:43:50.361400Z

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

piyer 2021-05-01T03:35:52.362600Z

your system component comes from env?

emccue 2021-05-01T04:13:06.362800Z

Can you document all the pain points you have working with this library?

emccue 2021-05-01T04:14:09.363Z

this seems like a pretty good example of the kind of lib clojure tends to have trouble with

emccue 2021-05-01T04:14:34.363200Z

and I am personally interested in what libraries can be written to ease some pains

zackteo 2021-05-01T04:15:40.363400Z

Alright! Hope I can get a minimal example working ... ><

zackteo 2021-05-01T04:16:43.363600Z

Any suggestions on how I should document it though? @emccue

zackteo 2021-05-01T04:17:59.363900Z

As of now I've been trying to do a one to one translation of the code from java to clojure

matheusashton 2021-05-01T04:18:26.364100Z

I created a config component that could receive some env variables

matheusashton 2021-05-01T04:18:35.364300Z

like database credentials

borkdude 2021-05-01T09:57:05.365700Z

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?

borkdude 2021-05-01T10:15:13.365900Z

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

Ben Sless 2021-05-01T10:18:57.366200Z

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

Helins 2021-05-01T10:26:25.367600Z

Is there a reason behind not implementing this?

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

p-himik 2021-05-01T10:29:54.367700Z

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

1💯
Ben Sless 2021-05-01T10:30:45.367900Z

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 Sless 2021-05-01T10:30:54.368100Z

(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)))))

p-himik 2021-05-01T10:31:28.368300Z

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

borkdude 2021-05-01T10:33:56.368600Z

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

Ben Sless 2021-05-01T10:34:18.368800Z

sure, please hold 🙂

Ben Sless 2021-05-01T10:38:58.369Z

looks like the inflection point for maps is around 4 elements

borkdude 2021-05-01T10:39:34.369200Z

:thanks3:

Ben Sless 2021-05-01T10:42:51.369400Z

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

Ben Sless 2021-05-01T10:43:21.369600Z

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

borkdude 2021-05-01T10:47:05.369800Z

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 Sless 2021-05-01T10:50:05.370Z

Which functions besides into?

Ben Sless 2021-05-01T10:51:01.370200Z

But theoretically, yes

borkdude 2021-05-01T10:51:36.370400Z

zipmap

zendevil 2021-05-01T10:58:31.372300Z

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)

borkdude 2021-05-01T11:03:14.372600Z

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.

2021-05-01T12:08:37.372800Z

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

NoahTheDuke 2021-05-01T13:13:01.374100Z

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ójcik 2021-05-01T13:16:24.374300Z

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

borkdude 2021-05-01T13:22:26.374800Z

@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ójcik 2021-05-01T13:22:49.375300Z

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

borkdude 2021-05-01T13:23:01.375600Z

@karol.wojcik What have you tried?

Karol Wójcik 2021-05-01T13:23:15.375900Z

@borkdude clj -X:new holy-lambda basic

borkdude 2021-05-01T13:23:53.376600Z

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

borkdude 2021-05-01T13:24:47.377600Z

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

1💯
borkdude 2021-05-01T13:32:12.377900Z

@karol.wojcik

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

Karol Wójcik 2021-05-01T13:33:52.378300Z

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

borkdude 2021-05-01T13:34:13.378600Z

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

1❤️
borkdude 2021-05-01T13:34:34.379Z

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

Santiago 2021-05-01T14:00:43.382300Z

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!)

borkdude 2021-05-01T14:10:59.382700Z

@slack.jcpsantiago (str buf) ?

Santiago 2021-05-01T14:49:37.383Z

I had typo :face_palm: ofc that works thanks

raymcdermott 2021-05-01T16:35:01.385700Z

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-himik 2021-05-01T16:39:36.385800Z

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.

yuhan 2021-05-01T16:43:42.386Z

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

yuhan 2021-05-01T16:44:55.386300Z

implementation of hash-map without alphanumeric characters:

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

1
2021-05-01T16:50:07.386600Z

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.

Helins 2021-05-01T16:50:09.386800Z

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

p-himik 2021-05-01T16:51:36.387Z

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

raymcdermott 2021-05-01T17:48:27.387400Z

ok - cool, it's how I thought. Thanks @p-himik and @andy.fingerhut

Jacob Emcken 2021-05-01T18:16:43.393100Z

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.

Jacob Emcken 2021-05-02T08:06:25.397500Z

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 Emcken 2021-05-02T08:11:43.397700Z

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 Emcken 2021-05-02T08:11:51.397900Z

thanks for your help

OrdoFlammae 2021-05-01T18:24:54.393300Z

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

1👍
dpsutton 2021-05-01T18:25:27.393800Z

There’s a var for that

dpsutton 2021-05-01T18:25:47.394400Z

Check out m-x apropos toplevel

OrdoFlammae 2021-05-01T18:30:08.394600Z

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?

dpsutton 2021-05-01T18:30:56.394800Z

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

dpsutton 2021-05-01T18:31:37.395Z

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

lilactown 2021-05-01T18:44:39.395200Z

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

2➕
awb99 2021-05-01T19:14:16.396100Z

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

awb99 2021-05-01T19:15:06.396400Z

(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)