Fork me on GitHub
#beginners
<
2021-07-20
>
zackteo03:07:33

Hello I'm getting a bit confused with js interop again may I ask what L.Polygon(latlngs).bindPopup('Hi There!').addTo(map); is equivalent to syntax wise ?

phronmophobic03:07:01

I would probably write something like:

(-> (L/Polygon latlngs) 
    (.bindPopup "Hi there") 
    (.addTo map))

phronmophobic03:07:07

actually, cljs might require:

(-> L
    (.Polygon latlngs) 
    (.bindPopup "Hi there") 
    (.addTo map))

zackteo03:07:14

Okay let me try 🙂 I somehow always feel clojurescript interop is much tougher than java interop

jaju04:07:45

Did you get it to work? What did you try?

zackteo04:07:48

Am doing react-leaflet and got what I wanted to do to work for now ...

[:> GeoJSON
    ;; [:> Popup "test"]
    {:data sites
     ;; :color "#ffffff"
     :onEachFeature (fn [feature layer]
                      (do (.bindPopup layer "test")
                          (js/console.log ;; (.. layer -feature -properties)
                            layer))

                      ;; (.bindPopup (leaflet.) "hi")
                      )
     :eventHandlers {:click #(js/console.log %)}}]

👍 2
zackteo04:07:02

But do you by any chance understand how this might be done?

function MyComponent() {
  const map = useMap()
  console.log('map center:', map.getCenter())
  return null
}

function MyMapComponent() {
  return (
    <MapContainer center={[50.5, 30.5]} zoom={13}>
      <MyComponent />
    </MapContainer>
  )
}
I only know how to do this part
[:> MapContainer
 {:center [50.5 30.5] :zoom 13}]

jaju04:07:51

I’m guessing you probably mean to ask about children components (in this case, MyComponent) Something like this should work

[:> MapContainer
 {:center [50.5 30.5] :zoom 13}
 [:> MyComponent]
 ;; You can add as many children as you wish
]

jaju04:07:37

TBH - you may need to try some variations to get the right syntax, but this is essentially hiccup - multiple children, nested children - these typically work as you’d expect, save for some JS interop nuances.

zackteo04:07:20

How do I create MyComponent exactly 😮

jaju04:07:33

Oh wait - I was under the impression you are looking to use some existing JS from CLJS. To clarify - is your question how you’d do everything in CLJS?

zackteo04:07:00

I think my questions is how does the syntax of <MyComponent> as well as its creation as a function get translated to cljs

jaju05:07:20

Ok - your examples suggest you are already using reagent MyComponent has no visual part to it. useMap doesn’t seem to refer to any pre-existing state. You may probably want to explain the purpose of MyComponent some more?

zackteo04:07:02

But do you by any chance understand how this might be done?

function MyComponent() {
  const map = useMap()
  console.log('map center:', map.getCenter())
  return null
}

function MyMapComponent() {
  return (
    <MapContainer center={[50.5, 30.5]} zoom={13}>
      <MyComponent />
    </MapContainer>
  )
}
I only know how to do this part
[:> MapContainer
 {:center [50.5 30.5] :zoom 13}]

zackteo07:07:27

What's a more idiomatic way to use the function map inside the function map

Dongwook Kim07:07:58

(->> (map #(+ 1 %) [1 2 3])
     (map #(* 2 %))
something like this? I'm not sure, it's idiomatic way

zackteo07:07:43

right think that makes things a bit better 🙂

jaju07:07:31

map keeps one-to-one correspondence, so a comp may be a good option to use

(->> [1 2 3] (map (comp #(* 2 %) #(+ 1 %))))

zackteo08:07:26

Yeap! Okay!

Sebastian12:07:29

I am a newbie developer. This might not be as clojure specific and more of a design question,: I want to separate my business logic and persistence logic into two namespaces. Currently its a mix. I have a namespace (lets call it ns1) that calls some upsert functions in another namespace (ns2). However, these functions in ns2 contain business logic, checks and validation and also upserts data into the database. This is a lot of responsibility of a single function, therefore i want to split them out. My idea was to create an additional namespace and basically have all data access happen in that. So ns1 will call ns2 which handles all the business logic and validation of the data and then calls ns3 which actually inserts, upserts, fetches the data. Does this sound like a solid idea? Another problem is the naming of these functions. Currently all functions in ns2 are named something like "upsert-placeholder-into-db" But when i remove the upsert functiontionality from ns2 into ns3, what would i call the ns2 function then? From the perspective of ns1 it would look weird that i call some "handle-placeholder" function when all i really want in n1 is to just insert the data. Maybe i am overthinking this. Sadly i cant' show you any of the code

Jon Boone12:07:15

Hi @U01GQRC8W30 — this is, as you suspected, not a strictly Clojure related question. May I ask what purpose the functions in ns-1 serve?

dgb2312:07:37

think of your names as fully qualified. it helps you to find good names. Say you define a dbnamespace. then db/insert is a sufficiently descriptive name, so you just say (def insert …)

Jon Boone12:07:45

Are the json files received over http?

dgb2312:07:17

ns2 here would be something like model I think

dgb2312:07:05

that would be a traditional name for code that handles validation, marshalling and buisness logic on top of data base records.

dgb2312:07:54

you can then say model/insert and db/insert! where the former is just a function and the latter does the actual transaction. But that is just an example to showcase how the namespace belongs to the name.

Jon Boone13:07:12

I’d recommend reading this article about Clojure web app frameworks: https://purelyfunctional.tv/mini-guide/what-web-framework-should-i-use-in-clojure/

👍 2
dgb2313:07:03

not necessarily. there is a common design principle in clojure to avoid side effects and state. so ns2 would just be functions from data->data. ns3 would do the side effects.

dgb2313:07:48

this way you can lift the state up, make it visible

zackteo13:07:01

Hello, I am using clojure.java.shell/sh to get my clojure backend to execute a python script and using :out (as in the print) to get the output. Previously, while perhaps not the most ideal option, this has worked for simpler outputs However, I currently have a script that prints out some initialisation and takes awhile - under a min to a few minutes to finish printing. This causes clojure.java.shell/sh to return before my script has completed. Is there a way to approach this?

noisesmith14:07:52

ProcessBuilder is easy to use, it returns an outputstream or outputs to a file instead of giving you a string directly though something like: (-> (ProcessBuilder. ["python" "-flag" "myfile.py"]) (.start) (.waitFor)) gives basic execution

noisesmith14:07:38

this version shouldn't be hard to adapt for python:

(let [pb (ProcessBuilder. ["lua"])
      p (.start pb)
      out (.getOutputStream p)
      in (.getInputStream p)]
  (spit out "print \"hello from lua\"\n")
  (slurp in))

noisesmith14:07:13

(it also demonstrates sending real time input to the process, you could even interact while the process runs based on its output...)

jaju13:07:41

Here’s what I’d guess - the stdout isn’t flushed on program end, which leaves some of the output hanging. Depending on what python function you are using to print, try ensuring stdout flush as the last step before end?

zackteo14:07:19

You mean I should find a way to withhold output until everything is finished ?

dgb2314:07:20

what does :exit have in it?

👍 2
zackteo14:07:29

wait I think you are right .... I am getting an output cause my script has issues

jaju14:07:27

Please share what you find.

zackteo14:07:27

oh as in :exit is 1. And realised my script was encountering errors and hence was returning ... let me fix my script first

👍 2
Apple14:07:49

how to get [:a :c :a :c :a] given ((fn _) [3 :a :c])?

dpsutton14:07:18

how does [3 :a :c] translate to [:a :c :a :c :a] i would understand i think if there was another :c at the end. and you want the arguments repeated 3 times

Apple14:07:08

my clumsy onee: (butlast (interleave (repeat 3 :a) (repeat 3 :c)))

noisesmith15:07:13

(apply concat (take %1 (cycle %&))) I think

noisesmith15:07:37

oh yeah, the lack of :c at the end makes this one fail

dgb2315:07:15

I don’t think its clumsy at all

dpsutton15:07:20

(defn g [n & items]
  (butlast (into [] cat (repeat n items))))
can handle arbitrary number of items. (g 3 :a :b :c) etc

dpsutton15:07:06

but i think your version was fine if you know its only two arguments

Apple15:07:33

thank you both!

zackteo15:07:59

Hello, how do I read a vector of python dictionaries as string. Like [{'a': 'test' , 'b': 'test}, {'b' : 'test'}, {'c' : 'test'}] in clojure?

indy15:07:54

Convert Python dictionaries that you have as string to a vector of Clojure hashmaps? Is my understanding correct?

indy15:07:59

You'll have to roll your own parser or use something like https://github.com/Engelberg/instaparse

indy15:07:10

There is also https://github.com/clj-python/libpython-clj if you want to do the conversion of data structures residing in memory rather than reading from a file

indy15:07:31

Or convert to an intermediary format (a conversion that you trust) like JSON and read that into Clojure

zackteo16:07:18

I formatted it to edn and used edn/read-string just need to do some key to keyword conversion i guess

indy16:07:02

Oh I thought you would be reading a lot of these, didn't know it was a one-off use case 😅

zackteo16:07:08

It is a fixed python script I am running and processing into my clojure backend i guess

zackteo16:07:50

Is there a good way to convert/rename keys as strings to keywords

zackteo16:07:06

Thanks! I only knew of the latter option 🙂

zackteo16:07:59

Yeap keywordize-keys is exactly what i was looking for!

Rob Haisfield19:07:10

(#(re-seq #".md" %) "what.md")
I’m trying to get the part that is not .md

Rob Haisfield19:07:29

My naive pseudo-code implementation would be this, but it doesn’t work

(#(re-seq (not #".md") %) "what.md")

Jo Øivind Gjernes14:07:07

(first (str/split "what.md" #"\.md"))

Rob Haisfield19:07:42

How do I get the parts that aren’t .md?

seancorfield19:07:32

@U02108ERRU5 Like this you mean?

dev=> (second (re-find #"(.*)\.md" "what.md"))
"what"

Rob Haisfield19:07:28

Awesome, thank you!

ghadi19:07:57

@U02108ERRU5 are you using the REPL?

Rob Haisfield19:07:36

@U050ECB92I am using the REPL. Why do you bring it up?

Rob Haisfield19:07:14

(def test ["what.md" "test.md" "sup.md"])

(map second (map re-find #"(.*)\.md" test))
Okay now I’m trying to extend that function to a list of strings and it’s not working, I’m not sure what Im doing wrong

seancorfield19:07:08

(map second (map #(re-find #"(.*)\.md" %) test))

Rob Haisfield20:07:48

Okay that works for the list… so @U04V70XH6, what am I missing? Why does that work and what I did at first not work?

dpsutton20:07:17

take a string that you are saying it's not working on and try it in the repl. (re-find #(.*)\.md "some-string.markdown") or whatever and see what it returns

seancorfield20:07:28

Because (map re-find #"(.*)\.md" test) is calling map with three arguments as if it were (map func coll1 coll2)

seancorfield20:07:22

Which is not the same as (map #(func coll1 %) coll2)

dpsutton20:07:55

oh right 🙂 that

seancorfield20:07:04

Try (map vector [1 2 3] [4 5 6]) and (map #(vector [1 2 3] %) [4 5 6]) and you'll see the difference.

Rob Haisfield20:07:04

Ohhhh okay that makes sense, thank you for the explanation

leif19:07:09

If I have some namespace A, that provides some function f, and I want to make a new namespace B that provides the same function, what would the best way to go about it be?

leif19:07:53

Right now I can imagine:

(ns B
  (:require [A]))
(def f A/f)
But is there a better way?

seancorfield19:07:10

You'll lose metadata on f doing that. I guess the question is: why do you want to do this?

seancorfield19:07:24

(re-exporting vars from nses is a bit of a code smell, IMO)

leif19:07:45

The short answer is because I have to. The longer answer is because in this case, module B isn't actually written in clojure(script), but happens to satisfy the namespace protocol.

leif19:07:22

But because I want the effect of the code analyzer, I want to reprovide it from another module that is written in clojurescript.

leif19:07:57

If I have to, I can also write full blown wrapper functions to reify error checking done by B/f

leif19:07:09

I'd just be nice to not have to.

seancorfield20:07:27

As long as you don't care about metadata, (def f A/f) is probably sufficient. If you do care, you'll need something fancier that copies across the metadata into the B ns... but I'm not sure what that would look like in ClojureScript.

leif20:07:10

Eh, okay, thanks. Since B is sort of side-loaded into my environment there isn't any metadata (so it has to be provided by A anyway), so thanks. 🙂

Rob Haisfield21:07:06

(defn find-name-in-name [name1 name2]
  (re-seq (re-pattern name1) name2)) ; okay so this works

(find-name-in-name "GIF" "animated GIF for GuidedTrack")
I’m trying to figure out how to make it so if name1 appears in name2, it will return name2. Currently, the function just returns name1. Any advice?

Rob Haisfield21:07:29

I figured it out!

(defn find-name-in-name-experiment [name1 name2]
  (if (not (nil? (re-find (re-pattern name1) name2)))
    name2
    nil))

seancorfield21:07:13

(and (re-find (re-pattern name1) name2) name2)

seancorfield21:07:46

Or (when (re-find (re-pattern name1) name2) name2) if you prefer.

seancorfield21:07:13

(if (not (nil? x)) y z) is just (if x y z) BTW

seancorfield21:07:38

(except when x is false -- but in this case they'd be the same)

WWeeks23:07:50

What is a good way to get started using clojure with powershell scripts?

seancorfield23:07:08

@wme.weeks Can you elaborate? I'm not quite sure what you're asking...

seancorfield23:07:36

Do you mean "How can I install Clojure so I can use it from the Powershell command-line?" -- if so, try https://github.com/clojure/tools.deps.alpha/wiki/clj-on-Windows

sova-soars-the-sora23:07:58

Or is this a java shell interop question?