Fork me on GitHub
#beginners
<
2021-05-13
>
arielalexi08:05:36

Hey everyone 🙂 I was wondering is there an easy way to convert a project that was created with a project.clj file (the project was created with leiningen ) to dep.edn project?

stagmoose08:05:23

- Hi, recently I am trying to use [react-flow](https://github.com/wbkd/react-flow) in my project and I am really new to cljs 😢. - I am using shadow-cljs in my project and I've install the npm package using npm install react-flow-renderer and put (:require ["react-flow-renderer" :default ReactFlow]) in my core.cljs file - But for the next step I tried to implement this demo in [ React Flow - Overview Example](https://reactflow.dev/examples/) page yet didn't know how to start. - In that example page, I know I should probably represent the array of data objects in initial-elements.js using [ js-obj ](https://cljs.github.io/api/cljs.core/js-obj) (am I correct ? :rolling_on_the_floor_laughing:) - But next, in the index.js , how could I wrap jsx syntax in cljs, for example , this part:

return (
    <ReactFlow
      elements={elements}
      onElementsRemove={onElementsRemove}
      onConnect={onConnect}
      onLoad={onLoad}
      snapToGrid={true}
      snapGrid={[15, 15]}
    >
      <MiniMap
        nodeStrokeColor={(n) => {
          if (n.style?.background) return n.style.background;
          if (n.type === 'input') return '#0041d0';
          if (n.type === 'output') return '#ff0072';
          if (n.type === 'default') return '#1a192b';

          return '#eee';
        }}
        nodeColor={(n) => {
          if (n.style?.background) return n.style.background;

          return '#fff';
        }}
        nodeBorderRadius={2}
      />
      <Controls />
      <Background color="#aaa" gap={16} />
    </ReactFlow>
  );
- Is there anyone have relevant experience or know how to solve this problem. Thanks in advance! 🍻

Adrian Smith12:05:05

Could probably use reagent to replicate those jsx components using cljs data structures

stagmoose13:05:13

@UCJCPTW8J Thanks for your kind reply. This is my attempt to translate but it didn't work.

stagmoose13:05:19

(ReactFlow {:elements elements
             :style graph-styles}))
I believe the problem come from this part but haven't figure out how to solve it.

stagmoose13:05:11

This is my browser's warnings. Thanks again 🙏

stagmoose14:05:41

Update: I finally got to solve it by using :> in reagent

Endre Bakken Stovner12:05:19

I am trying to translate the following calls to cljs:

var g = new dagre.graphlib.Graph();
g.setGraph({});
g.setDefaultEdgeLabel(function() { return {}; });
g.setNode("kspacey",    { label: "Kevin Spacey",  width: 144, height: 100 });
My attempt:
(let [g (dagre/graphlib.Graph.)
        _ (g.setGraph (js->clj {}))
        _ (g.setDefaultEdgeLabel (js->clj #(fn [] {})))
        _ g.setNode("kspacey",    { label: "Kevin Spacey",  width: 144, height: 100 });
It fails with

Jakob Durstberger12:05:43

This might be helpful https://lwhorton.github.io/2018/10/20/clojurescript-interop-with-javascript.html#function-invocation The way to invoke functions is `([func-name] [target] parms) and js->clj us used to convert javascript types into clojure types. You probably want the opposite clj->js I think this should be closer. not sure about the dare/graphlib.Graph though

(let [g (dagre/graphlib.Graph.)
        _ (.setGraph g (clj->js {}))
        _ (.setDefaultEdgeLabel g (fn [] {}))

Endre Bakken Stovner12:05:28

D'oh, I meant the other way around. cljs->js.

Endre Bakken Stovner12:05:33

Thanks for the link.

Jakob Durstberger12:05:01

I’d probably pull the setGraph setDefaultEdgeLabel and setNode into the let body. And you can use -> and thread the calls like so

(-> g
  (.setGraph (clj->js {}))
  (.setDefaultEdgeLabel (fn [] {})))

Endre Bakken Stovner12:05:17

The above worked, thanks!

Jakob Durstberger13:05:14

:thumbsup: no worries 🙂

Endre Bakken Stovner12:05:54

Any tips? Also, is this a question more suited for #clojurescript?

Endre Bakken Stovner12:05:39

Note that I am not trying to use the g object in the hiccup. I am just trying to create it in a let.

Edward Ciafardini12:05:09

Hey there - I am trying to use clojure to separate an integer of variable length (ie 15_5_212518674225 => 1-5-5-2-1-2-5-1-8-6-7-4-2-2-5) into two separate vectors splitting every other number. The int would turn into this after the split: [1 5 1 5 8 7 2 5] and [5 2 2 1 6 4 2] .

yuhan14:05:20

(loop [n 155212518674225 xs () ys ()]
  (if (zero? n)
    [xs ys]
    (recur (quot n 10) (cons (rem n 10) ys) xs)))
;; => [(1 5 1 5 8 7 2 5) (5 2 2 1 6 4 2)]

Endre Bakken Stovner12:05:25

Probably not pretty but:

(let [n 155212518674225 n-str (str n)]  [(take-nth 2 n-str) (take-nth 2 (rest n-str))]) ;; [(\1 \5 \1 \5 \8 \7 \2 \5) (\5 \2 \2 \1 \6 \4 \2)]

Jakob Durstberger12:05:45

I think that’s not too bad. My first idea was way worse 😄 You’d probably have to convert the characters back to integers

(let [n 155212518674225
      n-str (str n)
      nums (map #(Integer/valueOf (str %)) n-str)]  
  [(take-nth 2 nums) (take-nth 2 (rest nums))])

👍 3
R.A. Porter14:05:49

Yours are much shorter and simpler than mine, certainly...

(let [n 155212518674225]
    (->> n
         str
         (partition 2 2 [\x])
         (apply map vector)
         (map #(filter #{\0 \1 \2 \3 \4 \5 \6 \7 \8 \9} %))
         (map #(map str %))
         (map #(map (fn [x] (Integer/parseInt x)) %))
         (map vec)))

puercopop14:05:39

I'm looking for the equivalent of macrolet for cljs. I found clojure/tools.macro but it only seems to be for clojure not clojurescript.

orpheus14:05:20

Hello everyone. How do I use the repl to call a function and use it’s result (an access token) in other functions? In bash I call a login function and save the accessToken to a variable I can use in my other rest calls, what’s the clojure-idiomatic way to do this? I’d like to be able to call (login environment) and then have my following calls use the accessToken from that login result

emilaasa15:05:56

If I was just messing around in the REPL exploring some api, I'd do (def access-token (login environment)) and use the access-token directly, that would define a var which is a global variable inside that namespace.

emilaasa15:05:46

When running production code it might be more likely that I had the token as an environment variable and used System/getenv to pull in the variable, possibly in a let block instead to limit it's scope.

emilaasa15:05:08

Doing something like: export YOUR_TOKEN=topsecret lein repl Will make your token avaliable with (System/getenv "YOUR_TOKEN")

orpheus15:05:28

I’ll give it a shot thank you!

orpheus16:05:39

@U6T7M9DBR in a production environment if you had to hit another server to get a accessToken, how would you save that variable for use in other rest calls? in this scenario it couldn’t be an env variable because it needs to be fetched

madstap17:05:20

You could use an atom to store it:

(def access-token (atom nil))

(reset! access-token (login environment))

(do-something @access-token)

🙌 3
emilaasa17:05:38

@U01JYKT6ENL depends - does it need to be renewed under the runtime of the program?

orpheus17:05:06

yeah during runtime, it’ll need to be changed/updated depending on the service I now want to hit

emilaasa17:05:04

Maybe you can stay immutable and not change/update it and make your life easier?

orpheus17:05:29

Hm.. I’d like to stay as functional as possible but I want to be able to target different service endpoints on demand. To do that I need the access token for each service-environment. If I were to stay purely functional, I’d have to call login before each request I make which is way too much overhead.

B Treebeard15:05:38

Hello everyone. Why does this snippet

(->> ["A" "B" "C"]
     (map #(println %))
     ((fn [x]
        (println "Done!"))))
produce this output?
Done!
nil
I.e., why aren’t A, B and C printed out?

B Treebeard15:05:26

(I’m only looking for some hints so that I can figure out what to Google to understand this behaviour better.)

dpsutton15:05:02

map is lazy. there's nothing realizing that sequence. the only thing that happens to it is that it's passed to a function, ignored, and "Done!" is printed. So nothing cares about the lazy sequence so it doesn't do any work

B Treebeard15:05:19

Ah, of course! Thanks!

B Treebeard15:05:44

And now…

(->> ["A" "B" "C"]
     (mapv #(println %))
     ((constantly (println "Done!"))))
gives me
Done!
A
B
C
nil

B Treebeard15:05:56

Why does the Done! turn up first? :thinking_face:

B Treebeard15:05:15

Presumably it’s something to do with constantly as with ((fn [x] (println "Done!"))) I get the “expected” order in the output.

dpsutton15:05:46

(constantly (println "Done"!)) will evaluate it's argument, a println which returns nil, and you end up with a function that takes arbitrary input and returns nil

B Treebeard15:05:32

Ah, the println within the constantly is being evaluated when the function that will be returned is being generated. That makes sense, thanks again. 👍

evocatus18:05:31

Hi! I'm playing with my own stupid merge sort implementation. And while mesuring performance I noticed a huge difference depending on how I generate numbers. this (repeatedly 1000000 (partial rand-int 1000000)) is 70000x slower than

(def N 1000000)
(repeatedly N (partial rand-int N))

evocatus18:05:09

a list comprehension (for [_ (range N)] (rand-int N)) is as slow as the first expression I mentioned

dpsutton18:05:25

repeatedly returns a lazy sequence. so most likely you are doing 70000x less work and seeing that take that much less time 🙂

dpsutton18:05:51

or realizing the sequence in some cases and not in others

evocatus18:05:23

but the first and second expressions are IDENTICAL except for using predefined constant or not

evocatus18:05:02

and the time difference I mentioned applies to clojure.core/sort too, not my function only

dpsutton18:05:33

what exact forms are you running in the repl?

dpsutton18:05:38

user=> (time (do (repeatedly N (partial rand-int N)) nil))
"Elapsed time: 0.022722 msecs"
nil
user=> (time (do (repeatedly 1000000 (partial rand-int 1000000)) nil))
"Elapsed time: 0.022792 msecs"
nil
these behave more or less identically for me, and they are very quick as i'm constructing a lazy sequence and not realizing any of it

evocatus18:05:57

sorry for bothering you, I can't reproduce the time difference anymore

evocatus18:05:20

but it was there

dpsutton18:05:21

you're most likely seeing the differences in the cached lazy sequence and realizing it.

dpsutton18:05:00

so sort will realize all of v and then sort it, the other sorts will benefit from having a cached lazy sequence and just do their sorting, rather than computing all of the random numbers and then sorting

evocatus18:05:36

but I call time not on combined function but on each sort method separately

evocatus18:05:56

and I called it several times changing the let form parameter

evocatus18:05:24

and the first function in list - clojure.core/sort produced such different timings

dpsutton18:05:04

yes. because the first time you access a lazy sequence you have to compute the items in it. subsequent accesses to it use the already computed values

dpsutton18:05:00

(let [coll (map #(do (Thread/sleep 1000) %) (reverse (range 4)))]
  (time (sort coll))
  (time (sort coll))
  (time (sort coll)))
"Elapsed time: 4014.109926 msecs"
"Elapsed time: 0.008128 msecs"
"Elapsed time: 0.004072 msecs"
(0 1 2 3)

evocatus18:05:15

I see now, thanks

evocatus18:05:44

I was puzzled because I was changing the source code and evaluating the changed version

evocatus18:05:52

does REPL intern such things?

evocatus18:05:47

my REPL output changes from yours - I have close times with both subsequent function calls inside the let form

dpsutton18:05:06

i'm not following

dpsutton18:05:24

can you post the output?

evocatus18:05:00

it's right above yours output

evocatus18:05:17

the result of evaluating the let form twice

dpsutton18:05:49

oh evaluating the left form twice. if you are creating a new lazy seq every time it will be computed every time

👍 3
Geoffrey Gaillard19:05:57

Hello! I'm wondering how to disable clojure.test tests in prod mode. The idiomatic way seems to not include the test folder in the classpath using an alias. But I have a technical constraint that some tests are co-located with the source code. Is there a way to set clojure.test/*load-tests* to false from deps.edn, and ensuring it during AOT compilation?

dpsutton19:05:35

Are your tests running or you just don’t want to define them?

hiredman19:05:37

The best attack will be on the constraint that forces you to put tests and source in the same place

hiredman19:05:14

Putting those in separate folders is common practice in clojure and I can't think of another language where that isn't how projects are layed out, maybe C?

Noah Bogart19:05:55

we do it with typescript at my job (thing.ts, thing.test.ts, thing.spec.ts). i hate it, but i don't get to make that decision, lol.

dpsutton19:05:05

I think Rust has support for same file tests. it's actually quite nice.

hiredman19:05:00

sure, you can even do it in clojure, I just mean conventionally most projects don't

dpsutton19:05:11

yeah. i think it might be a convention in Rust

dpsutton19:05:07

> However, because unit tests go in the same files as the code

hiredman19:05:40

so whatever "technical constraint" there is that is forcing you to co-locate them is likely a misunderstanding or a soft constraint

Geoffrey Gaillard20:05:56

I'd be happy to discuss the technical constraint, it's an interesting one, but since addressing the constraint itself is not an option I'd prefer to make it another thread :)

hiredman20:05:37

ok, I'll bite, what is the constraint

Geoffrey Gaillard20:05:11

I agree the constraint is odd, but I don't have control over it. It's a complex design choice with subtle implications. Targeting the constraint seems the best approach at first, but it's just not possible. Tests should not be defined in prod mode. When clojure.test/*load-tests* is false , deftest expands to nil. I just want to find a practical way to set it to false from clojure cli, deps.edn or a similar way. Is there a way to do so?

seancorfield20:05:06

How are you running your code in production?

Geoffrey Gaillard20:05:34

Using clj with a -main

seancorfield20:05:57

Any reason you’re not building an uberjar and running it just using java -jar in production?

Geoffrey Gaillard20:05:15

No reason so far, it could perfectly be done with an uberjar.

Geoffrey Gaillard20:05:37

And probably should

dpsutton20:05:46

you can achieve this with an appropriate -e call right?

dpsutton20:05:21

i wonder if there would be interest in that being initialized from a jvm property as well

Geoffrey Gaillard20:05:39

If -e has the right precedence it might work, I'll give it a try. How would the jvm property map to *load-tests*? Should I read the property from my -main and set *load-tests* accordingly?

dpsutton20:05:49

if the dynamic var was initialized to some jvm property otherwise true. No i'm musing about a change i might suggest on ask.clojure

Geoffrey Gaillard20:05:38

Ah! I'm allowed to wrap deftest in a custom macro. So my-deftest could read this property and expand to clojure.test/deftest or nil accordingly. This is another approach I might try.

dpsutton20:05:49

deftest is already that macro

Geoffrey Gaillard20:05:37

But is decides to expand or not on *load-tests*

seancorfield20:05:14

If you decide to switch to an uberjar, depstar has a mechanism for a “custom compile” function, so you could provide your own function that invokes compile inside a binding of *load-tests*.

seancorfield20:05:06

(but I would strongly advise “fixing” the root cause here and arranging for your tests to be in a separate tests folder tree instead of mixed in with your src)

Geoffrey Gaillard20:05:46

This is interesting and seems clean! I'll check depstar. I'll communicate more about the root cause and use case in the near future. @dpsutton @hiredman @nbtheduke and @seancorfield thank you very much for your help and kind advices. I think it unblocked me and I'll be able to move forward.

👍 3
ramseyst21:05:35

Hello Clojure wizards, please forgive my Clojure baby-talk. Does anyone know how to define a reflexive relation in core.logic? I can define a simple asymmetric relation like this:

(ns logictest.core
  (:gen-class))

(require '[clojure.core.logic.pldb :as pldb])
(require '[clojure.core.logic :as l])
(pldb/db-rel thing t)
(pldb/db-rel relation x y)
(def facts (pldb/db [thing 'a] [thing 'b] [relation 'a 'b]))
When I try to run pldb code to ask the question "what thing is related to 'b"?,
(pldb/with-db facts (l/run* [foo] (relation foo 'b)))
pleasingly, I get back 'a:
(a)
but when I run this form to try to ask "what thing is related to 'a,
(pldb/with-db facts (l/run* [foo] (relation foo 'a)))
I get (). But I would like to define relation to be symmetric. Is there a way to do that? I tried to study the code for pldb/db-rel to see if there is a hidden option to make a relation reflexive, but it is a bit beyond me, at my novice level of Clojure.

hiredman21:05:43

the way to do that is a conde in your logic program

🙌 3
ramseyst21:05:44

thank you!!!

hiredman21:05:40

(pldb/with-db facts
  (l/run* [foo]
    (l/conde
     [(relation foo 'a)]
     [(relation 'a foo)])))

ramseyst21:05:29

You are the best! This works!

(defn in-symmetric-pair [relation x y] (l/conde [(relation x y)] [(relation y x)]))
(pldb/with-db facts (l/run* [foo] (in-symmetric-pair relation foo 'a)))

ramseyst21:05:45

Thanks so much.

vinurs23:05:43

i have a vector like this [[1 2] [ 6 4]] is there a simple function that can add 1 and 6, and 2 with 4, then generate [7 6]

phronmophobic23:05:53

> (apply map + [[1 2] [ 6 4]])
(7 6)
seems to work

Juλian (he/him)12:05:22

be aware that it returns a list instead of a vector